如何确定Netty通道管道中的动作顺序

时间:2016-08-08 07:20:18

标签: websocket netty pipeline

例如,如果我想构建一个websocket服务器,我想知道应该在initChannel方法中放置什么。然后我在netty的源代码中找到了websocket示例,我需要在其中执行以下操作:

public void initChannel(final SocketChannel ch) throws Exception {
                ch.pipeline().addLast(
                    new HttpRequestDecoder(),
                    new HttpObjectAggregator(65536),
                    new HttpResponseEncoder(),
                    new WebSocketServerProtocolHandler("/websocket"),
                    new CustomTextFrameHandler());
            }

但我不知道为什么我需要按照这样的顺序放置对象。在HttpObjectAggregator的描述中,我发现了类似的内容:

Be aware that you need to have the {@link HttpResponseEncoder} or {@link HttpRequestEncoder} before the {@link HttpObjectAggregator} in the {@link ChannelPipeline}.

但是在上面的代码HttpObjectAggregator中,对象位于HttpResponseEncoder对象之前。我很迷惑。我如何知道我按正确顺序放置这些对象?

1 个答案:

答案 0 :(得分:1)

TLDR;您应该将HttpServerCodec放入init方法中,以保持简单。如果您选择使用聚合器,请在HttpObjectAggregator之前执行此操作。

我非常确定在HttpObjectAggregator之前放置编码器的建议是一个错字。编码器只有出站处理程序,而HttpObjectAggregator只是入站处理程序,这意味着事件永远不会与它们相互作用;所以他们的相对秩序无关紧要。

这里需要注意的是HttpObjectAggregator会在某些情况下写出HttpObjects(主要是100 CONTINUE),并且要将HttpObject转换为可以在线路上发送的byte [],它需要一个HttpResponseEncoder才能在管道。在传出时,管道被反向遍历,因此编码器之前的编码器将接收聚合器发送的消息,但是编码器在它获胜之后。您发布的示例代码中有一个错误,只有在需要发送100 CONTINUE时才会触发该错误。看起来这个错误是通过在聚合器之前用HttpServerCodec替换编码器/解码器来修复的。

解码器,如HttpRequestDecoder或HttpResponseDecoder只是一个入站处理程序,它们需要在HttpObjectAggregator之前才能正常运行。这是因为这两个解码器将byte[]转换为HttpObject,而HttpObjectAggregator实际上是消息解码器,将HttpObject转换为FullHttpMessage

Netty在一个类中引入了HttpServerCodec,它是HttpRequestDecoder和HttpResponseEncoder的组合。如果你把它放在你的聚合器之前,你将自己保存一行代码,并确保你的服务器有适当的编码器和解码器。

很好地参考了解邮件如何在入站和出站处理程序的管道中工作:https://netty.io/4.0/api/io/netty/channel/ChannelPipeline.html

首次引入此措辞的问题(注意没有提及编码,只提及解码):https://github.com/netty/netty/issues/2401

将此措辞指出为错字/错误的问题:https://github.com/netty/netty/issues/2471