精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

太極限了,JDK的這個(gè)Bug都能被我踩到

開發(fā) 前端
如果是在這個(gè)BUG的影響下,只要同一秒內(nèi)有2次變更,且讀取文件最后時(shí)間戳位于這2次變更之間的時(shí)間,第2次變更就無法被程序感知了,同1秒這個(gè)概率比同一毫秒大的多的多,所以當(dāng)然就被觸發(fā)了,導(dǎo)致了一次線上故障。

hello,大家好呀,我是小樓。

之前遇到個(gè)文件監(jiān)聽變更的問題,剛好這周末有空研究了一番,整理出來分享給大家。

從一次故障說起

我們還是從故障說起,這樣更加貼近實(shí)際,也能讓大家更快速理解背景。

有一個(gè)下發(fā)配置的服務(wù),這個(gè)配置服務(wù)的實(shí)現(xiàn)有點(diǎn)特殊,服務(wù)端下發(fā)配置到各個(gè)服務(wù)的本地文件,當(dāng)然中間經(jīng)過了一個(gè)agent,如果沒有agent也就無法寫本地文件,然后由client端的程序監(jiān)聽這個(gè)配置文件,一旦文件有變更,就重新加載配置,畫個(gè)架構(gòu)圖大概是這樣:

今天的重點(diǎn)是文件的變更該如何監(jiān)聽(watch),我們當(dāng)時(shí)的實(shí)現(xiàn)非常簡單:

  • 單獨(dú)起個(gè)線程,定時(shí)去獲取文件的最后更新時(shí)間戳(毫秒級)。
  • 記錄每個(gè)文件的最后更新時(shí)間戳,根據(jù)這個(gè)時(shí)間戳是否變化來判斷文件是否有變更。

從上述簡單的描述,我們能看出這樣實(shí)現(xiàn)有一些缺點(diǎn):

  • 無法實(shí)時(shí)感知文件的變更,感知誤差在于輪詢文件最后更新時(shí)間的間隔。
  • 精確到毫秒級,如果同一毫秒內(nèi)發(fā)生2次變更,且輪詢時(shí)剛好落在這2次變更的中間時(shí),后一次變更將無法感知,但這概率很小。

還好,上述兩個(gè)缺點(diǎn)幾乎沒有什么大的影響。

但后來還是發(fā)生了一次比較嚴(yán)重的線上故障,這是為什么呢?因?yàn)橐粋€(gè)JDK的BUG,這里直接貼出罪魁禍?zhǔn)祝?/p>

BUG詳見:https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8177809

在某些JDK版本下,獲取文件的最后更新時(shí)間戳?xí)G失毫秒精度,總是返回整秒的時(shí)間戳,為了直觀感受,寫了個(gè)demo分別在jdk1.8.0_261和jdk_11.0.6測試(均為MacOs):

  • jdk_1.8.0_261

  • jdk_11.0.6

如果是在這個(gè)BUG的影響下,只要同一秒內(nèi)有2次變更,且讀取文件最后時(shí)間戳位于這2次變更之間的時(shí)間,第2次變更就無法被程序感知了,同1秒這個(gè)概率比同一毫秒大的多的多,所以當(dāng)然就被觸發(fā)了,導(dǎo)致了一次線上故障。

這就好比之前是滄海一粟,現(xiàn)在變成了大海里摸到某條魚的概率。這也能被我們碰到,真是有點(diǎn)極限~

WatchService—JDK內(nèi)置的文件變更監(jiān)聽

當(dāng)了解到之前的實(shí)現(xiàn)存在BUG后,我就去搜了一下Java下如何監(jiān)聽文件變更,果然被我找到了WatchService。

說是WatchService可以監(jiān)聽一個(gè)目錄,對目錄下的文件新增、變更、刪除進(jìn)行監(jiān)聽。于是我很快就寫了個(gè)demo進(jìn)行測試:

public static void watchDir(String dir) {
Path path = Paths.get(dir);
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.OVERFLOW);
while (true) {
WatchKey key = watchService.take();
for (WatchEvent<?> watchEvent : key.pollEvents()) {
if (watchEvent.kind() == StandardWatchEventKinds.ENTRY_CREATE) {
System.out.println("create..." + System.currentTimeMillis());
} else if (watchEvent.kind() == StandardWatchEventKinds.ENTRY_MODIFY) {
System.out.println("modify..." + System.currentTimeMillis());
} else if (watchEvent.kind() == StandardWatchEventKinds.ENTRY_DELETE) {
System.out.println("delete..." + System.currentTimeMillis());
} else if (watchEvent.kind() == StandardWatchEventKinds.OVERFLOW) {
System.out.println("overflow..." + System.currentTimeMillis());
}
}
if (!key.reset()) {
System.out.println("reset false");
return;
}
}
} catch (Exception e) {
e.printStackTrace();

先對/tmp/file_test目錄進(jìn)行監(jiān)聽,然后每隔5毫秒往文件寫數(shù)據(jù),理論上來說,應(yīng)該能收到3次事件,但實(shí)際上很奇怪,仔細(xì)看接收到modify事件的時(shí)間大概是第一次文件修改后的9.5s左右,很奇怪,先記著,我們讀一下WatchService源碼:

>>> 1652076266609 - 1652076257097
9512

WatchService原理

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

通過debug發(fā)現(xiàn),這里的watchService實(shí)際上是PollingWatchService的實(shí)例,直接看PollingWatchService的實(shí)現(xiàn):

PollingWatchService上來就起了個(gè)線程,這讓我隱隱不安。再找一下這個(gè)scheduledExecutor在哪里用到:

每隔一段時(shí)間(默認(rèn)為10s)去poll下,這個(gè)poll干了什么?代碼太長,我截出關(guān)鍵部分:

果然,和我們的實(shí)現(xiàn)類似,也是去讀文件的最后更新時(shí)間,根據(jù)時(shí)間的變化來發(fā)出變更事件。

換句話說,在某些JDK版本下,他也是有BUG的!

這也就解釋了上文提到的事件監(jiān)聽為什么是在第一個(gè)9.5s之后才發(fā)出,因?yàn)楸O(jiān)聽注冊后,sleep了500ms后修改文件,10s輪詢,剛好9.5s后拿到第一輪事件。

inotify—Linux內(nèi)核提供的文件監(jiān)聽機(jī)制

至此,我想起了linux上的tail命令,tail 是在文件有變更的情況下輸出文件的末尾,理論上也是監(jiān)聽了文件變更,這塊剛好在很久之前聽過一個(gè)技術(shù)大佬分享如何自己實(shí)現(xiàn)tail命令,用到的底層技術(shù)就是inotify。

簡單來說,inotify是linux內(nèi)核提供的一種監(jiān)控文件變更事件的系統(tǒng)調(diào)用。如果基于此來實(shí)現(xiàn),不就可以規(guī)避JDK的BUG了嗎?

但奇怪的是為什么Java沒有用這個(gè)來實(shí)現(xiàn)呢?于是我又搜了搜,發(fā)現(xiàn)谷歌似乎有一個(gè)庫,但被刪了,看不到代碼:

github上又搜到一個(gè):https://github.com/sunmingshi/Jinotify。

看起來是一個(gè)native的實(shí)現(xiàn),需要自己編譯.so文件,這樣就比較蛋疼了。

記得上次這么蛋疼還是在折騰Java的unix domain socket,也是找到了一個(gè)google的庫,測試沒問題,放到線上就崩了~不得不說google還是厲害,JDK提供不了的庫,我們來提供!

于是我?guī)е@個(gè)疑問去問了一個(gè)搞JVM開發(fā)的朋友,結(jié)果他告訴我,Java也可以使用inotify!

瞬間斗志來了,難道是我測試的姿勢不對?

我又去翻了一遍Java文檔,發(fā)現(xiàn)在角落隱藏了這么一段話:

也就是說,不同的平臺(tái)下會(huì)使用不同的實(shí)現(xiàn),PollingWatchService是在系統(tǒng)不支持inotify的情況下使用的兜底策略。

于是將watchService的類型打印出來,在Mac上打印為:

class sun.nio.fs.PollingWatchService

在Linux上是:

class sun.nio.fs.LinuxWatchService

LinuxWatchService在Mac上是找不到這個(gè)類,我猜測應(yīng)該是Mac版的JDK壓根沒把這塊代碼打包進(jìn)來。

原來我本地測試都走了兜底策略,看來是測了個(gè)寂寞。

于是我寫了個(gè)demo再測試一把:

public static void main(String[] args) throws Exception {
Thread thread = new Thread(() -> watchDir("/tmp/file_test"));
thread.setDaemon(false);
thread.start();

Thread.sleep(500L);

for (int i = 0; i < 3; i++) {
String path = "/tmp/file_test/test";
FileWriter fileWriter = new FileWriter(path);
fileWriter.write(i);
fileWriter.close();
File file = new File(path);
System.out.println(file.lastModified());
Thread.sleep(5);
}
}
  • 本地Mac

  • Linux

可以看出,Linux上能收到的事件比本地多的多,而且接收事件的時(shí)間明顯實(shí)時(shí)多了。

為了更加準(zhǔn)確的驗(yàn)證是inotify,用strace抓一下系統(tǒng)調(diào)用,由于JVM fork出的子進(jìn)程較多,所以要加-f命令,輸出太多可以存入文件再分析:

strace -f -o s.txt java FileTime

果然是用到了inotify系統(tǒng)調(diào)用的,再次驗(yàn)證了我們的猜想。

故障是如何修復(fù)的?

再次回到開頭的故障,我們是如何修復(fù)的呢?由于下發(fā)的文件和讀取文件的程序都是我們可控的,所以我們繞過了這個(gè)BUG,給每個(gè)文件寫一個(gè)version,可以用文件內(nèi)容md5值作為version,寫入一個(gè)特殊文件,讀取時(shí)先讀version,當(dāng)version變化時(shí)再重新載入文件。

可能你要問了,為什么不用WatchService呢?

我也問了負(fù)責(zé)人,據(jù)說inotify在docker上運(yùn)行的不是很好,經(jīng)常會(huì)丟失事件,不是Java的問題,所有語言都存在這個(gè)問題,所以一直沒有使用。不過這塊找不到相關(guān)的資料,也無法證明,所以暫時(shí)擱置。

最后說幾句

有些BUG,不踩過就很難避免,代碼只要存在BUG的可能性,就一定會(huì)暴露出來,只是時(shí)間問題。

我們要在技術(shù)上深入探究,小心求證,但產(chǎn)品上不必執(zhí)著,可另辟蹊徑。

責(zé)任編輯:武曉燕 來源: 捉蟲大師
相關(guān)推薦

2024-10-09 09:07:10

JVM優(yōu)化String類JDK1.6

2020-07-20 09:40:49

MySQLBUG數(shù)據(jù)庫

2020-04-02 14:33:42

MySQLBUG解決方案

2022-05-27 07:03:04

JDK場景線程

2020-12-17 07:39:30

HashMap死循環(huán)數(shù)據(jù)

2022-11-11 15:49:41

MySQL隔離

2021-10-13 06:49:14

事故復(fù)盤ID

2022-02-23 11:47:57

CharlesFiddler抓包

2021-08-20 08:22:12

Tomcat原生線程池

2016-04-15 17:45:59

HPE存儲(chǔ)閃存

2021-09-25 13:05:10

MYSQL開發(fā)數(shù)據(jù)庫

2022-11-30 07:16:18

2020-04-27 09:40:43

開源項(xiàng)目 Bug

2019-05-13 09:01:13

程序員職責(zé)產(chǎn)品經(jīng)理

2022-06-21 11:24:05

多線程運(yùn)維

2021-08-31 15:19:16

美團(tuán)面試快排

2020-04-21 15:22:35

ChromeFirefox瀏覽器

2025-04-02 04:55:00

2021-12-27 18:28:28

Spring設(shè)計(jì)配置

2018-05-03 16:49:13

魅藍(lán)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

国产在线一区二区三区欧美| 欧美另类暴力丝袜| 嫩草影院国产精品| 欧美成人精品一区二区男人看| 国产精品亚洲综合一区在线观看| 久久久久国产精品免费| 免费看黄色的视频| 蜜桃精品视频| 色天使久久综合网天天| 日本一区二区三区四区五区六区| 偷拍自拍在线| 国产毛片精品国产一区二区三区| 欧美在线一区二区视频| 极品久久久久久| 国产一区二区三区不卡视频网站| 欧美一区二区三区四区五区| 欧美日韩在线中文| 在线免费观看a视频| 久久九九国产精品| 国产成人av一区二区三区| 丰满熟女人妻一区二区三| 亚洲电影av| 日韩一区二区av| 欧美特级黄色录像| 欧美a一欧美| 欧美一二三四区在线| 天天影视综合色| 周于希免费高清在线观看| 亚洲综合免费观看高清完整版在线 | 久久精品国产精品青草| 57pao国产成人免费| 久久久国产成人| 五月婷婷亚洲| 中文字幕亚洲字幕| 国产肥白大熟妇bbbb视频| 大香伊人久久精品一区二区| 欧美一二三区在线| 国内精品国产三级国产aⅴ久| 播放一区二区| 色妞www精品视频| 日韩欧美亚洲天堂| 国产精品vvv| 亚洲国产毛片aaaaa无费看| 无码毛片aaa在线| 日本www在线观看视频| 国产三区在线成人av| 欧美连裤袜在线视频| 污污的视频网站在线观看| 成人免费视频视频| 黑人另类av| 四虎永久在线观看| 91免费国产在线| 蜜桃成人在线| 国产精品毛片一区二区三区四区| 久久久久国产成人精品亚洲午夜| 免费99视频| 激情福利在线| 国产女同性恋一区二区| 视频一区视频二区视频| av电影在线播放高清免费观看| 国产欧美视频在线观看| 亚洲成人a**址| 免费在线你懂的| 亚洲男同性视频| 欧美大黑帍在线播放| caoporn-草棚在线视频最| 亚洲大尺度视频在线观看| 免费看国产曰批40分钟| av资源亚洲| 欧美性生活大片视频| 红桃视频 国产| 日韩精品一区国产| 亚洲国产毛片完整版| 亚洲欧美视频在线播放| 国产亚洲一区| 粗暴蹂躏中文一区二区三区| 国产午夜视频在线播放| 美女日韩在线中文字幕| 国产人妖伪娘一区91| 国产不卡av在线播放| av在线不卡观看免费观看| 蜜桃视频在线观看91| 91在线播放网站| 一区二区三区在线不卡| 北条麻妃在线观看| 伊人久久综合网另类网站| 欧美成人一区二区三区片免费| 国产精品第七页| 久久国产影院| 久久久久亚洲精品国产| 激情视频网站在线观看| 韩国三级中文字幕hd久久精品| 国产精品9999久久久久仙踪林| 欧美婷婷久久五月精品三区| 中文字幕一区二区三中文字幕| 久久艹国产精品| 99久久精品一区二区成人| 欧美r级电影在线观看| 亚洲精品成人无码熟妇在线| 国产精品黑丝在线播放| 68精品国产免费久久久久久婷婷 | 欧美日韩视频不卡| 最新版天堂资源在线| 欧洲乱码伦视频免费| 久久久久久久国产精品视频| 一本到在线视频| 99久久er热在这里只有精品66| 亚洲一区不卡在线| 中老年在线免费视频| 日韩美女一区二区三区四区| 天天躁日日躁aaaa视频| 在线日韩av| 成人亚洲激情网| jizzjizz在线观看| 欧美午夜无遮挡| 精品久久久久久无码人妻| 小说区图片区色综合区| 欧美激情小视频| 国产一区二区麻豆| 国产日韩欧美亚洲| 激情五月宗合网| 亚洲一区二区电影| 久久五月天综合| 中国精品一区二区| 久久久久久影视| 日韩欧美一区二| 一区二区三区四区高清视频| 日韩亚洲一区二区| 在线视频你懂得| 国产午夜精品一区二区三区四区| 亚洲人成无码网站久久99热国产| 精品国产亚洲一区二区三区在线| 一区二区中文字幕| 精品无码一区二区三区的天堂| 成人ar影院免费观看视频| 激情视频小说图片| 国产精品美女久久久久人| 日韩专区中文字幕| 国产又爽又黄免费软件| 国产精品午夜春色av| 国产av人人夜夜澡人人爽| 丝袜美腿一区二区三区动态图 | 丝袜美腿一区| 亚洲欧洲成视频免费观看| 国产 日韩 欧美 在线| 99热在这里有精品免费| 免费av观看网址| 欧美精品密入口播放| 91高清在线免费观看| 天天操天天干天天爽| 亚洲成人精品一区| 国产高清成人久久| 免费日韩av| 欧洲一区二区日韩在线视频观看免费 | 国产精品免费看片| 57pao国产成永久免费视频| 三区四区不卡| 92看片淫黄大片看国产片| 成人高清免费在线| 欧美电影免费提供在线观看| 国产无遮挡又黄又爽在线观看| 成人自拍视频在线| 欧美啪啪免费视频| 神马电影久久| 国产精品吴梦梦| 成人video亚洲精品| 精品久久久三级丝袜| 国产特黄大片aaaa毛片| 久久伊99综合婷婷久久伊| 毛片毛片毛片毛片毛片毛片毛片毛片毛片| 欧美精品羞羞答答| 亚洲综合在线小说| 妞干网免费在线视频| 国产亚洲美女久久| 国产麻豆免费观看| 黄色一区二区三区| 一级特黄曰皮片视频| 国产综合一区二区| 波多野结衣综合网| 成人直播大秀| 成人黄动漫网站免费| 美女一区网站| 久久久久北条麻妃免费看| 好吊视频一区二区三区| 一本高清dvd不卡在线观看| 黄色香蕉视频在线观看| 99re这里都是精品| 国产色视频在线播放| 亚洲第一网站| 一区不卡字幕| 欧美大片网址| 91视频国产一区| 国产乱码精品一区二三赶尸艳谈| 亚洲偷熟乱区亚洲香蕉av| www.xxxx国产| 欧美午夜精品一区| 精品成人久久久| 亚洲欧美综合色| aa片在线观看视频在线播放| 黄色小说综合网站| 日本在线视频www| 欧美日本一区| 亚洲一区二区三区加勒比 | 亚洲日本精品| 巨人精品**| 成人黄色生活片| 欧美三级精品| 午夜精品久久久久久久99热| 日本www在线观看| 亚洲香蕉成人av网站在线观看| 高清一区二区三区四区| 欧美顶级少妇做爰| 伊人久久久久久久久久久久| 亚洲国产精品天堂| 国产传媒免费在线观看| 中文字幕不卡在线播放| 日b视频在线观看| 成人一区在线观看| 一区二区三区四区毛片| 日本91福利区| 成人午夜视频免费在线观看| 99热免费精品| www插插插无码视频网站| 一区二区三区在线电影| 亚洲一区二区三区在线观看视频 | 国产成人日日夜夜| 九九热99视频| 久久99精品视频| www.欧美日本| 久久综合九色| 成人一级片网站| 亚洲视频1区| 日韩伦理在线免费观看| 亚洲一级黄色| 日本一本中文字幕| 国产在线成人| 成人精品中文字幕| 欧美一二三视频| h片在线观看| 欧美激情亚洲自拍| 好吊日av在线| 97色在线播放视频| av资源中文在线| 午夜精品久久久久久久久久久久| 欧洲精品二区| 国外成人性视频| 9999热视频在线观看| 91精品国产91久久| 日韩av一卡| 国产成人综合av| 亚洲电影有码| 国产主播欧美精品| 国产日韩欧美中文在线| 亚洲在线第一页| 综合中文字幕| 久久riav二区三区| 欧美男同视频网| 午夜一区二区三视频在线观看| 精品视频久久| 欧美h视频在线观看| 欧美一区国产在线| 欧美久久久久久久久久久久久| 夜夜嗨网站十八久久| 国内外成人免费激情视频| 日韩—二三区免费观看av| 手机av在线免费| 国产成人综合亚洲91猫咪| 理论片大全免费理伦片| 久久久噜噜噜久久人人看| 国产精品酒店视频| 亚洲精品视频一区二区| 国语对白一区二区| 一本一本大道香蕉久在线精品| 成人免费一区二区三区| 欧美一区二区性放荡片| 国模私拍视频在线| 中国日韩欧美久久久久久久久| 成人影院在线观看| 26uuu亚洲国产精品| 欧美风情在线视频| 国产精品三区四区| 日韩夫妻性生活xx| 国产日本在线播放| 免费成人小视频| 国产精品手机在线观看| 国产欧美一区二区精品性| 精品99在线观看| 欧美亚洲动漫另类| 亚洲第一天堂网| 一夜七次郎国产精品亚洲| 美女日批视频在线观看| 国产精品美女在线观看| jizz18欧美18| 伊人婷婷久久| 国产美女诱惑一区二区| 国产在线观看中文字幕| 久久久亚洲精品石原莉奈| 中文字幕另类日韩欧美亚洲嫩草| 欧美日韩精品在线视频| 国产日韩免费视频| 亚洲日韩欧美视频| 另类视频在线| 91精品国产自产在线观看永久| 国产福利一区二区精品秒拍| 伊人色综合影院| 老色鬼久久亚洲一区二区| 国产乱淫av麻豆国产免费| 中文字幕巨乱亚洲| 午夜影院在线看| 日韩欧美久久久| 日本www在线观看视频| 国产99久久精品一区二区| 国产精品中文字幕制服诱惑| 欧美爱爱视频网站| 日韩高清不卡一区| 丰满少妇高潮一区二区| 亚洲午夜久久久久| 91久久久久久久久久久久| 亚洲色图偷窥自拍| 欧美少妇网站| 国产成人精品日本亚洲11| 伊人久久大香线| wwwwwxxxx日本| 国产精品青草久久| 999视频在线| 亚洲偷欧美偷国内偷| 精品国产免费人成网站| 久久久av水蜜桃| 亚洲精一区二区三区| 久久久精品人妻一区二区三区| 亚洲欧洲三级电影| 一本色道久久综合无码人妻| 在线视频中文亚洲| 久久天堂av| 日本10禁啪啪无遮挡免费一区二区| 销魂美女一区二区三区视频在线| 国产精品手机在线观看| 亚洲大片精品永久免费| 日本精品999| 91精品国产一区| 免费精品国产| av动漫免费看| 国产亚洲婷婷免费| 中文字幕手机在线视频| 亚洲欧洲一区二区三区久久| 另类激情视频| 视频在线精品一区| 美女视频网站久久| 五月天av网站| 欧美一区二区三区在线视频| bestiality新另类大全| av一区二区三区四区电影| 亚洲国产精品第一区二区三区 | 99麻豆久久久国产精品免费| 免费看日韩毛片| 亚洲精品一区中文| 日韩精品免费观看视频| 亚洲日本japanese丝袜| 国产在线不卡一区| 久久人人爽人人爽人人| 精品福利av导航| 欧美特大特白屁股xxxx| 日日夜夜精品网站| 国产一区二区三区日韩| 久久影院一区二区| 亚洲精品98久久久久久中文字幕| 亚洲一二三四| 亚洲一区不卡在线| 成人美女视频在线看| 精品免费囯产一区二区三区| 中文字幕欧美日韩va免费视频| www.成人| 国产二区视频在线播放| 中文字幕第一页久久| 亚洲精品久久久久久动漫器材一区| 久久精品欧美一区二区三区不卡| 91视频免费网址| 国产一区二区三区丝袜| 国产精品亚洲欧美一级在线 | 国精产品视频一二二区| 日韩一区二区视频在线观看| 91视频欧美| 亚洲一区二区免费视频软件合集| 国产成人免费视频网站高清观看视频| 九九热在线免费观看| 久久久国产精品亚洲一区| 久久porn| 日本黄色的视频| 欧美午夜xxx| av激情在线| 欧美日韩在线一二三| 国产在线播放一区三区四| 在线天堂中文字幕| 久久久精品一区二区| 亚洲aaa级| 午夜视频在线免费看| 欧洲精品一区二区三区在线观看| 欧美黄色视屏| 亚洲人成网站在线观看播放 | 91精品国产综合久久精品app|