专栏首页后台经验现网gc问题定位三板斧
原创

现网gc问题定位三板斧

国庆假期临近,组里的小伙伴们都开开心心请假回家了,然后cgi很应景的出现了多台机器的频繁full gc,所以只能上阵用力撸一把了。

第一板斧:看gc日志。

首先登上机器,进入日志目录/usr/local/services/javacgi_qqke_web-2.0/log

javacgi_qqke_web这个工程是比较有节操的了,配置了输出gc日志。直接grep一下FULL GC,看下是不是和告警匹配。

用力敲下面的命令

grep -rn "Full GC" cgi_ke_web.gclog

观察下FULL GC的时间,明显太频繁了,而且老年代每次回收完都没什么变化,可以初步判断是内存泄漏了,有大量的内存回收不了

ps,如果遇到没有节操的工程,没有输出gc日志,不用怕,现场实时观察就好

用力敲下下面的命令,21332是pid,1000毫秒输出一次,输出10次。

/usr/local/services/jdk7_32-1.0/bin/jstat -gcutil 21332 1000 10

第二板斧:jmap看堆内存情况

/usr/local/services/jdk7_32-1.0/bin/jmap -heap 21332

通过jmap工具,可以清楚看到,老年代耗尽了,但是永久带也不够接受老年代的数据,所以无论怎么回收,老年代不减少,导致了频繁 FULL GC

第三板斧:MAT

首先先用jmap工具把堆dump下来。

/usr/local/services/jdk7_32-1.0/bin/jmap -dump:live,format=b,file=dump.hprof 21332

把文件下载到本地机器,MAT是eclipse出品,windows使用正常,mac能不能用看造化

别忘了修改这个文件,调整MAT内存大小,不然装不下服务器的堆文件的

导入成功后,直接点内存泄漏分析

分析的结果告诉我们Sppclient中疑似内存泄漏。

仔细看一下内存分析,内存主要用在两个和后端spp-qun服务连接的qcon上面,每个qcon占用了300M+的内存,而且sppclient是全局单例,里面的数据都是不会回收的,这就是造成内存泄漏的主要来源。

看下这个队列里面的元素,有131672个。。

再去看下代码

public boolean write(Object msg, ChannelFutureListener connectionListener, ChannelFutureListener writeListener) {
if (channels.size() < maxChannels) {
return doConnectAndWrite(msg, connectionListener, writeListener);
    } else {
        Object[] ca = channels.toArray();
        int size = ca.length;
        nextChannel = (nextChannel + 1) % size;
        Channel c = (Channel) ca[nextChannel];
        if (c.isConnected()) {
            c.write(msg).addListener(writeListener);
        } else {
            ChannelFuture connFuture = ch2connFuture.get(c);
            if (connFuture != null) {
                connFuture.addListener(connectionListener);
            } else {
log.error("no connection future!!! channel={}", c);
            }
        }
return true;
    }

}
private boolean doConnectAndWrite(final Object msg, ChannelFutureListener connectionListener, final ChannelFutureListener writeListener) {

//新建tcp连接
    MonitorUtils.monitor(3222607);

    ChannelFuture future = bootstrap.connect(addr);
    Channel channel = future.getChannel();
    future.addListener(connectionListener);
    ch2connFuture.put(channel, future);
    //这里注意,这个channel可能还未连接成功
    channels.add(channel);
    return true;
}

看完代码,更怀疑人生了,理论上ch2connFuture 和 channels 数量应该是一致的,而且这个队列设置了上限65535,为啥现网会超出这么多。。

这时我们再回去看下MAT中的数据,channels只有17个。。

为啥?!!直到看完了add的实现,才终于恍然大悟

@Override
public boolean add(Channel channel) {
    ConcurrentMap<Integer, Channel> map =
        channel instanceof ServerChannel? serverChannels : nonServerChannels;

    boolean added = map.putIfAbsent(channel.getId(), channel) == null;
    if (added) {
        channel.getCloseFuture().addListener(remover);
    }
return added;
}

关键就在于add的操作判断了channel里面是否已经有了即将添加的channel,而这个判断条件是对比channel的id,那么问题来了,这里的channel其实是一个异步初始化的future类型,在执行add操作的时候,并不能保证拿到id,所以这里会出现大量id为0的channel。。而只要和后端建立连接的时候出现网络问题,这里的bug就会触发,就会导致内存泄漏。

总结下,这次的full gc是因为网络抖动导致的spp-qun调用的框架bug在现网出现,最快的解决方法就是重启服务。。。。

小事重启果然是在哪里都适用的操作啊。。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 第十四节 netty源码分析之客户端源码分析01

    接着.channel(NioSocketChannel.class);会初始化一个ChannelFactory用于,目的是为后续创建channel,源码如下

    用户1418372
  • CKafka系列学习文章 - CKafka场景案例(五)

    导语:当我们的公司在不断发展时,业务也是遍布全国或者已经国际化了,公司内部的各种系统也是越来越多,还要对接其它公司的系统,来实现公司业务的正常运转。这时我们通常...

    发哥说消息队列
  • Kafka Network层解析,还是有人把它说清楚了

    我们知道kafka是基于TCP连接的。其并没有像很多中间件使用netty作为TCP服务器。而是自己基于Java NIO写了一套。

    李红
  • Kafka Network层解析,还是有人把它说清楚了

    我们知道kafka是基于TCP连接的。其并没有像很多中间件使用netty作为TCP服务器。而是自己基于Java NIO写了一套。

    李红
  • CDN技术原理

    用户发送一个请求,智能DNS会向所有的节点发送一个探测指令,节点收到探测指令以后会主动判断自己和目标之间的距离,然后将探测的结果反馈给智能DNS,由智能DNS进...

    框架师
  • java nio 使用入门

    while循环中,多次channel.read(buffer)、flip并write后,如果不调用clear会使read返回0 跟踪read方法到IOUtil...

    平凡的学生族
  • RTSP协议视频智能分析平台EasyNVR二次开发调用Getchannels接口的channel参数不生效问题修复

    在实际的项目中,我们经常能碰到用户要求支持接口调用和二次开发,对此我们TSINGSEE青犀视频开发的云边端智能分析平台都提供了丰富的二次开发接口,大家可根据自己...

    EasyNVR
  • 传统医疗行业上云实践

    随着医疗行业的发展,在医疗行业也出现了比较激烈的竞争,许多的医院开始由线下转到线上来,比较出名的可能就是寻医问药和春雨医生等这样问答形式的站点。他们验证了在线问...

    相柳
  • 【GAMES101-现代计算机图形学课程笔记】Lecture 10 Geometry 1 (介绍)

    如下图示,通常一个光滑的表面(比如水晶球)会反射环境光,因此我们可以看到球面上会被映射出其他物体。那么计算机中如何表示这个呢?

    marsggbo
  • Appium+python自动化(十二)- Android UIAutomator终极定位凶器(超详解)

    乍眼一看,小伙伴们觉得这部分其实在异性兄弟那里就做过介绍和分享了,其实不然,上次介绍和分享的大哥是uiautomatorviewer,是一款定位工具...

    北京-宏哥

扫码关注云+社区

领取腾讯云代金券