推荐学习书目
› Learn Python the Hard Way
Python Sites
› PyPI - Python Package Index
› http://diveintopython.org/toc/index.html
› Pocoo
值得关注的项目
› PyPy
› Celery
› Jinja2
› Read the Docs
› gevent
› pyenv
› virtualenv
› Stackless Python
› Beautiful Soup
› 结巴中文分词
› Green Unicorn
› Sentry
› Shovel
› Pyflakes
› pytest
Python 编程
› pep8 Checker
Styles
› PEP 8
› Google Python Style Guide
› Code Style from The Hitchhiker's Guide
cs8814336
V2EX  ›  Python

nginx + django + uwsgi + python2.7 如何排查内存泄露.

  •  2
     
  •   cs8814336 · Mar 11, 2019 · 5826 views
    This topic created in 2803 days ago, the information mentioned may be changed or developed.
    背景:
    该项目功能比较多, 而且在不同机房部署了多个实例, 但是只有其中一个机房的使用出现了明显的内存泄露(因为功能比较多,不同机房用的功能或者着重用的功能不一样). 发现问题是通过访问出现了 500,然后上服务器 top 发现了 uwsgi 多个进程占用比较大的内存,最大一个占用了 20% (8g 内存), 累积起来用满了内存和交换空间.


    求助: 如何有一种比较通用的内存泄露排查方法来定位到源码行.

    优先不考虑通过修改源码重启后收集内存对象的方法.(什么 objgraph 工具之类) 因为这种感觉不太适用于其他语言, 而且需要重启破坏掉现场,需要等待下次触发.

    已经有的思路:

    想通过查看具体分配堆地址看具体内容, 猜测是哪部分的功能.但是还在踩坑中.
    通过 gdb --pid [pid] attach 进程, 然后 shell pmap [pid] 查看分配内存,定位到一个 anno 的比较大的内存,然后
    x/big number address 来取得内存地址内容

    感觉大家的回答.
    Supplement 1  ·  Mar 22, 2019
    时隔多天之后, 再次搜索这个问题, 发现一个很好的工具 pyrasite.

    能生成 payload 监听一个随机端口, 然后通过远程线程注入代码的方式注入到该进程让进程执行然后连接到这个随机端口,接下来可以像 python cmd 互动式操作. (就是一个黑客里面的反向 shell)

    安装后使用过程有一点曲折, 但是躺过了没啥问题, 接下来可以用 objgraph 等库进行远程注入. 然后发现只能看到某个类型的占用的最大, 具体到定位到源码行还有一定的差距.

    通过 import gc; gc.garbage 发现是空的, 这是证明我不存在回收不了的对象吗? 但是内存还是很高,问题待查
    Supplement 2  ·  Mar 29, 2019
    import gc;
    gc.garbage 是显示 垃圾回收器不能回收的对象,例如__del__.

    通过 pyrasite 导出内存的对象(有每个对象的地址,大小, 假如是字符串的话就会直接有字符串的值), 发现 unicode 对象较多, 通过 linux shell 命令 sort 和 uniq 字符串的值,
    发现我某个频繁请求的接口输出的日志内存占用很多.(那个是拿任务的接口 ,客户端定时 10s 一次过来请求, 使用的是 http 短连接. 同时我对于每个接口都有一个装饰器包住,用来执行解密和日志输出,所以每个接口都有日志):
    serverinterface_logger = logging.getLogger("default")
    dump_string = func(request, *args, **kwargs)
    serverinterface_logger.info("resp! descrypt:%s, request.url: %s, method: %s,body: %s, resp_before_encrypt: %s" % (settings.ENCRYPT, request.get_full_path(), request.method, request.body, dump_string)) -----此行打印的日志占用内存较高.

    但是,思考觉得这种应该会很容易被回收,尽管频率很高.

    ===========

    接下来为了使用 tracemalloc 把 django1.9 python2 升级到 django1.11 python3 (具体来说是一个能兼容 python3,python2 运行环境的版本) (可以通过编译 pyhon2 来达到使用 tracemalloc, 但是我觉得 py3 是迟早的,所以趁着这个机会升级), 查看分配内存最高的行代码 ,验证了上述代码行的确分配内存最高.

    现在 python2 升级 python3 跑到正式环境出了点问题, 所以暂且只能用 python2 跑新版本, 等 bugs 修完就再次排查
    Supplement 3  ·  Dec 27, 2019
    原因最后因为 debug_toolbar 的 bug 导致的: https://blog.csdn.net/u012087220/article/details/103716134
    12 replies  •  2019-12-27 10:33:25 +08:00
    aikuzhenyan
    aikuzhenyan
    Mar 11, 2019
    1
    建议上 gunicorn
    cs8814336
    cs8814336
    OP
    Mar 11, 2019
    2
    @aikuzhenyan 恩,早有所闻,但是这个问题的话恐怕上什么应该也会重现的, 所以想要一个通用的方法来排查以后和现在的这种类似的内存泄露问题
    qqxx520
    qqxx520
    Mar 11, 2019 via iPhone
    3
    uwsgi 有个参数,处理完一定数量的请求之后就重启一次
    cs8814336
    cs8814336
    OP
    Mar 11, 2019
    4
    @qqxx520 感谢回答. 恩,我知道的, 假如是 uwsgi 的问题, 当然这个是完美解决的. 恐怕大几率是代码问题, 这样的话我更倾向于从根本上解决问题而不是临时解决.
    jingxyy
    jingxyy
    Mar 11, 2019
    5
    查完了分享一下内存泄露的原因呗~
    Ehco1996
    Ehco1996
    Mar 11, 2019
    6
    看一下依赖,是不是用了什么 c 库,一般都是这个原因
    simple2025
    simple2025
    Mar 11, 2019
    7
    这个时间就有点羡慕 golang 的 go tool 了,python 里面就没有类似的吗?
    cs8814336
    cs8814336
    OP
    Mar 20, 2019
    9
    时隔多天之后, 再次搜索这个问题, 发现一个很好的工具 pyrasite.

    能生成 payload 监听一个随机端口, 然后通过远程线程注入代码的方式注入到该进程让进程执行然后连接到这个随机端口,接下来可以像 python cmd 互动式操作. (就是一个黑客里面的反向 shell)

    安装后使用过程有一点曲折, 但是躺过了没啥问题, 接下来可以用 objgraph 等库进行远程注入. 然后发现只能看到某个类型的占用的最大, 具体到定位到源码行还有一定的差距. 现在还在查实
    cs8814336
    cs8814336
    OP
    Mar 20, 2019
    10
    @Ehco1996 里面没有自己写的 c 库
    cs8814336
    cs8814336
    OP
    Dec 26, 2019
    11
    已解决
    cs8814336
    cs8814336
    OP
    Dec 27, 2019
    12
    总结文章,大家有兴趣可以看下 https://blog.csdn.net/u012087220/article/details/103716134
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1224 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 39ms · UTC 17:31 · PVG 01:31 · LAX 09:31 · JFK 12:31
    ♥ Do have faith in what you're doing.