文章目錄
- 概念
- ByteBuf VS Java NIO Buffer
- ByteBuf實現類
- HeapByteBuf vs DirectByteBuf
- PooledByteBuf vs UnpooledByteBuf
- 其他
- ByteBuf的實現機制

概念
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。