一次内存泄漏问题定位过程与分析
来源:互联网 发布:linux vim 删除全部 编辑:程序博客网 时间:2024/05/16 17:44
现场:
逻辑server服务器处理能力骤降, 客户端请求大量失败. 逻辑server的统计数据显示,请求量略有增长(客户端重试的结果), log内容显示访问外部接口有一定失败.
分析:
第一反应是外部接口失败导致进程处理堵塞,大量请求被堵塞后丢弃导致客户端重试. vmstat 1看了一下, 发现b字段保持在20-40之间,wa字段值远大于0, 说明进程在等待输入输出而被阻塞. 而swap的si字段值很大,说明系统大量使用交换分区,难道有内存泄漏?
procs -----------memory---------- ---swap-- -----io---- -system-- -----cpu------
r b swpd free buff cache si so bi bo in cs us sy id wa st
27 21 1052252 5415680 7308 29892 1 1 1 1 0 0 8 8 82 2 0
30 22 1052252 5414936 7308 30276 644 0 644 8 15045 27172 4 3 52 40 0
19 22 1052252 5414440 7328 29640 616 0 620 176 15259 26953 4 3 42 50 0
3 21 1052252 5413696 7340 30084 572 0 572 32 15385 26809 3 3 45 48 0
0 21 1052252 5413216 7340 29412 672 0 672 0 15105 26989 4 3 30 63 0
top 看了一下, 发现单个处理进程的RES占到了300m,而SHR占用了34m,SHR是进程启动时分配的共享内存,数值是合理的,而RES字段经验值是在36m-40m左右,说明有内存泄,因此重启了一下进程进行确认,重启之后top如下所示:
top - 13:38:13 up 31 days, 22:15, 1 user, load average: 0.95, 1.57, 1.97
Tasks: 112 total, 8 running, 104 sleeping, 0 stopped, 0 zombie
Cpu(s): 17.9%us, 1.8%sy, 0.0%ni, 79.5%id, 0.0%wa, 0.0%hi, 0.9%si, 0.0%st
Mem: 16429836k total, 2236360k used, 14193476k free, 443520k buffers
Swap: 2104504k total, 0k used, 2104504k free, 1201280k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8901 root 15 0 74816 38m 34m S 7 0.2 2:38.97 logic_worker
9003 root 15 0 74840 38m 34m S 7 0.2 2:39.12 logic_worker
重启后,发现RES字段在不断增长,并且在SHR稳定在34m后还在持续上升,可以确定有内存泄漏。
解决:
查看进段时间的内存日报,发现曲线自2.3号发布新版本后内存使用量持续上升,从正常状态的3.3G,用到了8.7G,到今天内存已全部用尽,使用了交换分区,才出现异常。
对比当日版本代码变更,很快发现在一个外部库使用中,出现了内存泄漏,代码大致如下。
char *ptr;
int ret = Encode(ptr, len);
if (ret <0 )
{
return ErrorEncode;
}
ret = send(ptr, len);
if (ret <0 )
{
return ErrorSend;
}
return 0;
重新查看接口描述,发现ptr是在Encode里被malloc的,需要外部释放,于是修改代码如下:
char *ptr=NULL;
do
{
int ret = Encode(ptr, len);
if (ret <0 )
{
break;
}
ret = send(ptr, len);
if (ret <0 )
{
break;
}
}
if (NULL != ptr)
{
free(ptr);
ptr = NULL;
}
return ret;
修改后发布,10分钟后top观察,发现RES字段稳定在36m,问题解决。
总结:
1. 在使用外部库和接口时,一定要弄清楚api的使用方法和注意事宜,另外,在编写接口时也注意,最好不要在内部申请内存,而依赖外部释放,可以把上面Encode和Send封装到一个类中,或者一个接口中,接口本身负责编码和发送,内存申请和释放,调用者只需要知道返回码即可。
2. 在出现类似运营问题时,注意看系统参数是否异常,如果vmstat看 wa 和 si 值都异常,再综合top便可以看出,进程异常并不是因为请求量突增,处理时延而导致切换,而是因为内存泄漏的原因。
3. 注意对比监控曲线,如网络包量,请求量,内存使用,io使用等,通过对比,便可以看出,异常出现的时间点,结合代码变更便可定位出原因所在。
- 一次内存泄漏问题定位过程与分析
- 一次内存泄漏问题的发现与解决过程
- 记录一次kernel内存泄漏的查找定位过程
- 一次百度内存泄漏定位
- java内存泄漏的定位与分析
- java内存泄漏的定位与分析
- java内存泄漏的定位与分析
- 【java内存泄漏的定位与分析】
- java内存泄漏的定位与分析
- java内存泄漏的定位与分析
- java内存泄漏的定位与分析
- java内存泄漏的定位与分析
- java内存泄漏的定位与分析
- java内存泄漏的定位与分析
- java内存泄漏的定位与分析
- java内存泄漏的定位与分析
- java内存泄漏的定位与分析
- java内存泄漏的定位与分析
- JS得到窗口高度
- 设计模式(六)之Adapter - 适配器模式
- net use
- 设计模式(七)之Bridge - 桥接模式
- BS 7799
- 一次内存泄漏问题定位过程与分析
- 方法随tomcat启动被调用
- 学习C#从俄罗斯方块开始(二)俄罗斯方块的规则和算法的简单实现
- SDL & Object Pascal (Delphi) [1] 配置,第一个视频窗口,关闭
- 回家
- WINDOWS文件夹内容简介
- SDL & Object Pascal (Delphi) [2] 显示中文字符
- SDL & Object Pascal (Delphi) [3] 制作一个选单
- Flex Builder 快捷键