1. ctx.close()会触发当前Handler和当前Handler之前的close事件;
2. channel.close()所有Handler都会触发;
这样的顺序对于write操作和close都是一样道理的。
举例:netty服务端是这个添加顺序
ch.pipeline().addLast(new InboundHandler1());
ch.pipeline().addLast(new InboundHandler2());
ch.pipeline().addLast(new OutboundHandler1());
ch.pipeline().addLast(new OutboundHandler2());
链表中的顺序为head->in1->in2->out1->out2->tail
1、如果在InboundHandler2中执行的是ctx.channel().writeAndFlush,执行顺序是:
InboundHandler1
InboundHandler2
OutboundHandler2
OutboundHandler1
结果证明:执行完InboundHandler1、InboundHandler2之后,由于InboundHandler2中执行的是ctx.channel().writeAndFlush,它会直接从tail开始往前找Outbound执行,链表中的顺序为head->in1->in2->out1->out2->tail,所以会执行out2,再执行out1
2、如果在InboundHandler2中执行的是ctx.writeAndFlush,执行顺序是:
InboundHandler1
InboundHandler2
结果证明,由于OutboundHandler1与OutboundHandler2的add在InboundHandler2之后,而InboundHandler2中执行的是ctx.writeAndFlush,它会从当前InboundHandler2的位置,往前找Outbound执行,根据链表中的顺序为head->in1->in2->out1->out2->tail,in2之前已经无Outbound,所以不会再有Outbound会执行
上面两个已经能说明问题,为了方便对netty的handler执行不是太熟悉的读者理解,再举个例子:
ch.pipeline().addLast(new OutboundHandler1());
ch.pipeline().addLast(new OutboundHandler2());
ch.pipeline().addLast(new InboundHandler1());
ch.pipeline().addLast(new InboundHandler2());
链表中的顺序为head->out1->out2->in1->in2->tail
1、如果在InboundHandler2中执行的是ctx.channel().writeAndFlush,执行顺序是:
InboundHandler1
InboundHandler2
OutboundHandler2
OutboundHandler1
结果证明,执行完InboundHandler2后,由于InboundHandler2中执行的是ctx.channel().writeAndFlush,它会从tail往前找Outbound执行,而链表中的顺序为head->out1->out2->in1->in2->tail,所以会继续执行到out2、out1
2、如果在InboundHandler2中执行的是ctx.writeAndFlush,执行顺序是:
InboundHandler1
InboundHandler2
OutboundHandler2
OutboundHandler1
结果证明,执行完InboundHandler2后,由于InboundHandler2中执行的是ctx.writeAndFlush,它会从InboundHandler2位置往前找Outbound执行,而链表中的顺序为head->out1->out2->in1->in2->tail,所以会继续执行到out2、out1
核心最容易让人误解的点总结:
1、ctx.writeAndFlush只会从当前的handler位置开始,往前找outbound执行
2、ctx.pipeline().writeAndFlush与ctx.channel().writeAndFlush会从tail的位置开始,往前找outbound执行
相信你看到这里,基本能掌握channelHandlerContext调用与pipeline、channel调用的区别,但我敢肯定你只能记住3~5天就又忘记了;所以我再加一句记忆方法:
每次add一个channelHandler都会创建一个channelHandlerContext与之绑定,channelHandlerContext的作用就是管理它所关联的channelHandler和在同一个pipeline中的其他channelHandler之间的交互,他是什么?他与某个channelHandler绑定,权利有限,只能从当前他所绑定的channelHandler开始搞事情;
而pipeline与channel比较屌,可以指挥从头或者尾开始搞。
注:channelRead以及channelActive等这些都会接着pipeline传递
参考:
一文搞懂Netty中Handler的执行顺序
ctx.close() 和 ctx.channel().close() 到底有何区别?
网友评论