Netty 消息构造干扰
我碰到了一个问题,看起来是这样的: 1) 我在ByteToMessageDecoder中构建了约70Kb的长消息—我们称之为BlockMessage 2) 同时还有一个打乒乓球的计时器, 即发送Ping和get的Pong都是短~8字节的消息。 (!!!)问题是,有时我会看到Pong消息干扰BlockMessage,这会破坏消息结构 可以这样描述: 1) 我正在这个过程中 阅读信息的方式:Netty 消息构造干扰,netty,Netty,我碰到了一个问题,看起来是这样的: 1) 我在ByteToMessageDecoder中构建了约70Kb的长消息—我们称之为BlockMessage 2) 同时还有一个打乒乓球的计时器, 即发送Ping和get的Pong都是短~8字节的消息。 (!!!)问题是,有时我会看到Pong消息干扰BlockMessage,这会破坏消息结构 可以这样描述: 1) 我正在这个过程中 阅读信息的方式: @Override protected void decode(ChannelHandlerContext
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
// No header for Eth. message
if (in.readableBytes() < 8) return;
long magicBytes = in.readUnsignedInt();
long msgSize = in.readUnsignedInt();
if (!((magicBytes >> 24 & 0xFF) == 0x22 &&
(magicBytes >> 16 & 0xFF) == 0x40 &&
(magicBytes >> 8 & 0xFF) == 0x08 &&
(magicBytes & 0xFF) == 0x91 )) {
logger.error("abandon garbage, wrong magic bytes: [ {} ] msgSize: [ {} ]", magicBytes, msgSize);
ctx.close();
}
// Don't have the full packet yet
if (msgSize > in.readableBytes()) {
logger.debug("msg decode: magicBytes: [ {} ], readBytes: [ {} ] / msgSize: [ {} ] ", magicBytes, in.readableBytes(), msgSize);
in.resetReaderIndex();
return;
}
logger.debug("message fully constructed go handle it: readBytes: [ {} ] / msgSize: [ {} ]", in.readableBytes(), msgSize);
byte[] decoded = new byte[(int)msgSize];
in.readBytes(decoded);
out.add(decoded);
in.markReaderIndex();
}
@覆盖
受保护的无效解码(ChannelHandlerContext ctx、ByteBuf输入、列表输出)引发异常{
//没有Eth.message的头
if(in.readableBytes()<8)返回;
long magicBytes=in.readUnsignedInt();
long msgSize=in.readUnsignedInt();
如果(!((magicBytes>>24&0xFF)==0x22&&
(magicBytes>>16&0xFF)==0x40&&
(magicBytes>>8&0xFF)==0x08&&
(magicBytes&0xFF)==0x91){
错误(“放弃垃圾,错误的魔法字节:[{}]msgSize:[{}]”,magicBytes,msgSize);
ctx.close();
}
//我还没有收到完整的包裹
if(msgSize>in.readableBytes()){
debug(“msg decode:magicBytes:[{}],readBytes:[{}]/msgSize:[{}]”,magicBytes,in.readableBytes(),msgSize);
in.resetReaderIndex();
返回;
}
debug(“完全构造的消息处理:readBytes:[{}]/msgSize:[{}]”,in.readableBytes(),msgSize);
字节[]已解码=新字节[(int)msgSize];
in.readBytes(已解码);
输出。添加(解码);
in.markReaderIndex();
}
2) 同时:计时器调用ping并从
同行
3) 我把这个乒乓球放在镜框里(1)
我认为这是一个非常简单和常见的情况,但我没有找到任何例子和
问题是如何避免帧干扰
我使用的提示:
4.0.17.最终
我找到了根本原因和解决方案:
(问题)当大消息到达时,它被构造成一条消息
字节流外数据包。在此期间,不应发出任何其他信息
在那个频道被问到,即使是很小的乒乓球也会干扰
并在结构中插入损坏的数据
(解决方案)为了避免干扰,我使用队列顺序
仅当完整的消息被
接收到的下一个往返调用,无论是
乒乓球或其他请求/响应。您能详细描述一下它们是如何干扰的吗。write(..)设计用于处理并发。更新了信息,现在更好了吗?如何将这两条消息写入通道?您是使用一次调用来编写大型消息,还是将其分解?您的解码器是否在多个频道之间共享?很少有事情会导致这种情况,但是,正如mdu 5所说,如果您只需要编写两个单独的调用,每个消息一个,并且您使用的是TCP,那么这种情况不应该发生——ping应该被卡在块消息后面。