WatchService 简单使用

简介

WatchService
看作是文件监控器,通过操作系统原生文件系统来运行。
针对单点多appkey的情况,可以注册开启多个监控器。
每个监控器可看作是后台线程,通过监控文件发出的信号来实现监控。


实现方法

  • WatchService 用来观察被注册了的对象所有的变化和事件
  • Watchable 被观察者,与WatchService结合使用, java.nio.file.Path 已经实现

WatchService 实例化

WatchService watchService = FileSystems.getDefault().newWatchService();

利用 Path 实例化监控对象 Watchable

Path dir = Paths.get(path);

将 Path 注册到 WatchService 中

//这里监控文件的 创建、修改、删除  但是这里返回的key里面的监控信息为空
WatchKey key = dir.register(watchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);   

WatchKey:该文件节点所绑定的监控信息池,当文件发生变化时所有的变化信息都会被导入监控池。

⚠️注意:监控池是静态的,只有当你主动去获取新的监控池时才会有更新的内容加入监控池。这就造成了系统接收到监控信息事件可能稍长的问题。

WatchKey 代表监听服务的注册,被用来获取事件的属性。
获取事件的方法:

for(;;)
key = watchService.poll();    //尝试获取下一个变化信息的监控池,如果没有变化则返回null


//another fun
key = watchService.take();    // 尝试获取下一个变化信息的监控池,如果没有变化则一直等待

如果需要长时间一直监控要用take,而如果只是在某个指定的时间监控则用poll
获取更新的监控信息其实需要当前Java进程和操作系统进程之间进行交流,返回的WatchKey是当前Java程序的(内存空间位于当前Java程序中)

人为或者是外部写日志操作会引起一系列的变化:

//获取监控信息
while((key = watchService.take()) != null)


//利用 key.pollEvents() 方法返回一系列的事件列表 List> list
for (WatchEvent event: key.pollEvents()) {
    //得到 监听的事件类型
    WatchEvent.Kind kind = event.kind();
    //得到 监听的文件/目录的路径
    Path pathName = (Path) event.context();


    //每次的到新的事件后,需要重置监听池
    key.reset();
}




//创建 test.log 后保存
ENTRY_CREATE: Documents/work/watchtest/.test.log.swp
ENTRY_MODIFY: Documents/work/watchtest/.test.log.swp
ENTRY_CREATE: Documents/work/watchtest/test.log
ENTRY_DELETE: Documents/work/watchtest/.test.log.swp

key.reset();方法
每次take()\poll()操作都会导致线程监控阻塞,每次操作文件可能需要长时间,如果监听目录下有其他事件发生,将会导致事件丢失。
重置操作表示重启该线程,后续的事件都会被读到。

关闭监听池服务

key.cancel();

提示信息缓慢的情况修正:

//原:
WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
//修改: 提高灵敏度,提示速度明显增加
WatchKey key = dir.register(watcher, new WatchEvent.Kind[]
        {StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_CREATE,
        StandardWatchEventKinds.ENTRY_DELETE}, SensitivityWatchEventModifier.HIGH);

适用:
大多数文件系统对文件进行修改的时候支持通知本机,当文件系统不支持这种机制的时候,监视器服务将轮训文件系统,等待事件。


测试

本地:
启动WatchService监控服务,递归创建监听池:根目录下所有的子目录都会被注册为新的监听器 (模拟agent采集目录:www/watchtest/appkey/*.log)
树形目录

.../watchtest/  --- appkey1 --- 269files
                --- appkey2 --- 337files
                --- appkey3 --- 290files
                --- appkey4 --- 248files
                --- appkey5 --- 258files

开始的时候只注册监听池 watchtest
随后依序创建 appkey1-5,新监听池也随即被创建
每个appkey目录下创建.log文件,总数为 1402

使用命令:
java Pid GC.heap_dump 得到dump.hprof

监听程序对 包括文件、文件夹在内的1407个文件进行监听,CUP占用峰值为 1%
实例占用2.8% ,大小 接近40000B,1.3%

你可能感兴趣的:(Java)