Netty:channelInactive、exceptionCaught方法不断触发

最近用Netty写IM参考了 FreddyChen 大佬的开源,关于这个不断重连的问题,也请教了大佬,大佬前后都十分热心,共同找分析共同解决,谢谢大佬!

开源一个自用的Android IM库,基于Netty+TCP+Protobuf实现

背景:

期间发现一个非常重要的问题,就是ChannelInboundHandlerAdapter的channelInactive、exceptionCaught方法在重新登录,或者网络状态有变的情况下,可能会出现无限触发的问题.

 
图片.png

 

问题场景:

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
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
posted @ 2024-07-26 18:01  枫树湾河桥  阅读(17)  评论(0编辑  收藏  举报
Live2D