zoukankan      html  css  js  c++  java
  • 文件监控性能问题【BUG】

    文件监控性能问题【BUG】

    背景:JAVA写了一个文件夹目录监控的程序,使用的是org.apache.commons.io.monitor 包,项目稳定运行了一个月,现场反馈,文件夹数据处理越来越慢,等到数据推送到前端要好几分钟,于是开始了寻找问题的路程。

    监控代码

    之前写的文件监控代码

    问题发现

    我在ApplicationRunner的实现类中重写了run方法,打印了日志

        @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 监听中也是发现大概三分钟才能发现一批新数据,这就是导致数据推送不及时的原因。

    在发现问题过后,我仔细想了下文件监控的原理,到底是怎么来监控文件的呢,找了下源码看了下,果然,是循环处理所有文件。FileAlterationObserver中的checkeNotify()方法,就是获取所有的文件,然后进行一个个的判断。

     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);
            }
    
        }
    

    分析问题

    问题出现的原因:由于程序在处理了文件之后,并没有将文件进行删除处理,而是将数据移动到当前目录的子目录中,但是子目录依旧在程序监控的根目录下,这就导致根目录下的数据量越来越大,进而引发了项目文件监控处理一次需要三分钟,也就是说会随着文件数据量的逐渐增加,处理一次需要的时间也会逐渐增加,最终会导致程序崩溃。

    解决方案

    1.在处理完文件之后,将文件删除。

    2.处理完文件之后,将文件移动到不在监控文件夹下

    BUG感悟

    不是所有的bug在本地都可以复现,在线上出现问题的时候,不要怀疑是偶然情况,预定难以解决的问题的时候,先大致分析下问题所在,找不到问题原因就打日志,缩小问题范围,结合源码进行分析。

  • 相关阅读:
    shell 字符串替换
    shell 拆分字符串成数组 放入数组
    shell 换行输出变量 换行
    Linux shell修改xml文件
    Spark 实现共同好友
    Hive 开启 service2 服务
    hive 求相互是好友.
    Linux 查看外网ip
    Termux下开启kex远程桌面
    Termux开启ssh服务
  • 原文地址:https://www.cnblogs.com/chengzhihua/p/14297123.html
Copyright © 2011-2022 走看看