我想我不理解某些不同课程的意图。
所以我有一个简单的管道,基本上它需要通过自定义方法(hadoop writables)进行序列化的顶级对象,然后尝试将它们转换为ByteBufs然后发送它们。所以我实现了一个OutboundFrameHandler,它接受消息对象,然后尝试序列化简单的帧,然后将其发送到上游。以下是实施:
public class OutboundFrameHandler extends MessageToByteEncoder<MsgType> {
public void encode(ChannelHandlerContext ctx, MsgType msg, ByteBuf out) throw Exception {
byte[] data = ...; // custom serialization mechanism
out.writeInt(data.length + 4);
out.writeInt(msg.callId);
out.writeBytes(data);
}
}
在运行时,我得到了这个:
警告:触发了exceptionCaught()事件,并在管道结束时到达。它通常意味着管道中的最后一个入站处理程序没有处理异常。 io.netty.channel.NoSuchBufferException:找不到合适的目标缓冲区。仔细检查管道是否配置正确,其处理程序是否按预期工作。
我查看了示例源代码,我注意到的一点是“编码”编解码器看起来更像是这样: public class StringEncoder扩展了MessageToMessageEncoder {}
和'encode'方法创建ByteBuf。
但我也注意到ProtobufVarint32LengthFieldPrepender扩展了MessageToByteEncoder并使用了ByteBuf out参数。我查看了源代码,我不确定'out'是如何设置的。它是通过调用ctx.nextOutboundByteBuffer()在MessageToByteEncoder'flush'中获得的,但我不清楚它是如何工作的。看看它是如何产生的,看起来这是在init期间设置的,其中一个处理程序需要从newOutboundBuffer返回ByteBuf。
进行向后分析,似乎从newOutboundBuffer()返回ByteBuf的唯一子类是ChannelOutboundByteHandlerAdapter。并且很少有子类。
所以看一下localtime示例,我不清楚ProtobufVarin32LengthFieldPrepender实际上是如何 WORKS 。看来,我使用MessageToByteEncoder时,我真正想要的是MessageToMessageEncoder
摘要问题: - 何时使用MessageToByteEncoder - 当管道中的处理程序似乎从newOutboundBuffer返回ByteBuf时,基于MessageToByteEncoder的编码器如何获得有效的出站buf?
**回答自己**
原来,(a)我没有排入正确的消息类型! (b)我潜水并发现HeadHandler,它似乎是“最后手段”的ByteBuf发电机。一切都很好。