鍍金池/ 教程/ Java/ 豐富的緩沖實(shí)現(xiàn)
Netty 實(shí)現(xiàn) WebSocket 聊天功能
總結(jié)
寫(xiě)個(gè)時(shí)間客戶(hù)端
寫(xiě)個(gè)丟棄服務(wù)器
問(wèn)題
開(kāi)始之前
關(guān)閉你的應(yīng)用
開(kāi)始
用POJO代替ByteBuf
總結(jié)
架構(gòu)總覽
豐富的緩沖實(shí)現(xiàn)
解決
寫(xiě)個(gè)應(yīng)答服務(wù)器
I/O API 統(tǒng)一的異步 I/O API
適用快速開(kāi)發(fā)的高級(jí)組件
處理一個(gè)基于流的傳輸
Netty 實(shí)現(xiàn)聊天功能
基于攔截鏈模式的事件模型
寫(xiě)個(gè)時(shí)間服務(wù)器
查看收到的數(shù)據(jù)

豐富的緩沖實(shí)現(xiàn)

Netty 使用自建的 buffer API,而不是使用 NIO 的 ByteBuffer 來(lái)表示一個(gè)連續(xù)的字節(jié)序列。與 ByteBuffer 相比這種方式擁有明顯的優(yōu)勢(shì)。Netty 使用新的 buffer 類(lèi)型 ByteBuf,被設(shè)計(jì)為一個(gè)可從底層解決 ByteBuffer 問(wèn)題,并可滿(mǎn)足日常網(wǎng)絡(luò)應(yīng)用開(kāi)發(fā)需要的緩沖類(lèi)型。這些很酷的特性包括:

  • 如果需要,允許使用自定義的緩沖類(lèi)型。
  • 復(fù)合緩沖類(lèi)型中內(nèi)置的透明的零拷貝實(shí)現(xiàn)。
  • 開(kāi)箱即用的動(dòng)態(tài)緩沖類(lèi)型,具有像 StringBuffer 一樣的動(dòng)態(tài)緩沖能力。
  • 不再需要調(diào)用的flip()方法。
  • 正常情況下具有比 ByteBuffer 更快的響應(yīng)速度。

更多信息請(qǐng)參考:io.netty.buffer 包描述

Extensibility 可擴(kuò)展性

ByteBuf 具有豐富的操作集,可以快速的實(shí)現(xiàn)協(xié)議的優(yōu)化。例如,ByteBuf 提供各種操作用于訪問(wèn)無(wú)符號(hào)值和字符串,以及在緩沖區(qū)搜索一定的字節(jié)序列。你也可以擴(kuò)展或包裝現(xiàn)有的緩沖類(lèi)型用來(lái)提供方便的訪問(wèn)。自定義緩沖式仍然實(shí)現(xiàn)自 ByteBuf 接口,而不是引入一個(gè)不兼容的類(lèi)型

Transparent Zero Copy 透明的零拷貝

舉一個(gè)網(wǎng)絡(luò)應(yīng)用到極致的表現(xiàn),你需要減少內(nèi)存拷貝操作次數(shù)。你可能有一組緩沖區(qū)可以被組合以形成一個(gè)完整的消息。網(wǎng)絡(luò)提供了一種復(fù)合緩沖,允許你從現(xiàn)有的任意數(shù)的緩沖區(qū)創(chuàng)建一個(gè)新的緩沖區(qū)而無(wú)需沒(méi)有內(nèi)存拷貝。例如,一個(gè)信息可以由兩部分組成;header 和 body。在一個(gè)模塊化的應(yīng)用,當(dāng)消息發(fā)送出去時(shí),這兩部分可以由不同的模塊生產(chǎn)和裝配。

<pre> +--------+----------+
 | header |   body   |
 +--------+----------+
 </pre>

如果你使用的是 ByteBuffer ,你必須要?jiǎng)?chuàng)建一個(gè)新的大緩存區(qū)用來(lái)拷貝這兩部分到這個(gè)新緩存區(qū)中?;蛘?,你可以在 NiO做一個(gè)收集寫(xiě)操作,但限制你將復(fù)合緩沖類(lèi)型作為 ByteBuffer 的數(shù)組而不是一個(gè)單一的緩沖區(qū),打破了抽象,并且引入了復(fù)雜的狀態(tài)管理。此外,如果你不從 NIO channel 讀或?qū)?,它是沒(méi)有用的。

    // 復(fù)合類(lèi)型與組件類(lèi)型不兼容。
    ByteBuffer[] message = new ByteBuffer[] { header, body };

通過(guò)對(duì)比, ByteBuf 不會(huì)有警告,因?yàn)樗峭耆蓴U(kuò)展并有一個(gè)內(nèi)置的復(fù)合緩沖區(qū)。

    // 復(fù)合類(lèi)型與組件類(lèi)型是兼容的。
    ByteBuf message = Unpooled.wrappedBuffer(header, body);

    // 因此,你甚至可以通過(guò)混合復(fù)合類(lèi)型與普通緩沖區(qū)來(lái)創(chuàng)建一個(gè)復(fù)合類(lèi)型。
    ByteBuf messageWithFooter = Unpooled.wrappedBuffer(message, footer);

    // 由于復(fù)合類(lèi)型仍是 ByteBuf,訪問(wèn)其內(nèi)容很容易,
    //并且訪問(wèn)方法的行為就像是訪問(wèn)一個(gè)單獨(dú)的緩沖區(qū),
    //即使你想訪問(wèn)的區(qū)域是跨多個(gè)組件。
    //這里的無(wú)符號(hào)整數(shù)讀取位于 body 和 footer
    messageWithFooter.getUnsignedInt(
         messageWithFooter.readableBytes() - footer.readableBytes() - 1);

Automatic Capacity Extension 自動(dòng)容量擴(kuò)展

許多協(xié)議定義可變長(zhǎng)度的消息,這意味著沒(méi)有辦法確定消息的長(zhǎng)度,直到你構(gòu)建的消息?;蛘?,在計(jì)算長(zhǎng)度的精確值時(shí),帶來(lái)了困難和不便。這就像當(dāng)你建立一個(gè)字符串。你經(jīng)常估計(jì)得到的字符串的長(zhǎng)度,讓 StringBuffer 擴(kuò)大了其本身的需求。

    // 一種新的動(dòng)態(tài)緩沖區(qū)被創(chuàng)建。在內(nèi)部,實(shí)際緩沖區(qū)是被“懶”創(chuàng)建,從而避免潛在的浪費(fèi)內(nèi)存空間。
    ByteBuf b = Unpooled.buffer(4);

    // 當(dāng)?shù)谝粋€(gè)執(zhí)行寫(xiě)嘗試,內(nèi)部指定初始容量 4 的緩沖區(qū)被創(chuàng)建
    b.writeByte('1');

    b.writeByte('2');
    b.writeByte('3');
    b.writeByte('4');

    // 當(dāng)寫(xiě)入的字節(jié)數(shù)超過(guò)初始容量 4 時(shí),
    //內(nèi)部緩沖區(qū)自動(dòng)分配具有較大的容量
    b.writeByte('5');

Better Performance 更好的性能

最頻繁使用的緩沖區(qū) ByteBuf 的實(shí)現(xiàn)是一個(gè)非常薄的字節(jié)數(shù)組包裝器(比如,一個(gè)字節(jié))。與 ByteBuffer 不同,它沒(méi)有復(fù)雜的邊界和索引檢查補(bǔ)償,因此對(duì)于 JVM 優(yōu)化緩沖區(qū)的訪問(wèn)更加簡(jiǎn)單。更多復(fù)雜的緩沖區(qū)實(shí)現(xiàn)是用于拆分或者組合緩存,并且比 ByteBuffer 擁有更好的性能。