99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

Netty字節(jié)數(shù)據(jù)的容器ByteBuf

2022-04-21 09:12 更新

既然所有的網(wǎng)絡(luò)通信都是要基于底層的字節(jié)流來(lái)傳輸,那么傳輸所使用的數(shù)據(jù)接口就要求是效率高得、使用方便的而且容易使用的,NettyByteBuf更好能夠達(dá)到這些要求。

ByteBuf 是一個(gè)已經(jīng)經(jīng)過(guò)優(yōu)化的很好使用的數(shù)據(jù)容器,字節(jié)數(shù)據(jù)可以有效的被添加到 ByteBuf 中或者也可以從 ByteBuf 中直接獲取數(shù)據(jù)。ByteBuf中有兩個(gè)索引:一個(gè)用來(lái)讀,一個(gè)用來(lái)寫(xiě)。這兩個(gè)索引達(dá)到了便于操作的目的。我們可以按順序的讀取數(shù)據(jù),也可以通過(guò)調(diào)整讀取數(shù)據(jù)的索引或者直接將讀取位置索引作為參數(shù)傳遞給get方法來(lái)重復(fù)讀取數(shù)據(jù)。

ByteBuf 的工作原理

寫(xiě)入數(shù)據(jù)到 ByteBuf 后,writerIndex(寫(xiě)入索引)增加寫(xiě)入的字節(jié)數(shù)。讀取字節(jié)后,readerIndex(讀取索引)也增加讀取出的字節(jié)數(shù)。你可以讀取字節(jié),直到寫(xiě)入索引和讀取索引處在相同的位置。此時(shí)ByteBuf不可讀,所以下一次讀操作將會(huì)拋出 IndexOutOfBoundsException,就像讀取數(shù)組時(shí)越位一樣。

調(diào)用 ByteBuf 的以 "read" 或 "write" 開(kāi)頭的任何方法都將自動(dòng)增加相應(yīng)的索引。另一方面,"set" 、 "get"操作字節(jié)將不會(huì)移動(dòng)索引位置,它們只會(huì)在指定的相對(duì)位置上操作字節(jié)。

可以給ByteBuf指定一個(gè)最大容量值,這個(gè)值限制著B(niǎo)yteBuf的容量。任何嘗試將寫(xiě)入超過(guò)這個(gè)值的數(shù)據(jù)的行為都將導(dǎo)致拋出異常。ByteBuf 的默認(rèn)最大容量限制是 Integer.MAX_VALUE。

ByteBuf 類似于一個(gè)字節(jié)數(shù)組,最大的區(qū)別是讀和寫(xiě)的索引可以用來(lái)控制對(duì)緩沖區(qū)數(shù)據(jù)的訪問(wèn)。下圖顯示了一個(gè)容量為16的空的 ByteBuf 的布局和狀態(tài),writerIndex 和 readerIndex 都在索引位置 0 :

11385343fbf2b2119fb390fced3374300dd78e19

ByteBuf 使用模式

HEAP BUFFER(堆緩沖區(qū))

最常用的模式是 ByteBuf 將數(shù)據(jù)存儲(chǔ)在 JVM 的堆空間,這是通過(guò)將數(shù)據(jù)存儲(chǔ)在數(shù)組的實(shí)現(xiàn)。堆緩沖區(qū)可以快速分配,當(dāng)不使用時(shí)也可以快速釋放。它還提供了直接訪問(wèn)數(shù)組的方法,通過(guò) ByteBuf.array() 來(lái)獲取 byte[]數(shù)據(jù)。 這種方法,正如清單5.1中所示的那樣,是非常適合用來(lái)處理遺留數(shù)據(jù)的。

Listing 5.1 Backing array

ByteBuf heapBuf = ...;
if (heapBuf.hasArray()) {                //1
    byte[] array = heapBuf.array();        //2
    int offset = heapBuf.arrayOffset() + heapBuf.readerIndex();                //3
    int length = heapBuf.readableBytes();//4
    handleArray(array, offset, length); //5
}

1.檢查 ByteBuf 是否有支持?jǐn)?shù)組。

2.如果有的話,得到引用數(shù)組。

3.計(jì)算第一字節(jié)的偏移量。

4.獲取可讀的字節(jié)數(shù)。

5.使用數(shù)組,偏移量和長(zhǎng)度作為調(diào)用方法的參數(shù)。

注意:

  • 訪問(wèn)非堆緩沖區(qū) ByteBuf 的數(shù)組會(huì)導(dǎo)致UnsupportedOperationException, 可以使用 ByteBuf.hasArray()來(lái)檢查是否支持訪問(wèn)數(shù)組。
  • 這個(gè)用法與 JDK 的 ByteBuffer 類似

DIRECT BUFFER(直接緩沖區(qū))

“直接緩沖區(qū)”是另一個(gè) ByteBuf 模式。對(duì)象的所有內(nèi)存分配發(fā)生在 堆,對(duì)不對(duì)?好吧,并非總是如此。在 JDK1.4 中被引入 NIO 的ByteBuffer 類允許 JVM 通過(guò)本地方法調(diào)用分配內(nèi)存,其目的是

  • 通過(guò)免去中間交換的內(nèi)存拷貝, 提升IO處理速度; 直接緩沖區(qū)的內(nèi)容可以駐留在垃圾回收掃描的堆區(qū)以外。
  • DirectBuffer 在 -XX:MaxDirectMemorySize=xxM大小限制下, 使用 Heap 之外的內(nèi)存, GC對(duì)此”無(wú)能為力”,也就意味著規(guī)避了在高負(fù)載下頻繁的GC過(guò)程對(duì)應(yīng)用線程的中斷影響.(詳見(jiàn)http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html.)

這就解釋了為什么“直接緩沖區(qū)”對(duì)于那些通過(guò) socket 實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)膽?yīng)用來(lái)說(shuō),是一種非常理想的方式。如果你的數(shù)據(jù)是存放在堆中分配的緩沖區(qū),那么實(shí)際上,在通過(guò) socket 發(fā)送數(shù)據(jù)之前,JVM 需要將先數(shù)據(jù)復(fù)制到直接緩沖區(qū)。

但是直接緩沖區(qū)的缺點(diǎn)是在內(nèi)存空間的分配和釋放上比堆緩沖區(qū)更復(fù)雜,另外一個(gè)缺點(diǎn)是如果要將數(shù)據(jù)傳遞給遺留代碼處理,因?yàn)閿?shù)據(jù)不是在堆上,你可能不得不作出一個(gè)副本,如下:

Listing 5.2 Direct buffer data access

ByteBuf directBuf = ...
if (!directBuf.hasArray()) {            //1
    int length = directBuf.readableBytes();//2
    byte[] array = new byte[length];    //3
    directBuf.getBytes(directBuf.readerIndex(), array);        //4    
    handleArray(array, 0, length);  //5
}

1.檢查 ByteBuf 是不是由數(shù)組支持。如果不是,這是一個(gè)直接緩沖區(qū)。

2.獲取可讀的字節(jié)數(shù)

3.分配一個(gè)新的數(shù)組來(lái)保存字節(jié)

4.字節(jié)復(fù)制到數(shù)組

5.將數(shù)組,偏移量和長(zhǎng)度作為參數(shù)調(diào)用某些處理方法

顯然,這比使用數(shù)組要多做一些工作。因此,如果你事前就知道容器里的數(shù)據(jù)將作為一個(gè)數(shù)組被訪問(wèn),你可能更愿意使用堆內(nèi)存。

COMPOSITE BUFFER(復(fù)合緩沖區(qū))

最后一種模式是復(fù)合緩沖區(qū),我們可以創(chuàng)建多個(gè)不同的 ByteBuf,然后提供一個(gè)這些 ByteBuf 組合的視圖。復(fù)合緩沖區(qū)就像一個(gè)列表,我們可以動(dòng)態(tài)的添加和刪除其中的 ByteBuf,JDK 的 ByteBuffer 沒(méi)有這樣的功能。

Netty 提供了 ByteBuf 的子類 CompositeByteBuf 類來(lái)處理復(fù)合緩沖區(qū),CompositeByteBuf 只是一個(gè)視圖。

警告

CompositeByteBuf.hasArray() 總是返回 false,因?yàn)樗赡芗劝丫彌_區(qū),也包含直接緩沖區(qū)

例如,一條消息由 header 和 body 兩部分組成,將 header 和 body 組裝成一條消息發(fā)送出去,可能 body 相同,只是 header 不同,使用CompositeByteBuf 就不用每次都重新分配一個(gè)新的緩沖區(qū)。下圖顯示CompositeByteBuf 組成 header 和 body:

Figure 5.2 CompositeByteBuf holding a header and body

Figure%205

下面代碼顯示了使用 JDK 的 ByteBuffer 的一個(gè)實(shí)現(xiàn)。兩個(gè) ByteBuffer 的數(shù)組創(chuàng)建保存消息的組件,第三個(gè)創(chuàng)建用于保存所有數(shù)據(jù)的副本。

Listing 5.3 Composite buffer pattern using ByteBuffer

// 使用數(shù)組保存消息的各個(gè)部分
ByteBuffer[] message = { header, body };

// 使用副本來(lái)合并這兩個(gè)部分
ByteBuffer message2 = ByteBuffer.allocate(
        header.remaining() + body.remaining());
message2.put(header);
message2.put(body);
message2.flip();

這種做法顯然是低效的;分配和復(fù)制操作不是最優(yōu)的方法,操縱數(shù)組使代碼顯得很笨拙。

下面看使用 CompositeByteBuf 的改進(jìn)版本

Listing 5.4 Composite buffer pattern using CompositeByteBuf

CompositeByteBuf messageBuf = ...;
ByteBuf headerBuf = ...; // 可以支持或直接
ByteBuf bodyBuf = ...; // 可以支持或直接
messageBuf.addComponents(headerBuf, bodyBuf);
// ....
messageBuf.removeComponent(0); // 移除頭    //2

for (int i = 0; i < messageBuf.numComponents(); i++) {                        //3
    System.out.println(messageBuf.component(i).toString());
}

1.追加 ByteBuf 實(shí)例的 CompositeByteBuf

2.刪除 索引1的 ByteBuf

3.遍歷所有 ByteBuf 實(shí)例。

清單5.4 所示,你可以簡(jiǎn)單地把 CompositeByteBuf 當(dāng)作一個(gè)可迭代遍歷的容器。 CompositeByteBuf 不允許訪問(wèn)其內(nèi)部可能存在的支持?jǐn)?shù)組,也不允許直接訪問(wèn)數(shù)據(jù),這一點(diǎn)類似于直接緩沖區(qū)模式,如圖5.5所示。

Listing 5.5 Access data

CompositeByteBuf compBuf = ...;
int length = compBuf.readableBytes();    //1
byte[] array = new byte[length];        //2
compBuf.getBytes(compBuf.readerIndex(), array);    //3
handleArray(array, 0, length);    //4

1.得到的可讀的字節(jié)數(shù)。

2.分配一個(gè)新的數(shù)組,數(shù)組長(zhǎng)度為可讀字節(jié)長(zhǎng)度。

3.讀取字節(jié)到數(shù)組

4.使用數(shù)組,把偏移量和長(zhǎng)度作為參數(shù)

Netty 嘗試使用 CompositeByteBuf 優(yōu)化 socket I/O 操作,消除 原生 JDK 中可能存在的的性能低和內(nèi)存消耗問(wèn)題。雖然這是在Netty 的核心代碼中進(jìn)行的優(yōu)化,并且是不對(duì)外暴露的,但是作為開(kāi)發(fā)者還是應(yīng)該意識(shí)到其影響。

CompositeByteBuf API

CompositeByteBuf 提供了大量的附加功能超出了它所繼承的 ByteBuf。請(qǐng)參閱的 Netty 的 Javadoc 文檔 API。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)