[翻译]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 这样子流穿.
其实其他的事件, 也同理~