老项目是netty3的,本来想直接改到netty5,但是netty5居然是只支持jdk1.7,很奇怪jdk1.6和jdk1.8都不行..为了兼容jdk1.6加上netty4本来和netty5就差别不大,最后上的netty4.
先期看了一些netty3升netty4的经验总结,然后开始动工.改完后运行一下,发现2个客户端连接,只有1个工作正常,另一个在建立连接的时候直接就阻塞到建立连接这里:
channel = this.lastWriteFuture.awaitUninterruptibly().channel();
建立连接阶段直接一直阻塞,当时我就有点晕啊..死锁?第一印象,这项目线程无数,理了一遍又一遍真是一点头绪没有.随便写个简单demo型的客户端连接一下,一切正常,服务端没有任何问题.
对比其中能正常建立连接的客户端代码,没发现什么区别啊(实际上此时如果头脑快的话,应该已经能定位问题所在了),没解了,被这问题 绊住1天多,只好用最笨的办法排除了,从demo代码向项目中的真实代码一点一点累加,看出在哪部分..经过n长时间终于确认到这个客户端的handler部分有问题..这handler继承了一层,父子类看了一遍又一遍,也没看出来特别的地方.没招继续用最笨的方法,一段代码一段代码注释掉,看哪部分影响..就这样n久之后发现问题代码段,一看还没觉得有什么问题,点了一下看了一下文档说明才发觉问题所在,感觉这2天又虚度了..
//netty3的方法
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
xxxx;
}
//netty4我改成的方法
@Override
public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise future)
throws Exception {
xxxx;
}
这个当时替换的时候直接当做一个方法处理了...生成新的重写方法的时候,因为名字很像就直接也点选生成了,然后就把原来的channelConnected方法中的实现写到这个方法中了.这个其实如果它要是抛异常或是出错应该马上就能发现这里写错了..但是点选这个connect方法能看到文档如下解释:
Calls ChannelHandlerContext.connect(SocketAddress, SocketAddress, ChannelPromise) to forward to the next ChannelOutboundHandler in the ChannelPipeline. Sub-classes may override this method to change behavior.
//简单说程序在管道中多个ChannelOutBoundHandler中传递的时候,可以用这个方法进行一些自定义操作.
然后我把这个方法写成别的了,而且并没有调用connect(ctx, remoteAddress, localAddress, future)方法导致这个方法功能直接废了,没法在管道中传递了.现象就是没有任何异常和报错的这个连接走到这里就无返回值的结束了,而建立连接那头还在无限期的等待连接建立...
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
xxxx;
}
改成以上的正常代码后,功能恢复正常,连接可以正常建立...