监控Server端频繁挂机处理

来源:互联网 发布:昆山华道数据有限公司 编辑:程序博客网 时间:2024/05/16 04:40

1、  现象

应用接口人:“又报警了,旺旺都没法输入了……” “我的妈啊,几百个异常提醒,太恐怖了……”

监控首页:一片大红


2、  监控通信框图


上图左边的代码安装在各台机器上,大概480台左右,右边webApp有两台服务器,而与Agent通信的Server只有一台服务器。

3、  排查过程

1)  挂掉点是一段Jar包的java程序,自然排查其启动的内存,以及最大内存,查看启动参数:

java  -Xmx256m –Xms256m -jar../lib/gaea.env.server-0.0.1-SNAPSHOT.jar

2)  要与几百台机器通信,并且没5秒钟都有监控任务要处理,并写redis,怀疑内存太小,加大内存。

java  -Xmx2048m –Xms2048m -jar../lib/gaea.env.server-0.0.1-SNAPSHOT.jar

刚开始运行,监控显示非常正常,结果运行一晚上之后,监控图如下:


查看垃圾回收情况,FGC比YGC大很多


上面两个图非常清晰说明Server端挂机不是加内存的问题了,server端中明显存在内存泄露。

3)  dump内存文件分析


用mat工具打开dump的内存文件,发现NioAcceptedSocketChannel占用了98.77%内存,点击Details查看详情,


在此基本能确定连接的通道(channel)对象过多,没有释放掉;

4)  查看源代码与客户端监控通道的相关代码,调用顺序

main函数入口—>startup(),startup方法如下:


代码中阴影部分是 new EnvServerPipelineFactory(),主要代码如下:


阴影部分是new EnvServerDataHandler(),这个方法主要用来接收几百台机器的请求任务,由于这是从main函数启动时初始化的,new一个新对象应该没有问题,因为入口只有一个,并且只能同时启动一个Server,所以理论上EnvServerDataHandler应该也只会有一个。但是,用命令jmap –histo pid |grep EnvServerDataHandler 时会发现,这个对象刚开始时比较小,但是随着运行时间的加长,这个对象也在增多,甚至多达几千个,这就奇怪了!

5)  从mat的截图中也可以看到,DefaultChannelPipeline对象也应该被怀疑(该对象来自netty框架),查看 ChannelPipeline pipeline=Channels.pipeline()这句话,


可以看到,这个pipeline每一次客户端来一个请求都是return一个新的对象,从而建立一个通信管道,那么,pipelIne.addlist(“handler”,newEnvServerDataHandler());这句代码每次都new了一个EnvServerDataHandler,所以这个对象会很多,并且没能回收;

4、  处理方法

1)     由于nettey框架中每次都new了一个channel,那么应该将这句中的handler用单例实现,保证只有一个对象,

将pipelIne.addlist(“handler”,newEnvServerDataHandler())改为

 pipeline.addLast("handler", EnvServerDataHandler.getEnvServerDataHandler());

        其他改动代码略。

     为了监控改动之后的效果,将内存设为512m,效果如下:连续运行约80小时,FGC10次,总体维持在256m以内。


2)     由于Sever挂掉影响较大,为了进一步保证稳定性,还将进行以下处理:

server部署两台;

server端将开发自监控启动程序(下周任务);

原创粉丝点击