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

How to decide the sequence of actions in Netty channel 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 对象之前。我很迷惑。我怎么知道我是否以正确的顺序放置了这些对象?

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

我很确定关于将编码器放在 HttpObjectAggregator 之前的建议是错字。编码器是 outbound 唯一的处理程序,而 HttpObjectAggregator 是 inbound 唯一的处理程序,这意味着事件永远不会与它们交互;所以他们的相对顺序很重要是没有意义的。

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

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

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

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

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

此措辞被指出为 typo/bug 的问题:https://github.com/netty/netty/issues/2471