我想我不理解某些不同课程的意图。
所以我有一个简单的管道,基本上它采用通过自定义方法(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 extends MessageToMessageEncoder {}
'encode' 方法创建 ByteBuf。
但我也注意到 ProtobufVarint32LengthFieldPrepender 扩展了 MessageToByteEncoder 并使用了 ByteBuf out 参数。我查看了源代码,但我不确定“out”是如何设置的。它是通过调用 ctx.nextOutboundByteBuffer() 在 MessageToByteEncoder 'flush' 中获得的,但我不清楚这是如何工作的。看看这是怎么发生的,看起来这是在 init 期间设置的,其中一个处理程序需要从 newOutboundBuffer 返回一个 ByteBuf。
进行向后分析,似乎唯一从 newOutboundBuffer() 返回 ByteBuf 的子类是 ChannelOutboundByteHandlerAdapter。而且它的子类很少。
所以看看本地时间的例子,我不清楚 ProtobufVarin32LengthFieldPrepender 是如何工作的。看来,当我使用 MessageToByteEncoder 时,我真正想要的是 MessageToMessageEncoder
摘要问题: - 什么时候使用 MessageToByteEncoder - 当管道中似乎没有处理程序从 newOutboundBuffer 返回 ByteBuf 时,基于 MessageToByteEncoder 的编码器如何获得有效的出站 buf?
** 回答我自己 **
结果是(a)我没有将正确的消息类型排入队列!(b) 我发现了 HeadHandler,它似乎是“最后的手段”的 ByteBuf 生成器。现在一切都很好。