太极限了,JDK的这个BUG都能被我踩到

本文讲述了作者在处理文件监听变更时遇到的一个JDK BUG,该BUG可能导致无法精确感知文件变更。作者介绍了WatchService的原理,并发现其在某些JDK版本下同样存在问题。接着探讨了Linux的inotify机制,以及如何在Java中利用它来避免JDK的BUG。最后,文章分享了故障的修复方案和一些技术思考。
摘要由CSDN通过智能技术生成

之前遇到个文件监听变更的问题,刚好这周末有空研究了一番,整理出来分享给大家。

从一次故障说起

我们还是从故障说起,这样更加贴近实际,也能让大家更快速理解背景。

有一个下发配置的服务,这个配置服务的实现有点特殊,服务端下发配置到各个服务的本地文件,当然中间经过了一个agent,如果没有agent也就无法写本地文件,然后由client端的程序监听这个配置文件,一旦文件有变更,就重新加载配置,画个架构图大概是这样:

今天的重点是文件的变更该如何监听(watch),我们当时的实现非常简单:

  • 单独起个线程,定时去获取文件的最后更新时间戳(毫秒级)
  • 记录每个文件的最后更新时间戳,根据这个时间戳是否变化来判断文件是否有变更

从上述简单的描述,我们能看出这样做有一些缺点:

  • 无法实时感知文件的变更,感知误差在于查询文件最后更新时间的间隔
  • 精确到毫秒级,如果同一毫秒内发生2次变更,且轮询时刚好落在这2次变更的中间时,后一次变更将无法感知,但这概率很小

还好,上述两个缺点几乎没有什么大的影响。

但后来还是发生了一次比较严重的线上故障,这是为什么呢?因为一个JDK的BUG,这里直接贴出罪魁祸首:

BUG详见:
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8177809

在某些JDK版本下,获取文件的最后更新时间戳会丢失毫秒精度,总是返回整秒的时间戳,为了直观感受,写了个demo分别在 jdk1.8.0_261 和 jdk_11.0.6 测试(均为MacOs):

  • jdk_1.8.0_261
  • jdk_11.0.6

如果是在这个BUG的影响下,只要同一秒内有2次变更,且读取文件最后时间戳位于这2次变更之间的时间,第2次变更就无法被程序感知了,同1秒这个概率比同一毫秒大的多的多,所以当然就被触发了,导致了一次线上故障。

这就好比之前是沧海一粟,现在变成了大海里摸到某条鱼的概率。这也能被我们碰到,真是有点极限~

WatchService—JDK内置的文件变更监听

当了解到之前的实现存在BUG后,我就去搜了一下Java下如何监听文件变更,果然被我找到了 WatchService 。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值