对页游《小兵大战》服务器DM内存溢出的排错过程总结

简介: 对页游《小兵大战》服务器DM内存溢出的排错过程总结
这篇文章成文于2012年公司内存论坛交流,现和大家分享一下!--流子

这个事件发生在前一阵子,总结为了给项目组的同事和自己遇到类似问题时少走冤枉路,定位问题的思路如果能给你的工作带来一点点帮助,我会非常开心!

背景

项目名《小兵大战》  欢迎试玩,-->传送门<--

合作平台:腾讯QQ空间,朋友网,新浪微游戏等

托管模式:使用腾讯云平台托管/部署服务(hosting) 或者自己出服务器

模式:大区单服

游戏服务器硬件配置

资源类型 硬件 型号/版本/配置
VC3 CPU 8核,相当于2.0GHZ的Xeon处理器或Opteron处理器
内存 7G 相当于DDR3 1066MHZ
硬盘 300G SATA raid0 结构单盘硬盘
OS Linux 2.6 (suse 10,64位)

跑的都是JAVA应用(JDK 1.6),用的数据库为MySQL5.5.13,缓存数据库为Redis 2.6.11

事件:

19:35 事件信息:腾讯云监控-系统内存将占满

手机收到消息【腾讯云监控,系统内存将占满】app100630301|19:35|10.190.*.*|系统内存使用达到95%,剩余0.35G【腾讯科技】

19:50  事件信息:通过跳板机登录不了游戏服务器

怀疑整台虚拟机宕掉,通过腾讯运维重启解决

21:37 事件信息:应用游戏逻辑 game server和gate server停掉

重启所有应用解决,并开始监控分析

分析:

step 1. 查看服务器应用的日志,没有抛出任何异常,有点诡异!

Step 2. 莫非是JVM crash 了,这样的话,应该能在几个应用的当前目录下能找到hs_err_pid*******.log 的crash log.,也没有找到,迷茫!

step 3 查看系统日志

app100630301@Tencent64:~>cat /var/log/messages |grep -i "killed process"

<span style="color:#000066">Jun 28 21:36:08 VM_235_15 kernel:out of memory:killed process [pid](java)
................
................</span>

sudo dmesg|grep -i kill|less

[6710782.021013] java invoked oom-killer: gfp_mask=0xd0, order=0, oom_adj=0, oom_scoe_adj=0
[6710782.070639] [<ffffffff81118898>] ? oom_kill_process+0x68/0x140 
[6710782.257588] Task in /LXC011175068174 killed as a result of limit of /LXC011175068174 
[6710784.698347] Memory cgroup out of memory: Kill process 215701 (java) score 854 or sacrifice child 
[6710784.707978] Killed process 215701, UID 679, (java) total-vm:11017300kB, anon-rss:7152432kB, file-rss:1232kB

以上表明,对应的java进程被系统的OOM Killer给干掉了,得分为854.

解释一下OOM killer(Out-Of-Memory killer),该机制会监控机器的内存资源消耗。当机器内存耗尽前,该机制会扫描所有的进程(按照一定规则计算,内存占用,时间等),挑选出得分最高的进程,然后杀死,从而保护机器。

dmesg日志时间转换公式:

log实际时间=格林威治1970-01-01+(当前时间秒数-系统启动至今的秒数+dmesg打印的log时间)秒数:

date -d "1970-01-01 UTC `echo "$(date +%s)-$(cat /proc/uptime|cut -f 1 -d' ')+12288812.926194"|bc ` seconds"

内存总占用超过系统内存,然后系统优先kill掉相对耗内存的进程,这种情况下既不会有crash log,也不会有core dump,推断Game server和gate server就是这样被OOM killer 灭掉的!定位到Game server 或Gate server有内存泄漏。

step 4 开始监控重启后的应用,发现gate 的内存占用有问题!

app100630301@Tencent64:~>t:~ # ps -ef|grep java

root     25936     1  0 Apr19 ?        00:17:29 java -server -Xms1G -Xmx1G -Xmn256m -XX:PermSize=64m -XX:MaxPermSize=64m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -XX:+HeapDumpOnOutOfMemoryError -Xloggc:gate_gc_1_201304191211.log -jar /data/ztgame/S20120712R1/gate/gate.jar 1

app100630301@Tencent64:~>top p 18202

PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND 
 25936 root      18   0 4359m 492m 7856 S    0  64.0  17:29.21 java

进程占用了4G多,单个进程占用达到了60%多(总共7G) 问题定位到了进程gate 以前也遇到过内存溢出的情况,但应用都会抛出java.lang.OutOfMemoryException,而这次却没有,但为何 gate苑苑超出了JVM内存配置的2G的上限呢?

Step 5 查看堆的占用

app100630301@Tencent64:~>jmap -heap 18202

<span style="color:#330099">Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 1073741824 (1024.0MB)
   NewSize          = 268435456 (256.0MB)
   MaxNewSize       = 268435456 (256.0MB)
   OldSize          = 5439488 (5.1875MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 67108864 (64.0MB)
   MaxPermSize      = 67108864 (64.0MB)
Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 241631232 (230.4375MB)
   used     = 43095400 (41.098976135253906MB)
   free     = 198535832 (189.3385238647461MB)
   17.835194417251493% used
Eden Space:
   capacity = 214827008 (204.875MB)
   used     = 41506656 (39.583831787109375MB)
   free     = 173320352 (165.29116821289062MB)
   19.320967315245575% used
From Space:
   capacity = 26804224 (25.5625MB)
   used     = 1588744 (1.5151443481445312MB)
   free     = 25215480 (24.04735565185547MB)
   5.927215053866137% used
To Space:
   capacity = 26804224 (25.5625MB)
   used     = 0 (0.0MB)
   free     = 26804224 (25.5625MB)
   0.0% used
concurrent mark-sweep generation:
   capacity = 805306368 (768.0MB)
   used     = 265440944 (253.1442108154297MB)
   free     = 539865424 (514.8557891845703MB)
   32.96148578325907% used
Perm Generation:
   capacity = 67108864 (64.0MB)
   used     = 26712504 (25.47502899169922MB)
   free     = 40396360 (38.52497100830078MB)
   39.80473279953003% used</span>

算了下,实际堆内存占用才1G左右,苑苑没有达到JVM的内存占用上限,那么,那3G多的内存是从哪里泄漏的呢?

Step 6. JVM除了堆内存外,就只有栈内存和Direct Memory了,栈空间每个线程是固定的,而占用大小基本固定而且可以忽略,而Direct Memory或者叫直接内存,并不是虚拟机运行时数据区的一部分,不受JVM的GC管理,其中Java的nio中Buffer直接在堆外分配的就属于这个部分,直接以native的方式分配内存,这是为了提高网络和文件的IO效率,避免过度的内存拷贝而出现的,那么,怀疑的目标就只剩下Direct Memory了。

Direct Memory 占用的大小没有直接的工具或者API可以查看,不过,我们可以通过反射在某个类里拿到这个数据。

<span style="color:#000066">Class<?> c = Class.forName("java.nio.Bits");
Field maxMemory = c.getDeclaredField("maxMemory");
maxMemory.setAccessible(true);
Field reservedMemory = c.getDeclaredField("reservedMemory");
reservedMemory.setAccessible(true);
Long maxMemoryValue = (Long)maxMemory.get(null);
Long reservedMemoryValue = (Long)reservedMemory.get(null);</span>

如果不想反射获得,那么,netty已经给我们提供了一个方法,

io.netty.util.internal.PlatformDependent#maxDirectMemory()直接用就行,感谢netty

参考来源:JVM的DirectMemory设置

reservedMemoryValue 表示直接内存的已占用大小,结果明显正式了我的猜测!Direct Memory增长失控了,那么,是什么导致了Direct Memory内存泄漏呢?

Step 7.记得为了减少和客户端的数据通信量大小,协议的来往都会通过zlib进行压缩和解压,而 zlib codec为了提高压缩和解压的效率采用了nio包的direct-buffers.那么,如果猜测是对的话,如果暂时关闭压缩和解压的功能,应该停止内存泄漏,于是吧服务器的压缩开关关闭。

<span style="color:#000066">14:06 400M 5.6%
14:10 511M,7.3% 
15:08 606M 8.7%
15:14 626M 8.9%
16:17 629M 9.0% </span>

基本已经不变,稳定!

Step 8 知道了根本原因,修改代码,zlib codec的Deflater 和Inflater在压缩和解压后都需要关闭,才能保证内存不会泄漏!

<span style="color:#000066">Inflater decompresser=null;
解压加上 finally{
decompresser.end();
}
Deflater compresser=null;
压缩加上 
解压加上 finally{
compresser.end();
}</span>

Step 9.修改完毕,发出版本,搞定!

总结

综上,分析问题的定位思路,从确定应用Game server或者gate server --> 锁定 Gate server -> Gate Server -> 锁定Direct Memory的溢出->最终确定是Zlib的压缩和解压为内存溢出的根本原因,层层分析,顺藤摸瓜,希望大家看到后都能得到一些收获!

有什么问题想交流的,请随时和我联系,谢谢!

QQ:41157121

 

目录
相关文章
|
2月前
|
存储 分布式计算 网络协议
阿里云服务器内存型r7、r8a、r8y实例区别参考
在阿里云目前的活动中,属于内存型实例规格的云服务器有内存型r7、内存型r8a、内存型r8y这几个实例规格,相比于活动内的经济型e、通用算力型u1实例来说,这些实例规格等性能更强,与计算型和通用型相比,它的内存更大,因此这些内存型实例规格主要适用于数据库、中间件和数据分析与挖掘,Hadoop、Spark集群等场景,本文为大家介绍内存型r7、r8a、r8y实例区别及最新活动价格,以供参考。
阿里云服务器内存型r7、r8a、r8y实例区别参考
|
3月前
|
弹性计算
2024阿里云幻兽帕鲁/Palworld服务器价格表(CPU/内存/带宽/磁盘收费标准)
2024年阿里云幻兽帕鲁专用服务器的价格根据不同的配置有所不同。 • 4核16G配置的价格为32元/月,如果选择购买3个月,则价格为96元。 • 8核32G配置的价格为90元/月,如果选择购买3个月,则价格为271元。 另外,还有配置为4核16G10M带宽的服务器,其价格为26元/月起。而8核32G10M带宽的价格也是90元/月。
98 1
|
28天前
|
存储 缓存 NoSQL
Redis 服务器指南:高性能内存数据库的完整使用指南
Redis 服务器指南:高性能内存数据库的完整使用指南
|
2月前
|
存储 缓存 PHP
阿里云服务器实例、CPU内存、带宽、操作系统选择参考
对于使用阿里云服务器的用户来说,云服务器的选择和使用非常重要,如果实例、内存、CPU、带宽等配置选择错误,可能会影响到自己业务在云服务器上的计算性能及后期运营状况,本文为大家介绍一下阿里云服务器实例、CPU内存、带宽、操作系统的选择注意事项,以供参考。
阿里云服务器实例、CPU内存、带宽、操作系统选择参考
|
2月前
|
弹性计算 固态存储 Linux
2024年阿里云服务器租用详细价格表(CPU/内存/带宽/系统盘)
2024阿里云服务器租用优惠价格表,轻量服务器2核2G3M带宽轻量服务器一年61元,2核4G4M带宽轻量服务器一年165元12个月,ECS云服务器e系列2核2G配置、3M固定带宽、40G ESSD Entry云盘,99元一年、2核4G服务器30元3个月、2核4G配置365元一年、2核8G配置522元一年,云服务器u1、云服务器c7、g7和r7优惠价格表,CPU内存带宽系统盘配置详细报价:
920 3
|
2月前
|
弹性计算 固态存储 调度
阿里云服务器部署配置选择全攻略,ECS实例规格、CPU内存配置
阿里云服务器部署配置选择全攻略,ECS实例规格、CPU内存配置,CPU内存、公网带宽和系统盘怎么选择?个人用户选择轻量应用服务器或ECS通用算力型u1云服务器,企业用户选择ECS计算型c7、通用型g7云服务器,阿里云百科分享阿里云服务器配置选择方法
|
2月前
|
弹性计算 固态存储 调度
阿里云服务器选购指南_2024新版CPU内存带宽系统盘选择攻略
阿里云服务器选购指南_2024新版CPU内存带宽系统盘选择攻略,CPU内存、公网带宽和系统盘怎么选择?个人用户选择轻量应用服务器或ECS通用算力型u1云服务器,企业用户选择ECS计算型c7、通用型g7云服务器,阿里云百科分享阿里云服务器配置选择方法
|
2月前
|
弹性计算 固态存储 调度
阿里云配置服务器详细指南_2024新版CPU内存带宽系统盘选择
阿里云配置服务器详细指南_2024新版CPU内存带宽系统盘选择,阿里云服务器配置怎么选择?CPU内存、公网带宽和系统盘怎么选择?个人用户选择轻量应用服务器或ECS通用算力型u1云服务器,企业用户选择ECS计算型c7、通用型g7云服务器,阿里云百科分享阿里云服务器配置选择方法
|
3月前
|
弹性计算 大数据 测试技术
阿里服务器租用多少钱一年?阿里云服务器租用价格表(最新CPU/内存/带宽/磁盘收费标准)
阿里服务器租用多少钱一年?阿里云服务器租用价格表(最新CPU/内存/带宽/磁盘收费标准)。阿里云服务器的租用费用因实例类型、地域、配置等因素而有所不同,价格范围可以从几百元到几千元不等。2024年阿里云服务器租用费用价格表更新,云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、ECS u1实例2核4G、5M固定带宽、80G ESSD Entry盘优惠价格199元一年,轻量应用服务器2核2G3M带宽轻量服务器一年61元、2核4G4M带宽轻量服务器一年165元12个月、2核4G服务器30元3个月,幻兽帕鲁4核16G和8核32G服务器配置,云服务器ECS可以选择经济型e实例、通用算力u1实
|
3月前
|
弹性计算 大数据 测试技术
2024阿里云服务器租用价格表(CPU/内存/带宽/磁盘收费标准)
阿里云服务器分为轻量应用服务器和云服务器ECS,轻量适合个人开发者使用,搭建轻量级的网站、测试环境使用;专业级如大数据、科学计算、高并发网站等需要使用云服务器ECS。2024年阿里云服务器租用价格表出炉!云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、ECS u1实例2核4G、5M固定带宽、80G ESSD Entry盘优惠价格199元一年,轻量应用服务器2核2G3M带宽轻量服务器一年61元、2核4G4M带宽轻量服务器一年165元12个月、2核4G服务器30元3个月,幻兽帕鲁4核16G和8核32G服务器配置,云服务器ECS可以选择经济型e实例、通用算力u1实例、ECS计算型c7、通
464 1

热门文章

最新文章