Netty之ByteBuf

我們在進(jìn)行數(shù)據(jù)傳送的時(shí)候需要用到緩沖區(qū)擅腰,常用的就是NIO的Buffer,實(shí)際上7種類型(除了Boolean)都有相關(guān)的實(shí)現(xiàn)枷莉,但是NIO編程常用的還是ByteBuffer熬词。但是ByteBuffer有position轮听,limit卷谈,capacity位置杯拐,每次讀寫還需要flip和clear處理相對比較麻煩,所以Netty自己使用ByteBuf來替換NIO的緩沖。

1.ByteBuf的原理

ByteBuf通過兩個(gè)指針來協(xié)助緩沖區(qū)的讀寫操作端逼,讀操作用readerIndex朗兵,寫操作用writeIndex;

readerIndex和writerIndex的取值一開始都是0顶滩,隨著數(shù)據(jù)的寫入writerIndex會增加,讀取數(shù)據(jù)會使readerIndex增加矛市,但是它不會超過writerIndex.在讀取之后,0~readerIndex的就被視為discard的诲祸,調(diào)用discardReadBytes方法,可以釋放這部分空間而昨,它的作用類似ByteBuffer的compact方法救氯。 ReaderIndex和writerIndex 之間的數(shù)據(jù)是可讀取的,等價(jià)于ByteBuffer position和limit之間的數(shù)據(jù)歌憨。WriterIndex 和capacity之間的空間是可寫的着憨,等價(jià)于ByteBuffer limit 和capacity之間的可用空間。

由于寫操作不修改readerIndex指針务嫡,讀操作不修改writerIndex指針甲抖,因此讀寫之間不再需要調(diào)整位置指針,這極大地簡化了緩沖區(qū)的讀寫操作心铃,避免了由于遺漏或者不熟悉flip()操作導(dǎo)致的功能異常准谚。

具體操作流程如下圖:

image

2.ByteBuf的功能

2.1 順序讀read操作

byteBuf的read操作ByteBuffer的get操作,有許多可以查看相關(guān)api去扣。

比如readBytes()

2.2 順序?qū)憌rite操作

byteBuf的write操作ByteBuffer的put操作柱衔,有許多可以查看相關(guān)api。

比如writeBytes()

2.3 readerIndex和writerIndex

Netty提供了兩個(gè)指針變量用于支持順序讀取和寫入操作:readerIndex用于標(biāo)識讀取索引愉棱,writerIndex 用于標(biāo)識寫入索引唆铐。兩個(gè)位置指針將ByteBuf緩沖區(qū)分割成三個(gè)區(qū)域.

調(diào)用ByteBuf 的read操作時(shí),從readerIndex處開始讀取奔滑。readerIndex 到writerIndex之間的空間為可讀的字節(jié)緩沖區(qū);從writerIndex到cappacitcity 之間為可寫的字節(jié)緩沖區(qū); 0到readerIndex之間是已經(jīng)讀取過的緩沖區(qū)艾岂,可以調(diào)用discardReadBytes操作來重用這部分空間,以節(jié)約內(nèi)存朋其,防止ByteBuf的動(dòng)態(tài)擴(kuò)張王浴。這在私有協(xié)議棧消息解碼的時(shí)候非常有用,因?yàn)門CP底層可能粘包令宿,幾百個(gè)整包消息被TCP粘包后作為一個(gè)整包發(fā)送叼耙,這樣,通過discardReadBytes操作可以重用之前已經(jīng)解碼過的緩沖區(qū)粒没,這樣就可以防止接收緩沖區(qū)因?yàn)槿萘坎蛔銓?dǎo)致的擴(kuò)張筛婉。

2.4 Discardable bytes

清理掉已經(jīng)讀取到的緩沖區(qū)。

2.5 ReadableBytes 和WritableBytes

可以查看可讀字節(jié)以及可寫的字節(jié)數(shù)

2.6 Clear,SkipBytes操作

clear 會將readerIndex和writerIndex全部設(shè)置為0,內(nèi)容不會清除

SkipBytes跳過不需要讀取的字節(jié)或者字節(jié)數(shù)組爽撒。

2.7 Mark和Reset操作

如果某個(gè)時(shí)候我們需要對于某一個(gè)操作做回滾入蛆,那么mark和reset就是這樣的實(shí)現(xiàn)的,他們只是改變索引位置硕勿,并不會 改變緩沖區(qū)內(nèi)容哨毁。通過mark操作將當(dāng)前指針備份到mark中,當(dāng)調(diào)用reset操作恢復(fù)備份的mark值源武。

比如:

markReaderIndex
resetReaderIndex

markWriterIndex
resetWriterIndex

2.8 查找操作

我們可以通過某一個(gè)字符定位他的位置做到定位操作扼褪。

比如indexOf,bytesBefore,forEachByte等。

2.9 Derived buffers 新建視圖

類似數(shù)據(jù)庫視圖粱栖,可以創(chuàng)建byteBuf的視圖或者復(fù)制byteBuf

  • 1)duplicate:返回當(dāng)前ByteBuf的復(fù)制對象话浇,復(fù)制的只是指針,內(nèi)容還是原來的內(nèi)容闹究,如果原來的內(nèi)容變了幔崖,之后的byteBuf獲得的內(nèi)容也是變化后的。

  • 2)copy:完全復(fù)制新的ByteBuf渣淤,內(nèi)容和索引都是完全互不影響

  • 3)slice:返回當(dāng)前可讀緩沖區(qū)即readerIndex到writerIndex赏寇,返回后的ByteBuf和原來的共享內(nèi)容,但是指針各種維護(hù)

2.10 轉(zhuǎn)換為標(biāo)準(zhǔn)的ByteBuffer

將byteBuf轉(zhuǎn)換為對應(yīng)的ByteBuffer

2.11 隨機(jī)讀寫(set/get)

除了順序的read和write外价认,也支持隨機(jī)讀寫嗅定,不過不同的地方就是順序讀寫可以做到自動(dòng)擴(kuò)容,隨機(jī)讀寫會對索引和長度進(jìn)行校驗(yàn)刻伊,不會動(dòng)態(tài)擴(kuò)展緩沖區(qū)露戒,所以需要注意字節(jié)長度,否則會拋出越界的錯(cuò)誤捶箱。

3.ByteBuf的輔助類

3.1 ByteBufHolder

ByteBufHolder是ByteBuf的容器智什,在Netty中,它非常有用丁屎,例如HTTP協(xié)議的請求消息和應(yīng)答消息都可以攜帶消息體荠锭,這個(gè)消息體在NIOByteBuffer中就是個(gè)ByteBuffer對象,在Netty中就是ByteBuf對象晨川。由于不同的協(xié)議消息體可以包含不同的協(xié)議字段和功能证九,因此,需要對ByteBuf進(jìn)行包裝和抽象共虑,不同的子類可以有不同的實(shí)現(xiàn)愧怜。

為了滿足這些定制化的需求,Netty 抽象出了ByteBufHolder 對象妈拌,它包含了一個(gè)ByteBuf,另外還提供了一些其他實(shí)用的方法拥坛,使用者繼承ByteBufHolder接口后可以按需封裝自己的實(shí)現(xiàn)蓬蝶。

3.2 ByteBufferAllocator

ByteBufAllocator是字節(jié)緩沖區(qū)分配器,按照Netty的緩沖區(qū)實(shí)現(xiàn)不同猜惋,共有兩種不同的分配器:基于內(nèi)存池的字節(jié)緩沖區(qū)分配器和普通的字節(jié)緩沖區(qū)分配器丸氛。

  • UnpooledByteBufAllocator

  • PooledByteBufAllocator

他們分別可以創(chuàng)建堆內(nèi)緩沖和非堆內(nèi)緩沖

3.3 CompositeByteBuf

CompositeByteBuf允許將多個(gè)ByteBuf的實(shí)例組裝到一起,形成-一個(gè)統(tǒng)- -的視圖著摔,有點(diǎn)類似于數(shù)據(jù)庫將多個(gè)表的字段組裝到一起統(tǒng)一用視圖展示缓窜。

3.4 ByteBufUtil

ByteBufUtil是一個(gè)非常有用的工具類,它提供了一系列靜態(tài)方法用于操作ByteBuf對象.

比較有用的比如encodeString,decodeString,hexDump等方法谍咆。

4. 內(nèi)存分配和回收

從內(nèi)存分配的角度看禾锤,ByteBuf 可以分為兩類:

(1)堆內(nèi)存(HeapByteBuf) 字節(jié)緩沖區(qū):特點(diǎn)是內(nèi)存的分配和回收速度快,可以被 JVM自動(dòng)回收;缺點(diǎn)就是如果進(jìn)行Socket 的I/O 讀寫摹察,需要額外做一次內(nèi)存復(fù)制时肿,將堆 內(nèi)存對應(yīng)的緩沖區(qū)復(fù)制到內(nèi)核Channel中,性能會有一定程度的下降港粱。

(2)直接內(nèi)存( DirectByteBuf) 字節(jié)緩沖區(qū):非堆內(nèi)存,它在堆外進(jìn)行內(nèi)存分配旦签,相 比于堆內(nèi)存查坪,它的分配和回收速度會慢--些,但是將它寫入或者從SocketChannel中讀取 時(shí)宁炫,由于少了一次內(nèi)存復(fù)制偿曙,速度比堆內(nèi)存快。

正是因?yàn)楦饔欣赘岢玻訬etty提供了多種ByteBuf供開發(fā)者使用望忆,經(jīng)驗(yàn)表明,ByteBuf 的最佳實(shí)踐是在I/O通信線程的讀寫緩沖區(qū)使用DirectByteBuf,后端業(yè)務(wù)消息的編解碼模 塊使用HeapByteBuf,這樣組合可以達(dá)到性能最優(yōu)竿秆。

從內(nèi)存回收角度看启摄,ByteBuf也分為兩類:基于對象池的ByteBuf和普通ByteBuf。兩 者的主要區(qū)別就是基于對象池的ByteBuf可以重用ByteBuf對象幽钢,它自己維護(hù)了一個(gè)內(nèi)存 池歉备,可以循環(huán)利用創(chuàng)建的ByteBuf,提升內(nèi)存的使用效率,降低由于高負(fù)載導(dǎo)致的頻繁GC匪燕。 測試表明使用內(nèi)存池后的Netty在高負(fù)載蕾羊、大并發(fā)的沖擊下內(nèi)存和GC更加平穩(wěn)。 盡管推薦使用基于內(nèi)存池的ByteBuf,但是內(nèi)存池的管理和維護(hù)更加復(fù)雜帽驯,使用起來 也需要更加謹(jǐn)慎龟再,因此,Netty提供了靈活的策略供使用者來做選擇尼变。

參考:《Netty權(quán)威指南》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末利凑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌截碴,老刑警劉巖梳侨,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異日丹,居然都是意外死亡走哺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門哲虾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丙躏,“玉大人舅世,你說我怎么就攤上這事萤捆「嵛叮” “怎么了诫硕?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵亡容,是天一觀的道長讼稚。 經(jīng)常有香客問我陈醒,道長抚岗,這世上最難降的妖魔是什么扒寄? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任鱼鼓,我火速辦了婚禮,結(jié)果婚禮上该编,老公的妹妹穿的比我還像新娘迄本。我一直安慰自己,他們只是感情好课竣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布嘉赎。 她就那樣靜靜地躺著,像睡著了一般于樟。 火紅的嫁衣襯著肌膚如雪公条。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天迂曲,我揣著相機(jī)與錄音赃份,去河邊找鬼。 笑死奢米,一個(gè)胖子當(dāng)著我的面吹牛抓韩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鬓长,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼谒拴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了涉波?” 一聲冷哼從身側(cè)響起英上,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤炭序,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后苍日,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惭聂,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年相恃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辜纲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拦耐,死狀恐怖耕腾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情杀糯,我是刑警寧澤扫俺,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站固翰,受9級特大地震影響狼纬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜骂际,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一畸颅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧方援,春花似錦、人聲如沸涛癌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拳话。三九已至先匪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間弃衍,已是汗流浹背呀非。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留镜盯,地道東北人岸裙。 一個(gè)月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像速缆,于是被迫代替她去往敵國和親降允。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容