Netty之Bytebuf的輔助類

目錄

Bytebuf類別

ByteBufHolder

ByteBufAllocator

CompositeByteBuf

ByteBufUtil



Bytebuf類別

Bytebuf的繼承圖

   

 Bytebuf的分類

  從內存角度

    堆內存字節緩衝區(HeapBytebuf)

      優點:堆內存的分配和回收速度快,可以被JVM自動回收。

      缺點:如果進行Socket的I/O讀寫的時候還需要一次複製,將字節複製到堆內存外的內存,然後使用,所以性能會有一定程度的下降

    直接內存字節緩衝區(DirectBytebuf)

      優點:不需要一次額外的字節複製,讀寫速度回快一些

      缺點:內存分配和回收要慢一些

 Bytebuf的最佳實踐:在I/O通信線程使用過程是推薦使用DirectBytebuf,因爲不會每次讀寫都會創建新的Bytebuf對象,

                                  在後端業務消息的編碼模塊推薦使用HeapBytebuf,因爲Bytebuf對象的回收和創建要快一些

 從內存回收的角度

  基於對象池的PooledByteBuf

   優點:基於對象池的Bytebuf會重用Bytebuf對象,在PooledByteBuf內部維護了一個對象池,每次從池中獲取Bytebuf,減少了創建和銷燬Bytebuf對象的消耗,提高了內存的使用率。

   缺點:對象池的維護和管理操作複雜

  另外一種是普通Bytebuf,優缺點則和對象池相反

最佳實踐:推薦使用對象池Bytebuf

創建Bytebuf

基於UnpooledHeapByteBuf類型(常用)

 ByteBuf buf = Unpooled.buffer(initialCapacity)  創建一個給定大小的ByteBuf
 ByteBuf buf1 = Unpooled.copiedBuffer(byte byte[]); 將一個byte數組複製給ByteBuf

基於UnpooledDirectByteBuf類型

ByteBuf buf = Unpooled.directBuffer(initialCapacity)

基於堆內存的池對象

  PooledByteBufAllocator pool = new PooledByteBufAllocator();
  ByteBuf heapBuf = pool.buffer(initialCapacity);

 基於直接內存的池對象

  PooledByteBufAllocator pool = new PooledByteBufAllocator();
  ByteBuf dirctBuf = pool.directBuffer(initialCapacity);

ByteBufHolder

我們經常在ByteBuf中存儲一些正常數據之外,我們有時候還需要增加一些各式各樣的屬性值,一個Http響應體就是一個很好的例子,除了按照字節傳輸過來的主體內容,還有狀態碼,cookie等信息

Netty提供了ByteBufHolder來處理這些常用的用戶案例,ByteBufHolder還提供了Netty一些其他的先進特性,例如緩存池,緩存池可以是ByteBuf中直接“借出”獲取,如果有需要,“借出”的ByteBuf還可以自動的還到池中

ByteBufHolder提供了一系列的獲取底層數據和引用計數的方法,表5.6向你展示了一些常用的方法

如果你想要實現一個消息對象可以在ByteBuf中存儲其有效負荷的話,使用ByteBufHolder是一個不錯的選擇

ByteBufAllocator

ByteBufAllocator

爲了減少分配和釋放內存的開銷,Netty 通過支持池類 ByteBufAllocator,可用於分配的任何 ByteBuf 我們已經描述過的類型的實例。是否使用池是由應用程序決定的,列出了 ByteBufAllocator 提供的操作。

名稱 描述
buffer() buffer(int) buffer(int, int) Return a ByteBuf with heap-based or direct data storage.
heapBuffer() heapBuffer(int) heapBuffer(int, int) Return a ByteBuf with heap-based storage.
directBuffer() directBuffer(int) directBuffer(int, int) Return a ByteBuf with direct storage.
compositeBuffer() compositeBuffer(int) heapCompositeBuffer() heapCompositeBuffer(int) directCompositeBuffer()directCompositeBuffer(int) Return a CompositeByteBuf that can be expanded by adding heapbased or direct buffers.
ioBuffer() Return a ByteBuf that will be used for I/O operations on a socket.

通過一些方法接受整型參數允許用戶指定 ByteBuf 的初始和最大容量值。你可能還記得,ByteBuf 存儲可以擴大到其最大容量。

得到一個 ByteBufAllocator 的引用很簡單。你可以得到從 Channel (在理論上,每 Channel 可具有不同的 ByteBufAllocator ),或通過綁定到的 ChannelHandler 的 ChannelHandlerContext 得到它,用它實現了你數據處理邏輯。

下面的列表說明獲得 ByteBufAllocator 的兩種方式。

Channel channel = ...;
ByteBufAllocator allocator = channel.alloc(); //1
....
ChannelHandlerContext ctx = ...;
ByteBufAllocator allocator2 = ctx.alloc(); //2
...

1.從 channel 獲得 ByteBufAllocator

2.從 ChannelHandlerContext 獲得 ByteBufAllocator

Netty 提供了兩種 ByteBufAllocator 的實現,一種是 PooledByteBufAllocator,用ByteBuf 實例池改進性能以及內存使用降到最低,此實現使用一個“jemalloc”內存分配。其他的實現不池化 ByteBuf 情況下,每次返回一個新的實例。

Netty 默認使用 PooledByteBufAllocator,我們可以通過 ChannelConfig 或通過引導設置一個不同的實現來改變。更多細節在後面講述 ,見 Chapter 9, "Bootstrapping Netty Applications"

CompositeByteBuf

CompositeBytebuf允許將多個Bytebuf的實例組合起來,在內部使用一個Bytebuf進行統一管理。

例如在協議中一個協議通常會包含多個部分,消息體,消息頭等,他們都是Bytebuf對象,如果我們需要對他進行管理,可以把這些Bytebuf對象都放到CompositeBytebuf中進行統一管理

 

public class Test {
	public static void bytebuf() {
		
		PooledByteBufAllocator pool = new PooledByteBufAllocator(); 
		CompositeByteBuf buf = new CompositeByteBuf(pool, true, 2000);
		byte[] b1 = {1,2,3};
		byte[] b2 = {4,5,6};
		buf.addComponent(Unpooled.copiedBuffer(b1));
		buf.addComponent(Unpooled.copiedBuffer(b2));
		byte b = buf.getByte(3);
		
		System.out.println(b);
	}
	
	public static void main(String[] args) {
		Test.bytebuf();
	}
}

結果是 4;

ByteBufUtil

 這個是ByteBuf的一個靜態工具類

 常用的有 encodeString():對字符串進行編碼,生存ByteBuf對象

                decodeString():對字符串進行解碼,生存ByteBuf對象

                 hexDump():能夠將參數ByteBuf的內容轉換爲十六進制的字符串

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章