zoukankan      html  css  js  c++  java
  • 从零开始搞监控系统(4)——内存泄漏

      在将监控日志的服务独立部署后,还是发现CPU会在不特定时间段(例如21~22、23~02等)飙到70%,内存也是一路飙升不会下降,明显是出现了内存泄漏。

      

      

      需要进一步做优化,于是开通了阿里云的 Node.js 性能平台

    一、Node.js性能平台

      要使用此工具需要在自己的服务器中安装些组件的,具体步骤参考官网说明,公司运维操作起来蛮快的,下图是平台中的数据趋势。

      

      点击堆快照,就会生成一个*.heapsnapshot文件,通过该文件就能查看内存的分布和使用情况,点击下图中的转储就能查看分析了。

      

       但是我怎么点,每次都是失败,后面找了阿里云的技术人员,他说是因为文件太大,下载的时候总是会断开,无奈,只能在服务器上手动下载,然后在本地Chrome中加载了。

    二、分析

      在该平台上下载了堆快照(*.heapsnapshot文件),在Chrome的Memory选项卡中载入,可以看到下图内容。

      

    1)任务队列(Kue.js)

      翻看其中的几列,发现内存中滞留了很多队列任务的数据,于是锁定内存暴涨与队列有关。

      然后开始查代码,并且在本地做了调试,发现在任务完成后没有将其标记为成功,因为声明的那个改变状态的函数没有被执行。

      只有标记成功的任务才会被自动清除,由于状态没有更新,导致滞留在内存中,从而使得内存一直在涨而不会降。

      一顿操作猛如虎,但是最后发布上去后,内存并没有降下来,依然在增长中,说明不是这个问题。

      在创建队列任务时会打条日志,然后在完成任务后,会再打一条日志,发现一分钟内会创建大约4、5百个任务,但是完成的任务只有200个,甚至更少。

      也就是出队的速度没有入队快,队列来不及处理任务。如此下去的话,就会将任务堆积在一起。

      马上为队列处理的方法加了个并发的参数,再用LoadTest模拟并发,效果非常理想,任务有条不紊地被处理了,于是发布了代码。

      若要结束并发测试,mac电脑可执行命令 kill -USR2 36155,其中 36155 是端口号。

      

      但高兴的还是太早,虽然为队列加了并发的设置,但滞留的任务并没有减少,猜想可能是任务中的逻辑阻塞了任务的完成,继续将耗时逻辑注释掉,内存并没有如预期那样降下来。

      再次分析,感觉是上面配置的并发没有生效,很奇怪,查看Kue.js源码也没看出个所以然来。

      只能另辟蹊径了,也就是多创建几种类型,但处理的逻辑是一样的,以此来弥补任务队列的吞吐量。

    for (let i = 1; i <= 3; i++) {
      const taskName = "handleMonitor" + i;
      queue.process(taskName, (job, done) => {
        services.common
          .handleMonitor(job.data.monitor)
          .then(() => {
            done();
          })
          .catch((err) => {
            done(err);
          });
      });
    }

      查看日志,发现队列的入和出已经平衡,但是内存仍然会升,没有降的趋势。

    2)继续分析

      再次观察堆快照,我一度怀疑是 SequelizeKOA 或 Node.js 8.0版本的问题,翻来覆去的查,虽然的确看到了内存泄漏的蛛丝马迹,但仍然没有起色。

      后面将两份堆快照做对比,在查看增长的数据时,发现我请求的 ma.gif 路径中的变量不会释放,存在着一个闭包,八成是这个原因导致内存一直涨。

      

      于是仔细查看代码,将最可疑的一句代码注释掉,如下所示,省略了其他逻辑,就放出了关键的那句代码,为外部的 queue 对象反复注册了一个error事件。

    import queue from "../util/queue";
    router.get("/ma.gif", async (ctx) => {
      queue.on('error', function( err ) {
        logger.trace('handleMonitor queue error', err);
      });
    });

      没想到内存一下子平稳了,没有出现暴增的情况。一波多折后发现,原来是自己写的代码不对导致内存的泄漏。

      

    参考资料:

    Node.js 内存管理和 V8 垃圾回收机制

    Loadtest库做负载测试

    Memory Usage Bug

    4类 JavaScript 内存泄漏及如何避免

    Node.js 调试指南

    有意思的 Node.js 内存泄漏问题

  • 相关阅读:
    【乱侃】How do they look them ?
    【softeware】Messy code,some bug of Youdao notebook in EN win7
    【随谈】designing the login page of our project
    【web】Ad in security code, making good use of resource
    SQL数据库内存设置篇
    关系数据库的查询优化策略
    利用SQL未公开的存储过程实现分页
    sql语句总结
    sql中使用cmd命令注销登录用户
    SQLServer 分页存储过程
  • 原文地址:https://www.cnblogs.com/strick/p/14754867.html
Copyright © 2011-2022 走看看