侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Erlang项目内存泄漏分析方法

技术  /  管理员 发布于 7年前   142

随着项目越来越依赖Erlang,碰到的问题也随之增加。前段时间线上系统碰到内存高消耗问题,记录一下troubleshooting的分析过程。线上系统用的是Erlang R16B02版本。

问题描述

有几台线上系统,运行一段时间,内存飙升。系统模型很简单,有网络连接,pool中找新的process进行处理。top命令观察,发现内存都被Erlang进程给吃完了,netstat命令查看网络连接数,才区区几K。问题应该是Erlang内存泄漏了。

分析方法

Erlang系统有个好处,可以直接进入线上系统,在生产现场分析问题。我们系统是通过Rebar管理的,可以用不同方法进入线上系统。

本机登录

可以直接登录到线上机器,然后通过以下命令attach到Erlang系统里面
复制代码 代码如下:
$ cd /path/to/project
$ rel/xxx/bin/xxx attach
(node@host)>

通过remote shell

获取Erlang系统的cookie
复制代码 代码如下:
$ ps -ef |grep beam  %%找到参数 --setcookie

新开一个shell,使用同样的cookie,不同的nodename
复制代码 代码如下:
$ erl --setcookie cookiename -name [email protected]

用start remote shell进入系统
复制代码 代码如下:
Erlang R16B02 (erts-5.10.3) [source] [64-bit] [smp:2:2] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V5.10.3  (abort with ^G)
([email protected])1> net_adm:ping('[email protected]').
pong
([email protected])2> nodes().
['[email protected]']
([email protected])3>
User switch command
 --> h
  c [nn]            - connect to job
  i [nn]            - interrupt job
  k [nn]            - kill job
  j                 - list all jobs
  s [shell]         - start local shell
  r [node [shell]]  - start remote shell
  q                 - quit erlang
  ? | h             - this message
 --> r '[email protected]'
 --> j
   1  {shell,start,[init]}
   2* {'[email protected]',shell,start,[]}
 --> c 2

分析流程

Erlang有很多工具,可以分析系统信息,比如appmon,webtool。但是系统内存严重不足,已经没有办法启动这些工具了,幸好还有Erlang shell。

Erlang shell自带了很多有用的命令,可以用help()方法查看
复制代码 代码如下:
> help().

Erlang系统内存消耗情况

top结果显示,是内存问题,所以第一步可以先看看Erlang的系统内存消耗情况
复制代码 代码如下:
> erlang:memory().

memory()可以看到Erlang emulator分配的内存,有总的内存,atom消耗的内存,process消耗的内存等等。

Erlang process创建数量

线上系统发现主要内存消耗都在process上面,接下来要分析,是process内存泄漏了,还是process创建数量太多导致。
复制代码 代码如下:
> erlang:system_info(process_limit).  %%查看系统最多能创建多少process
> erlang:system_info(process_count).  %%当前系统创建了多少process

system_info()返回当前系统的一些信息,比如系统process,port的数量。执行上面命令,大吃一惊,只有2,3k的网络连接,结果Erlang process已经有10多w了。系统process创建了,但是因为代码或者其它原因,堆积没有释放。

查看单个process的信息

既然是因为process因为某种原因堆积了,只能从process里找原因了

先要获取堆积process的pid
复制代码 代码如下:
> i().  %%返回system信息
> i(0,61,886).  %% (0,61,886)是pid

看到有很多process hang在那里,查看具体pid信息,发现message_queue有几条消息没有被处理。下面就用到强大的erlang:process_info()方法,它可以获取进程相当丰富的信息。
复制代码 代码如下:
> erlang:process_info(pid(0,61,886), current_stacktrace).
> rp(erlang:process_info(pid(0,61,886), backtrace)).

查看进程的backtrace时,发现下面的信息
复制代码 代码如下:
0x00007fbd6f18dbf8 Return addr 0x00007fbff201aa00 (gen_event:rpc/2 + 96)
y(0)     #Ref<0.0.2014.142287>
y(1)     infinity
y(2)     {sync_notify,{log,{lager_msg,[], ..........}}
y(3)     <0.61.886>
y(4)     <0.89.0>
y(5)     []

process在处理Erlang第三方的日志库lager时,hang住了。

问题原因

查看lager的文档,发现以下信息
复制代码 代码如下:
Prior to lager 2.0, the gen_event at the core of lager operated purely in synchronous mode. Asynchronous mode is faster, but has no protection against message queue overload. In lager 2.0, the gen_event takes a hybrid approach. it polls its own mailbox size and toggles the messaging between synchronous and asynchronous depending on mailbox size.

{async_threshold, 20}, {async_threshold_window, 5}

This will use async messaging until the mailbox exceeds 20 messages, at which point synchronous messaging will be used, and switch back to asynchronous, when size reduces to 20 - 5 = 15.

If you wish to disable this behaviour, simply set it to 'undefined'. It defaults to a low number to prevent the mailbox growing rapidly beyond the limit and causing problems. In general, lager should process messages as fast as they come in, so getting 20 behind should be relatively exceptional anyway.

原来lager有个配置项,配置message未处理的数量,如果message堆积数超出,则会用 同步 方式处理!

当前系统打开了debug log,洪水般的log把系统给冲垮了。

老外也碰到类似问题,这个thread给我们的分析带来很多帮助,感谢一下。

总结

Erlang提供了丰富的工具,可以在线进入系统,现场分析问题,这个非常有助于高效、快速的定位问题。同时,强大的Erlang OTP让系统有更稳定的保证。我们还会继续挖掘Erlang,期待有更多的实践分享。


  • 上一条:
    Erlang程序设计(第2版)读书笔记:Erlang安装和基础语法
    下一条:
    Erlang的一些编程技巧分享
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 2024.07.09日OpenAI将终止对中国等国家和地区API服务(0个评论)
    • 2024/6/9最新免费公益节点SSR/V2ray/Shadowrocket/Clash节点分享|科学上网|免费梯子(0个评论)
    • 国外服务器实现api.openai.com反代nginx配置(0个评论)
    • 2024/4/28最新免费公益节点SSR/V2ray/Shadowrocket/Clash节点分享|科学上网|免费梯子(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-07
    • 2017-08
    • 2017-09
    • 2018-01
    • 2018-07
    • 2018-08
    • 2018-09
    • 2018-12
    • 2019-01
    • 2019-02
    • 2019-03
    • 2019-04
    • 2019-05
    • 2019-06
    • 2019-07
    • 2019-08
    • 2019-09
    • 2019-10
    • 2019-11
    • 2019-12
    • 2020-01
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2020-10
    • 2020-11
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-04
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-12
    • 2024-02
    • 2024-04
    • 2024-05
    • 2024-06
    • 2025-02
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客