V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yuyuyu
V2EX  ›  Node.js

nodejs+docker 内存泄露问题

  •  
  •   yuyuyu · 2017-03-23 13:38:29 +08:00 · 4326 次点击
    这是一个创建于 2839 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我有一个 centos 的容器里面运行的是 pm2-docker ,然后 pm2-docker 运行了一个 nodejs 程序,现在时不时会出现系统内存被吃光的问题,看 top 里 node 的内存占用 10%左右, pm2 list 看启动的 nodejs 程序也只有 100M 左右,实际系统已经被吃掉 90%的内存开始出现性能警告了,只要我重启下这个容器,系统内存就降下来正常了,这种情况是什么造成了内存泄露?我写的 nodejs 么?

    27 条回复    2018-04-11 10:53:39 +08:00
    hpeng
        1
    hpeng  
       2017-03-23 13:48:19 +08:00 via iPhone
    一般来说是的,你可以 docker 启动限制容器内存
    yuyuyu
        2
    yuyuyu  
    OP
       2017-03-23 13:55:05 +08:00
    @hpeng 我是想找出内存泄露,限制内存重启容器都不是解决方法……
    xujialiang
        3
    xujialiang  
       2017-03-23 13:57:44 +08:00
    那你试试不要用 pm2 docker ,我容器跑 nodejs ,貌似没发生这种问题。
    yuyuyu
        4
    yuyuyu  
    OP
       2017-03-23 14:00:11 +08:00
    @xujialiang 我试试 , google 过 nodejs 内存相关的东西,都是 top 和 pm2 list 就能看到内存暴涨,但我这里的情况是 top 和 pm2 list 看内存占用都非常正常,比较迷
    unclechan
        5
    unclechan  
       2017-03-23 15:37:09 +08:00
    有可能是 pm2 本身占用内存过多,我以前遇到过 pm2 莫名占用 cpu 很高的问题,不知道是不是 bug
    chairuosen
        6
    chairuosen  
       2017-03-23 15:41:28 +08:00
    我遇到过 pm2 自己 cpu 太高崩掉的问题,发现是 0.10node 时装的 pm2 跑在 6.几 node 里导致的,更新了 Pm2 就好了
    WildCat
        7
    WildCat  
       2017-03-23 15:43:29 +08:00
    既然用 docker 了,最佳实践应该直接启动 node app 而不是用 pm2 吧?
    (新手
    WildCat
        8
    WildCat  
       2017-03-23 15:43:37 +08:00
    (我是新手
    otakustay
        9
    otakustay  
       2017-03-23 15:43:41 +08:00
    用 top 看内存正常说明这些内存已经和 node 这个进程无关了,就算用 profile 都查不出来,只能瞎猜了,先去掉 pm2 看看能不能正常,不行再去掉几个功能模块半分法找?
    yuyuyu
        10
    yuyuyu  
    OP
       2017-03-23 15:52:18 +08:00
    @unclechan
    @chairuosen

    我没有去掉 pm2 ,在执行 docker exec web pm2 restart all 以后内存恢复正常……大概还是我的程序有问题吧

    @otakustay

    我也找不到其他占用内存多的程序……那泄露的内存就完全看不到到哪去了?

    我现在试试 heapdump
    fyibmsd
        11
    fyibmsd  
       2017-03-23 16:30:14 +08:00
    docker 里为啥还要用 pm2
    otakustay
        12
    otakustay  
       2017-03-23 18:57:55 +08:00
    @fyibmsd pm2 深入进程的监控能提供很多操作系统层面拿不到的信息
    yuyuyu
        13
    yuyuyu  
    OP
       2017-03-23 19:53:10 +08:00 via Android
    @otakustay 能详细说说么
    yuyuyu
        14
    yuyuyu  
    OP
       2017-03-23 21:38:14 +08:00
    通过 heapdump 收集了内存快照,在内存暴涨的时候, heapdump 出来的快照最多也就 22M ,里面最大的 shallow size 也只有几 M ,引用的包就这些:
    ```
    "dependencies": {
    "babel-runtime": "6.x.x",
    "bluebird": "3.3.5",
    "heapdump": "^0.3.7",
    "log4js": "^0.6.37",
    "mysql": "^2.11.1",
    "sequelize": "^3.23.3"
    },
    ```
    对,用了 babel+bluebird ,然后程序里很多 await
    denghongcai
        15
    denghongcai  
       2017-03-23 22:36:55 +08:00
    你是不是跑在 docker 里打日志了? docker 版本多少?
    yuyuyu
        16
    yuyuyu  
    OP
       2017-03-23 22:41:59 +08:00
    @denghongcai
    确实会打日志 Docker 版本 Docker version 1.13.1, build 092cba3
    yuyuyu
        17
    yuyuyu  
    OP
       2017-03-23 22:47:47 +08:00
    @denghongcai 我只是直接通过 console.log 输出日志
    mooncakejs
        18
    mooncakejs  
       2017-03-23 23:24:28 +08:00 via iPhone
    echo 1 > /proc/sys/vm/drop_caches 可以释放掉。应该是内存碎片吧
    yuyuyu
        19
    yuyuyu  
    OP
       2017-03-23 23:26:06 +08:00
    @mooncakejs 试了下内存丝毫没变, 2 、 3 也试过
    mooncakejs
        20
    mooncakejs  
       2017-03-23 23:46:37 +08:00 via iPhone
    @yuyuyu 在宿主机里使用的?
    mooncakejs
        21
    mooncakejs  
       2017-03-23 23:47:09 +08:00 via iPhone
    @yuyuyu 我碰到过吃内存的情况。宿主机里可以清掉
    yunshansimon
        22
    yunshansimon  
       2017-03-24 00:21:03 +08:00
    nodejs 如果创建了独立的子进程,子进程内有 listener 之类的,它不会在完成任务后主动关闭,需要父进程发信号关闭。如果父进程在关闭自己的子进程之前就被关闭了,子进程就变成孤单的进程了,它会自己运行,谁都不属于,被占的内存也不会被释放。因此,必须在创建子进程的父进程内建立子进程列表,在父进程关闭前,向所有子进程发送强制关闭的消息。所以,子进程就跟名字一样,谁生的,谁必须负责到底。
    yuyuyu
        23
    yuyuyu  
    OP
       2017-03-24 08:23:13 +08:00 via Android
    @mooncakejs 嗯,是在宿主机执行的
    yuyuyu
        24
    yuyuyu  
    OP
       2017-03-24 08:27:01 +08:00 via Android
    @yunshansimon 但是我这没有创建任何子进程,整个程序很简单就一个 httpserver ,然后会执行 http.request 去请求数据返回给客户端,就是业务内部的一个 http 中转程序
    denghongcai
        25
    denghongcai  
       2017-03-27 09:53:05 +08:00
    Node 进程内存占用不大,但是 Docker 进程占用大吧

    把 console.log 改成向文件输出日志,在 Docker 容器了往 stdout 打日志会内存泄露,我时常碰到,但是每次 Docker 那边都没修好
    yuyuyu
        26
    yuyuyu  
    OP
       2017-03-27 10:39:44 +08:00
    @denghongcai 没有, docker 进程内存也正常,没有哪个进程占用很大的内存,都挺正常的,给我的感觉就是内存消失了……然而只要重启 nodejs 的那个容器内存就回来了,打日志的我也去掉了,问题依旧
    lyzlyz
        27
    lyzlyz  
       2018-04-11 10:53:39 +08:00
    请问这个问题解决了吗?我跟你遇到了一摸一样的问题,也是 docker 中使用 pm2 运行 nodejs,内存会缓慢的上升直到 100%
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1099 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 19:23 · PVG 03:23 · LAX 11:23 · JFK 14:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.