概念
ByteBuf是Netty中用于处理二进制数据的缓冲区
Netty的ByteBuf是一个可用于高效存储和操作字节数据的数据结构。与传统的ByteBuffer相比,ByteBuf提供了更灵活、更强大的API。
主要特性:
- 可扩展性: ByteBuf支持动态扩展,可以自动扩展其容量以适应数据的增长。
- 读写索引分离: 与ByteBuffer不同,ByteBuf有独立的读和写索引。这意味着可以读取和写入数据而无需手动切换模式。
- 零拷贝: ByteBuf支持零拷贝操作,可以提高性能并降低内存复制的开销。
- 池化支持: Netty提供了ByteBuf的池化支持,可帮助有效地重用内存以减少垃圾收集的压力。
ByteBuf VS Java NIO Buffer
ByteBuf则是Java NIO Buffer的新轮子,官方列出了一些ByteBuf的特性:
- 需要的话,可以自定义buffer类型;
- 通过组合buffer类型,可实现透明的zero-copy;
- 提供动态的buffer类型,如StringBuffer一样,容量是按需扩展;
- 无需调用flip()方法
- …
ByteBuf实现类
ByteBuf提供了一些较为丰富的实现类,逻辑上主要分为两种:
HeapByteBuf
DirectByteBuf
实现机制则分为两种:
PooledByteBuf
UnpooledByteBuf
除了这些之外,Netty还实现了一些衍生ByteBuf(DerivedByteBuf)
,如:ReadOnlyByteBuf
、DuplicatedByteBuf
以及SlicedByteBuf
。
HeapByteBuf vs DirectByteBuf
HeapByteBuf
和DirectByteBuf
区别在于Buffer的管理方式:
HeapByteBuf
由Heap管理,Heap是Java堆的意思,内部实现直接采用byte[] array;DirectByteBuf
使用是堆外内存,Direct应是采用Direct I/O之意,内部实现使用java.nio.DirectByteBuffer
。
PooledByteBuf vs UnpooledByteBuf
UnpooledByteBuf
实现就是普通的ByteBuf了PooledByteBuf
是4.x之后的新特性
其他
DerivedByteBuf
是ByteBuf衍生类,实现采用装饰器模式对原有的ByteBuf进行了一些封装。ReadOnlyByteBuf
是某个ByteBuf的只读引用;DuplicatedByteBuf
是某个ByteBuf对象的引用;SlicedByteBuf
是某个ByteBuf的部分内容。
ByteBuf的实现机制
Netty中的ByteBuf是一个强大的字节容器,用于处理字节数据。它的实现机制相当复杂,其主要特点如下
- 内存分配: Netty的ByteBuf使用了一种称为池化的内存管理机制。这意味着它不是每次都直接分配新的内存,而是从预分配的内存池中获取。这有助于减少内存碎片化和提高性能。 4.x开发了Pooled Buffer,实现了一个高性能的buffer池,分配策略则是结合了buddy allocation和slab allocation的jemalloc变种,代码在io.netty.buffer.PoolArena
- 引用计数: ByteBuf使用了引用计数机制来跟踪对它的引用。这种方式允许多个部分同时引用同一个ByteBuf,而不会导致内存泄漏。当引用计数降至零时,内存将被释放回池。
- 可读写的索引: ByteBuf通过维护两个索引来实现读写操作,分别是读索引(readerIndex)和写索引(writerIndex)。这两个索引允许你从中读取数据或将数据写入,而不会相互影响。
- 零拷贝: Netty的ByteBuf支持零拷贝的特性,这意味着在某些情况下,数据可以在不涉及实际数据复制的情况下传递给其他组件。这对于提高性能和降低资源消耗非常重要。 Zero-copy与传统意义的zero-copy不太一样。传统的zero-copy是IO传输过程中,数据无需中内核态到用户态、用户态到内核态的数据拷贝,减少拷贝次数。而Netty的zero-copy则是完全在用户态,或者说传输层的zero-copy机制,如下图。 由于协议传输过程中,通常会有拆包、合并包的过程,一般的做法就是System.arrayCopy了,但是Netty通过ByteBuf.slice以及Unpooled.wrappedBuffer等方法拆分、合并Buffer无需拷贝数据。 如何实现zero-copy的呢。slice实现就是创建一个SlicedByteBuf对象,将this对象,以及相应的数据指针传入即可,wrappedBuffer实现机制类似
- Composite ByteBuf: Netty提供了CompositeByteBuf,它是一种特殊的ByteBuf,可以将多个ByteBuf组合成一个逻辑上的ByteBuf。这使得可以在不实际复制数据的情况下聚合多个缓冲区
ByteBuf buffer1 = Unpooled.copiedBuffer("Hello, ".getBytes());
ByteBuf buffer2 = Unpooled.copiedBuffer("Netty!".getBytes());
CompositeByteBuf compositeBuffer = allocator.compositeBuffer();
compositeBuffer.addComponent(true, buffer1);
compositeBuffer.addComponent(true, buffer2);
// 使用compositeBuffer进行操作,它看起来像一个大的ByteBuf
CompositeByteBuf可以将多个ByteBuf组合成一个逻辑上的ByteBuf。