[翻译]Netty4中 Ctx.close 与 Ctx.channel.close 的区别
Contents
翻译
让我们假设在 pipeline 里有三个 handlers , 它们都都拦截 close()
方法操作, 并且在面里调用 ctx.close()
ChannelPipeline p = ...;
p.addLast("A", new SomeHandler());
p.addLast("B", new SomeHandler());
p.addLast("C", new SomeHandler());
...
public class SomeHandler extends ChannelOutboundHandlerAdapter {
@Override
public void close(ChannelHandlerContext ctx, ChannelPromise promise) {
ctx.close(promise);
}
}
Channel.close()
会触发C.close()
,B.close()
,A.clos()
, 然后再关闭 channelChannelPipeline.context("C").close()
会触发B.close()
,A.close()
, 然后再关闭 channelChannelPipeline.context("B").close()
会触发A.close()
, 然后再关闭 channelChannelPipeline.context("A").close()
则会直接关闭 channel. 不再会有 handlers 调用了.
因此, 什么时候应该使用 Channel.close()
和 ChannelHandlerContext.close()
? 最好规则如下:
- 如果你正写一个
ChannelHandler
, 并且想在这个 handler 中关闭 channel, 则调用ctx.close()
- 如果你正准备从一个外部的 handler (例如, 你有一个后台的非I/O线程, 并且你想从该线程中关闭连接). (译注: 这时是调用
Channel.close()
?)
总结
是不是, 整条流水线上, 如果后面的 handler 不用关心 close()
事件的话, 则用 ctx.close()
, 否则用 channel.close()
.
就像官方文档中对 pipeline 的描述那样, ctx.write()
是从当前的 handler 中, 写到离它最近的 out handler
中, 而不是从流水线最后开始从头穿过处理一样~
官方关于流水线的文档: doc
新手容易引起的流水线问题
pipeline 中的顺序是非常重要的~比如, 有个程序这样子初始化 pipeline:
@Override
protected void initChannel(final Channel ch) {
ChannelPipeline p = ch.pipeline();
p.addLast(new HttpRequestDecoder());
p.addLast(new HttpResponseEncoder());
p.addLast(new InHandler1());
p.addLast(new InHandler2());
p.addLast(new OutHandler1());
p.addLast(new OutHandler2());
}
如果在 InHandler2
中, 调用了 write(...)
则不会触发调用 OutHandler2
和 OutHandler1
的, 因为 ctx.write(...)
只会触发离它最近的 out handler
, 但是, InHandler2
前面没有 out handler
了~
但, 如果通过 channel.write(...)
的话, 则它会从 OutHandler2 -> OutHandler1
这样子流穿.
其实其他的事件, 也同理~