Troubleshooting系列-DUBBO中间版本导致应用频繁Fullgc的问题定位分析

1. 问题现象

一天运维同学找过来,现网有台机器频繁fullgc,几乎1分钟一次。

2. 问题定位分析

这种问题比较好定位分析,因为应用进程还在提供服务。先保留现场,取heap dump回来分析。

相关命令参考之前帖子Troubleshooting系列-JAVA虚拟机命令总结

给出命令

bash 复制代码
//123 通过jps获取应用进程替换
jmap -dump:format=b,file=123.bin 123 
jstack -1 123>123jstack.txt 
jmap dump:live,format=b,file=123.bin2 123

取回heap dump后,使用mat工具分析,mat工具使用参考Troubleshooting系列-MAT使用介绍以实战

简单分析后,发现dubbo的org apache,dubbo,remoting.transportnetty4.NettyChannel疑似存在内存泄露问题

发现问题后,寻找应用对应的版本,发现版本还是老版本dubbo 3.1.1,其他应用dubbo版本都已经升级到dubbo 3.2.0。怀疑是dubbo版本不兼容或者dubbo老版本有问题导致的。

现阶段解决方式比较简单,该应用已经好久没重启了,先重启,减少堆中NettyChannel占用

应急处理大法,重启

3. 源码分析

翻看dubbo 3.1.1源码 先看NettyChannel源码,主要就是存在CHANNEL_MAP

java 复制代码
final class NettyChannel extends AbstractChannel {

    private static final Logger logger = LoggerFactory.getLogger(NettyChannel.class);

    private static final ConcurrentMap<org.jboss.netty.channel.Channel, NettyChannel> CHANNEL_MAP = new ConcurrentHashMap<org.jboss.netty.channel.Channel, NettyChannel>();

    private final org.jboss.netty.channel.Channel channel;

    private final Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();

    private NettyChannel(org.jboss.netty.channel.Channel channel, URL url, ChannelHandler handler) {
        ...
    }

    static NettyChannel getOrAddChannel(org.jboss.netty.channel.Channel ch, URL url, ChannelHandler handler) {
        if (ch == null) {
            return null;
        }
        NettyChannel ret = CHANNEL_MAP.get(ch);
        if (ret == null) {
            NettyChannel nc = new NettyChannel(ch, url, handler);
            if (ch.isConnected()) {
                ret = CHANNEL_MAP.putIfAbsent(ch, nc);
            }
            if (ret == null) {
                ret = nc;
            }
        }
        return ret;
    }

    static void removeChannelIfDisconnected(org.jboss.netty.channel.Channel ch) {
        if (ch != null && !ch.isConnected()) {
            CHANNEL_MAP.remove(ch);
        }
    }
    ...

可能是调用getOrAddChannel的地方,没有在channel关闭的时候调用removeChannelIfDisconnected或者close方法,查看其调用方法

发现这个类NettyPortUnificationServerHandler比较可疑,channelInactive或者exceptionCaught没有处理

这个版本不是最终版本,同时出现好久了,一般在github已经有其他人会遇到,在github.com/apache/dubb... 上搜索NettyChannel,果然发现类似的问题

github.com/apache/dubb...

已经有了修复merge,如下 github.com/apache/dubb... 主要改动就是加了一个装饰类,重写了channelInactive,把nettychannel移除

4.总结

后台应用中间件升级版本需要保持一致,对于无需求的应用也要及时升级版本,避免出现已知问题。

相关推荐
一只叫煤球的猫5 小时前
写代码很6,面试秒变菜鸟?不卖课,面试官视角走心探讨
前端·后端·面试
bobz9656 小时前
tcp/ip 中的多路复用
后端
bobz9656 小时前
tls ingress 简单记录
后端
皮皮林5517 小时前
IDEA 源码阅读利器,你居然还不会?
java·intellij idea
你的人类朋友7 小时前
什么是OpenSSL
后端·安全·程序员
bobz9657 小时前
mcp 直接操作浏览器
后端
前端小张同学10 小时前
服务器部署 gitlab 占用空间太大怎么办,优化思路。
后端
databook10 小时前
Manim实现闪光轨迹特效
后端·python·动效
武子康10 小时前
大数据-98 Spark 从 DStream 到 Structured Streaming:Spark 实时计算的演进
大数据·后端·spark
该用户已不存在11 小时前
6个值得收藏的.NET ORM 框架
前端·后端·.net