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.总结

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

相关推荐
风一样的树懒1 分钟前
怎么理解ES的准实时性?
后端
惊骇世俗王某人12 分钟前
1. 深入理解ArrayList源码
java·开发语言
用户403159863966321 分钟前
表达式并发计算
java·算法
无限大624 分钟前
《计算机“十万个为什么”》之 Java 语言为什么能跨平台
后端
无为34731 分钟前
用AI解决独立开发者痛点:我如何构建一个面向开发者的产品灵感平台
后端
SimonKing33 分钟前
告别System.currentTimeMillis()!Java高精度计时最佳实践
java·后端·程序员
Dcs33 分钟前
JUnit 5架构如何用模块化颠覆测试框架?
java
Moment34 分钟前
通过 Mac 自动的 say 命令学习粤语真的太好玩了 😏😏😏
前端·javascript·后端
肉肉不想干后端37 分钟前
gRPC服务架构整合springboot部署实践指南
java
understandme38 分钟前
维护 mysql 老代码的 json 的坑
javascript·后端