Netty实战-ByteBuf

Java NIO中的Buffer用于和NIO通道进行交互,数据可以从通道读入缓冲区,也可以从缓冲区写入到通道中。所以说,Buffer其实就是一块可以读写数据的内存,我们将其包装为一个Java对象来提供一系列读写操作。Netty并没有直接使用Java NIO的Buffer实现,而是自己实现了一套Buffer框架来满足自己的业务或者性能需求。

ByteBuf的优点:

  • 可以自定义的缓冲区类型扩展
  • 通过内置的复合缓冲区类型实现了透明的零拷贝
  • 容量可以按需增长(类似于 JDK 的 StringBuilder)
  • 在读和写这两种模式之间切换不需要调用 ByteBuffer 的 flip()方法
  • 读和写使用了不同的索引
  • 支持方法的链式调用
  • 支持引用计数
  • 支持池化

ByteBuf如何工作

ByteBuf称作Netty的数据容器,如下,一个ByteBuf被两个pointers分成三个区域。

      +-------------------+------------------+------------------+
      | discardable bytes |  readable bytes  |  writable bytes  |
      |                   |     (CONTENT)    |                  |
      +-------------------+------------------+------------------+
      |                   |                  |                  |
      0      <=      readerIndex   <=   writerIndex    <=    capacity

3个区域:废弃区,可读区和可写区

  • 在初始化状态下,readerIndex和writerIndex都为0,整个空间中只存在可写区。此时只能写,不能读,进行读操作会抛出异常。
  • 写字节后,writeIndex增加,readIndex不变。
  • 读字节时,writeIndex不变,readIndex增加。
  • 如果discardable区域被回收,两个pointer都向左平移。
  • 如果调用clear(),两个pointer都回到0位置。
  • readerIndex > writerIndex, 将会抛异常IndexOutOfBoundsException。
  • writerIndex 超过最大容量也会触发异常

当然,实际上除了数据负载外,还需要存储各种属性值,如http响应的状态码和cookie等。Netty提供了ByteBufHolder,其中content()返回了所持有的ByteBuf。

字节级操作

名称以 read 或者 write 开头的 ByteBuf 方法,将会推进其对应的索引,而名称以set或者get开头的操作则不会。这个很关键,用错了可能导致一直读取同一份数据。

ByteBuf buffer = ...;
for (int i = 0; i < buffer.capacity(); i++) {
    byte b = buffer.getByte(i);// 不会改变index
    System.out.println((char)b);
}
ByteBuf buffer = ...;
while (buffer.isReadable()) {
    System.out.println(buffer.readByte());
}

while (buffer.maxWritableBytes() >= 4) {
    buffer.writeInt(random.nextInt());
}

查找

ByteBuf buffer = ...;
int index = buffer.forEachByte(ByteProcessor.FIND_CR);

还可以派生出一个新的ByteBuf实例,或者完全复制出一个新副本。切片是共享的,copy不共享,完全独立的副本。

ByteBuf的特殊机制

buffer池:减少分配释放的压力,

零拷贝
是指计算机操作的过程中,CPU不需要为数据在内存之间的拷贝消耗资源。如计算机在网络上发送文件时,不需要将文件内容拷贝到用户空间(User Space)而直接在内核空间(Kernel Space)中传输到网络的方式。Netty通过ByteBuf.slice以及Unpooled.wrappedBuffer等方法拆分、合并Buffer无需拷贝数据。


参考文档:

CONTENTS