Netty:channelInactive、exceptionCaught方法不断触发
最近用Netty写IM参考了 FreddyChen 大佬的开源,关于这个不断重连的问题,也请教了大佬,大佬前后都十分热心,共同找分析共同解决,谢谢大佬!
开源一个自用的Android IM库,基于Netty+TCP+Protobuf实现
背景:
期间发现一个非常重要的问题,就是ChannelInboundHandlerAdapter的channelInactive、exceptionCaught方法在重新登录,或者网络状态有变的情况下,可能会出现无限触发的问题.

问题场景:
channelInactive、exceptionCaught中,我们采用了自动重连,但会发现一个问题,在重连成功的情况下,还会重连,不断的反复重连.
问题原因:
1 : 主动退出
如果在用户主动退出的情况下,比如,用户主动退出聊天或者主动杀死App,这种情况下,是不需要重连的
2 : 业务逻辑异常
Channel中所有未捕获的异常,都会触发exceptionCaught方法,比如后台返回的数据格式不对,产生了没有捕获的异常,就会触发exceptionCaught,所以,在ChannelInboundHandlerAdapter的各种方法中,最好不要有没有处理的业务逻辑异常.
当天解决了这两个问题后,不断重连Bug不再重现,以为问题解决了,开开心心的回家,结果第二天来了,不断重连的问题又出现了,但这次出现的原因是,我退出登录后重新登录,才会出现.
分析:
首先,这次出现不断的重连原因,只有在第二次登陆后,才会重连.即便是第二次登录,但IM所有相关的连接和组件,都是重新初始化的, 所以我先把重连方法closeChannelAndReConnect(ctx);注释掉.注释后第二次登录,发现重连问题不再重现.所以,基本可以可以肯定,一定是重连的方法里,某个异常或者动作,导致了当前的连接主动关闭了
验证:
在channelInactive()方法打了断点,通过堆栈信息我看到触发channelInactive()方法的条件:wasActive&&isActive()

然后我继续查看isActive()方法发现:isActive = ch.isOpen()&&ch.isConnected()

看到这儿我就明白为什么会出现不断重连的问题了:
由于我在重连的之前,是先把所有的IM连接停止掉,包括线程池,具体方法看图:

但是,我没有清除Channel中的各种Handler,由于Handler在子线程中不停的轮训:

而这个task.run()回调的方法就是上面图2的方法.当我第一次登陆成功,Channel中就有了各种handler,而我在第二次登录的时候,由于第一次退出只是Channel.close()了,没有清除Channel中的各种handler,导致handler在轮训的时候,发现Channel是关闭的,所以就不断的触发不断的重连.....进入了死循环!
结论
关闭Channel之前,先清除掉Channel中的各种handler,如图

碎碎念:
1: 处理好各个handler中的透传逻辑,否则也是噩梦!
2: 各个重写方法中,确认是否需要调用父类的重写方法,比如是否需要调用super.channelInactive(),本质同上条
3: 如果有用,请点个喜欢
作者:moushao
链接:https://www.jianshu.com/p/903498747f47
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)