Netty源碼(一):Netty中的Buffer

      網友投稿 1007 2025-03-31

      最近我學習了NIO相關的知識,然后發現了Netty這個基于NIO的網絡應用框架,于是就研究起Netty框架源碼,來好好體會一下網絡框架的設計理念和思想.

      這個系列的文章不僅會總結Netty各個模塊的源碼原理,也會寫出一些自己對這些設計的理解和體會.

      我基本按照并發編程網上這個系列文章的順序來進行系列文章的順序,不同的是我是基于Netty4.1的源碼進行分析和講解.

      為了節約你的時間,本篇文章主要內容如下:

      - Netty的Buffer的內存模型,涉及讀寫指針

      - Netty的Buffer框架

      - Netty的Pool原理,輕量對象池

      Buffer

      Java NIO中的Buffer用于和NIO通道進行交互,數據可以從通道讀入緩沖區,也可以從緩沖區寫入到通道中.所以說,Buffer其實就是一塊可以讀寫數據的內存,我們將其包裝為一個Java對象來提供一系列讀寫操作.

      Netty并沒有直接使用Java NIO的Buffer實現,而是自己實現了一套Buffer框架來滿足自己的業務或者性能需求.

      ByteBuf的基本原理

      不同于NIO Buffer的讀寫指針共用原理,ByteBuf擁有readerIndex,writerIndex兩個指針.下面我們就來詳細的講解一下ByteBuf的內部原理.

      +-------------------+------------------+------------------+ | discardable bytes | readable bytes | writable bytes | | | (CONTENT) | | +-------------------+------------------+------------------+ | | | | 0 <= readerIndex <= writerIndex <= capacity

      1

      2

      3

      4

      5

      6

      從示意圖中我們可以看出readerIndex和writerIndex最多可以將整個內容空間劃分為三塊:廢棄區,可讀區和可寫區.下面我們就來看一下不同操作下的兩個指針的變化.

      Netty源碼(一):Netty中的Buffer

      - 在初始化狀態下,假設capacity為20,readerIndex和writerIndex都為0,整個空間中只存在可寫區.此時只能寫,不能讀,進行讀操作會拋出異常.

      +---------------------------------------------------------+ | writable bytes (got more space) | +---------------------------------------------------------+ | | readerIndex(0) writerIndex(0) <= capacity

      1

      2

      3

      4

      5

      6

      寫入10個字節的數據,writerIndex指向10,readerIndex不會改變,所有內容空間中有可讀區和可寫區.大小都是10字節.

      +-------------------+------------------+------------------+ | readable bytes | writable bytes | | (CONTENT) | | +--------- --------+------------------+------------------ | | | readerIndex(0) <= writerIndex(10) <= capacity

      1

      2

      3

      4

      5

      6

      讀取5個字節的內容,writerIndex不變,readerIndex加5,指向了5.此時內容空間分為了5字節的廢棄區,5字節的可讀區和10字節的可寫區.

      +-------------------+------------------+------------------+ | discardable bytes | readable bytes | writable bytes | | | (CONTENT) | | +-------------------+------------------+------------------+ | | | | 0 <= readerIndex(5) <= writerIndex(10) <= capacity

      1

      2

      3

      4

      5

      6

      7

      調用discardReadBytes方法后,將廢棄區的內容舍棄掉,readerIndex又指向了0,writerIndex指向了5,相當于可讀區和可寫區整體向左平移了5個字節.

      +------------------+--------------------------------------+ | readable bytes | writable bytes (got more space) | +------------------+--------------------------------------+ | | | readerIndex (0) <= writerIndex (5) <= capacity

      1

      2

      3

      4

      5

      OS層次上Zero-copy,就是在操作數據時,不需要將數據buffer從一個內存區域拷貝到另一個內存區域,因為減少了一次內存的拷貝,因此CPU的效率得到了提升.

      Netty的zero-copy體現在很多方面.比如Buffer的compose,duplicate,slice操作時不會拷貝底層的數據.而是通過ByteBuf對象的組合來實現上述的操作

      - Netty提供了CompositeByteBuf類,可以將多個ByteBuf組合成一個邏輯上的Buffer,避免了各個buffer之間的拷貝,CompositeByteBuf并不擁有底層的數據,而是通過擁有兩個buffer對象,從這兩個buffer對象中獲取數據來對外提供看似合并了的數據.比如我們將一份協議數據的頭部buffer和消息體buffer合并成一個Buffer.

      如上圖所示,所有底層的數據還是存儲在header和body這兩個真實的buffer中.

      對于ByteBuf的slice和duplicate操作也是如此,不同的buffer共享了相同的底層數據,而不是進行底層數據的拷貝.具體使用到的Buffer類型為DuplicatedByteBuf和SlicedByteBuf.誰說是共享的底層數據,但是通過對writerIndex和readerIndex兩個指針的操作來實現slice和duplicate的功能.

      Netty使用wrap操作將byte數組轉化為ByteBuf對象時,將byte數組包裹到對象中,而不是拷貝數組存放到對象中.

      Netty 中使用 FileRegion 實現文件傳輸的零拷貝, 不過在底層 FileRegion 是依賴于 Java NIO FileChannel.transfer 的零拷貝功能.

      Pool和Reference Count

      4.0之后的版本實現了高性能的Buffer池,分配策略則是結合了buddy allocation和slab allocation的jemalloc變種,實現類為PoolArena,這樣的話,可以在頻繁分配和釋放Buffer時緩解GC壓力,還可以在初始化新buffer時減少內存帶寬消耗(初始化時不可避免的要給buffer數組賦初始值).

      ByteBuf引入了Reference Count機制,你需要在不適用它的時候調用ReferenceCountUtil.release方法來減少它的引用.

      后記

      感覺自己在研究或在閱讀源代碼時還是有些問題,起始ByteBuf并不是Netty的關鍵所在,不應該花費這么長時間.以后還是要帶著目的來看源碼,不能把時間浪費在一些代碼細節上.

      引用

      https://segmentfault.com/a/1190000007560884

      Java

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:Excel 另類使用Max函數求最大值
      下一篇:excel 序號(excel序號怎么自動生成)
      相關文章
      精品国产日韩亚洲一区| 久久精品亚洲福利| 亚洲精品视频久久| 亚洲伦另类中文字幕| 亚洲av伊人久久综合密臀性色| 国产AⅤ无码专区亚洲AV| 在线精品亚洲一区二区三区| 亚洲乱码中文字幕手机在线| 亚洲AⅤ视频一区二区三区| 亚洲成AⅤ人影院在线观看| 亚洲国产精品综合久久一线| 国产成人不卡亚洲精品91| 麻豆亚洲AV成人无码久久精品 | 亚洲欧美熟妇综合久久久久| 亚洲午夜无码久久久久软件| 亚洲熟妇AV一区二区三区浪潮| 亚洲色成人WWW永久在线观看| 国产成人亚洲综合网站不卡| 亚洲日韩中文字幕无码一区| 亚洲欧洲日产国码久在线| 久久精品国产亚洲AV天海翼| 亚洲AV无码乱码在线观看| 亚洲精品国产V片在线观看| 亚洲人妻av伦理| 亚洲精品午夜无码电影网| 国产亚洲欧洲精品| 亚洲综合无码一区二区| 亚洲日本国产精华液| 日韩亚洲不卡在线视频中文字幕在线观看 | 麻豆亚洲AV永久无码精品久久| 久久久久亚洲Av无码专| 亚洲人成电影网站| 亚洲精品中文字幕| 亚洲国产精品人人做人人爱| 亚洲国产人成中文幕一级二级| 中文字幕不卡亚洲| 亚洲一区二区电影| 33333在线亚洲| 精品久久久久久亚洲综合网| 亚洲人成网站色在线入口| 久久综合九九亚洲一区|