背景:JAVA寫了一個文件夾目錄監控的程序,使用的是org.apache.commons.io.monitor 包,項目穩定運行了一個月,現場反饋,文件夾數據處理愈來愈慢,等到數據推送到前端要好幾分鐘,因而開始了尋找問題的路程。html
我在ApplicationRunner的實現類中重寫了run方法,打印了日誌java
@Override public void run(ApplicationArguments applicationArguments) throws Exception { log.info("監聽開始"); // 輪詢間隔 1 秒 long interval = TimeUnit.SECONDS.toMillis(1); // 建立過濾器 IOFileFilter directories = FileFilterUtils.and( FileFilterUtils.directoryFileFilter(), HiddenFileFilter.VISIBLE); IOFileFilter files = FileFilterUtils.and( FileFilterUtils.fileFileFilter(), FileFilterUtils.suffixFileFilter(fileEnd)); IOFileFilter filter = FileFilterUtils.or(directories, files); // 使用過濾器 FileAlterationObserver observer = new FileAlterationObserver(new File(baseDataSyncDir), filter); observer.addListener(new FileMonitor()); //建立文件變化監聽器 FileAlterationMonitor monitor = new FileAlterationMonitor(interval, observer); // 開始監控 monitor.start(); log.info("監聽開始{}",baseDataSyncDir); }
本地調試,秒打印兩行日誌,可是放到現場運行,這兩行日誌相差三分鐘,在以後的fileCreate 監聽中也是發現大概三分鐘才能發現一批新數據,這就是致使數據推送不及時的緣由。apache
在發現問題事後,我仔細想了下文件監控的原理,究竟是怎麼來監控文件的呢,找了下源碼看了下,果真,是循環處理全部文件。FileAlterationObserver中的checkeNotify()方法,就是獲取全部的文件,而後進行一個個的判斷。app
public void checkAndNotify() { Iterator var1 = this.listeners.iterator(); while(var1.hasNext()) { FileAlterationListener listener = (FileAlterationListener)var1.next(); listener.onStart(this); } File rootFile = this.rootEntry.getFile(); if (rootFile.exists()) { this.checkAndNotify(this.rootEntry, this.rootEntry.getChildren(), this.listFiles(rootFile)); } else if (this.rootEntry.isExists()) { this.checkAndNotify(this.rootEntry, this.rootEntry.getChildren(), FileUtils.EMPTY_FILE_ARRAY); } Iterator var5 = this.listeners.iterator(); while(var5.hasNext()) { FileAlterationListener listener = (FileAlterationListener)var5.next(); listener.onStop(this); } }
問題出現的緣由:因爲程序在處理了文件以後,並無將文件進行刪除處理,而是將數據移動到當前目錄的子目錄中,可是子目錄依舊在程序監控的根目錄下,這就致使根目錄下的數據量愈來愈大,進而引起了項目文件監控處理一次須要三分鐘,也就是說會隨着文件數據量的逐漸增長,處理一次須要的時間也會逐漸增長,最終會致使程序崩潰。ide
1.在處理完文件以後,將文件刪除。性能
2.處理完文件以後,將文件移動到不在監控文件夾下this
不是全部的bug在本地均可以復現,在線上出現問題的時候,不要懷疑是偶然狀況,預約難以解決的問題的時候,先大體分析下問題所在,找不到問題緣由就打日誌,縮小問題範圍,結合源碼進行分析。調試