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