Netty 解码器-ReplayingDecoder

它是ByteToMessageDecoder的一种变体,支持在阻塞I/O中实现非阻塞解码器。它不需要像 ByteToMessageDecoderdecode()方法中需要检查所需字节的可用性。

ReplayingDecoder 是如何运作的?

看一个例子:

//ByteToMessageDecoder实现:
public class IntegerHeaderFrameDecoder extends ByteToMessageDecoder {

  @Override
 protected void decode(ChannelHandlerContext ctx,ByteBuf buf, List<Object> out) throws Exception {
   if (buf.readableBytes() < 4) {
	  return;
   }

   buf.markReaderIndex();
   int length = buf.readInt();

   if (buf.readableBytes() < length) {
	  buf.resetReaderIndex();
	  return;
   }

   out.add(buf.readBytes(length));
 }
}

// 使用ReplayingDecoder简化如下:
public class IntegerHeaderFrameDecoder
	extends ReplayingDecoder<Void> {

 protected void decode(ChannelHandlerContext ctx,ByteBuf buf, List<Object> out) throws Exception {
   out.add(buf.readBytes(buf.readInt()));
 }
}

在IntegerHeaderFrameDecoder 类中,调用 buf.readInt()时会有两种情况:

  1. 缓冲区中有4个或更多字节,它将按预期返回整数index。
  2. 缓冲区中不足4个字节,将会引发Error并将控制权返回给ReplayingDecoder,当ReplayingDecoder捕获到Error ,那么它会将缓冲区的readerIndex倒回到“初始”位置(即缓冲区的开头),并在缓冲区接收到更多数据时再次调用decode(..) 方法。

以简单为代价,ReplayingDecoder 可能会多次调用 decode() 方法来解码某个消息,这会有性能损失。

使用checkpint(T)方法提高性能

幸运的是,可以使用checkpoint()方法可以显著提高解码器性能。checkpoint()更新缓冲区的readerIndex位置倒回到您调用checkpoint()方法的最后一个位置。
管理解码器状态最简单的方法是创建一个代表解码器当前状态的 Enum 类型,每次状态改变时,就调用 checkpoint(T)

public enum MyDecoderState {
 READ_LENGTH,
 READ_CONTENT;
}

public class IntegerHeaderFrameDecoder
	extends ReplayingDecoder<MyDecoderState> {

 private int length;

 public IntegerHeaderFrameDecoder() {
   // Set the initial state.
   super(MyDecoderState.READ_LENGTH);
 }

  @Override
 protected void decode(ChannelHandlerContext ctx,ByteBuf buf, List<Object> out) throws Exception {
   switch (state()) {
   case READ_LENGTH:
	 length = buf.readInt();
	 checkpoint(MyDecoderState.READ_CONTENT);
   case READ_CONTENT:
	 ByteBuf frame = buf.readBytes(length);
	 checkpoint(MyDecoderState.READ_LENGTH);
	 out.add(frame);
	 break;
   default:
	 throw new Error("Shouldn't reach here.");
   }
 }
}
posted @ 2021-08-27 00:17  bakanano  阅读(459)  评论(0)    收藏  举报