那些與Netty有關(guān)的知識點(diǎn),你知道多少

Netty 原理

Netty 是一個高性能、異步事件驅(qū)動的 NIO 框架,基于 JAVA NIO 提供的 API 實(shí)現(xiàn)。它提供了對TCP、UDP 和文件傳輸?shù)闹С郑鳛橐粋€異步 NIO 框架,Netty 的所有 IO 操作都是異步非阻塞的,通過 Future-Listener 機(jī)制,用戶可以方便的主動獲取或者通過通知機(jī)制獲得 IO 操作結(jié)果。

Netty 高性能

在 IO 編程過程中,當(dāng)需要同時處理多個客戶端接入請求時,可以利用多線程或者 IO 多路復(fù)用技術(shù)進(jìn)行處理。IO 多路復(fù)用技術(shù)通過把多個 IO 的阻塞復(fù)用到同一個 select 的阻塞上,從而使得系統(tǒng)在單線程的情況下可以同時處理多個客戶端請求。與傳統(tǒng)的多線程/多進(jìn)程模型比,I/O 多路復(fù)用的最大優(yōu)勢是系統(tǒng)開銷小,系統(tǒng)不需要創(chuàng)建新的額外進(jìn)程或者線程,也不需要維護(hù)這些進(jìn)程和線程的運(yùn)行,降低了系統(tǒng)的維護(hù)工作量,節(jié)省了系統(tǒng)資源。

與 Socket 類和 ServerSocket 類相對應(yīng),NIO 也提供了 SocketChannel 和 ServerSocketChannel兩種不同的套接字通道實(shí)現(xiàn)。

多路復(fù)用通訊方式

Netty 架構(gòu)按照 Reactor 模式設(shè)計(jì)和實(shí)現(xiàn),它的服務(wù)端通信序列圖如下:

image

客戶端通信序列圖如下:

image

Netty 的 IO 線程 NioEventLoop 由于聚合了多路復(fù)用器 Selector,可以同時并發(fā)處理成百上千個客戶端 Channel,由于讀寫操作都是非阻塞的,這就可以充分提升 IO 線程的運(yùn)行效率,避免由于頻繁 IO 阻塞導(dǎo)致的線程掛起。

異步通訊 NIO

由于 Netty 采用了異步通信模式,一個 IO 線程可以并發(fā)處理 N 個客戶端連接和讀寫操作,這從根本上解決了傳統(tǒng)同步阻塞 IO 一連接一線程模型,架構(gòu)的性能、彈性伸縮能力和可靠性都得到了極大的提升。

零拷貝(DIRECT BUFFERS 使用堆外直接內(nèi)存)

1. Netty 的接收和發(fā)送 ByteBuffer 采用 DIRECT BUFFERS,使用堆外直接內(nèi)存進(jìn)行 Socket 讀寫,不需要進(jìn)行字節(jié)緩沖區(qū)的二次拷貝。如果使用傳統(tǒng)的堆內(nèi)存(HEAP BUFFERS)進(jìn)行 Socket 讀寫,JVM 會將堆內(nèi)存 Buffer 拷貝一份到直接內(nèi)存中,然后才寫入 Socket 中。相比于堆外直接內(nèi)存,消息在發(fā)送過程中多了一次緩沖區(qū)的內(nèi)存拷貝。

2. Netty 提供了組合 Buffer 對象,可以聚合多個 ByteBuffer 對象,用戶可以像操作一個 Buffer 那樣方便的對組合 Buffer 進(jìn)行操作,避免了傳統(tǒng)通過內(nèi)存拷貝的方式將幾個小 Buffer 合并成一個大的Buffer。

3. Netty的文件傳輸采用了transferTo方法,它可以直接將文件緩沖區(qū)的數(shù)據(jù)發(fā)送到目標(biāo)Channel,避免了傳統(tǒng)通過循環(huán) write 方式導(dǎo)致的內(nèi)存拷貝問題。

內(nèi)存池(基于內(nèi)存池的緩沖區(qū)重用機(jī)制)

隨著 JVM 虛擬機(jī)和 JIT 即時編譯技術(shù)的發(fā)展,對象的分配和回收是個非常輕量級的工作。但是對于緩沖區(qū) Buffer,情況卻稍有不同,特別是對于堆外直接內(nèi)存的分配和回收,是一件耗時的操作。為了盡量重用緩沖區(qū),Netty 提供了基于內(nèi)存池的緩沖區(qū)重用機(jī)制。

高效的 Reactor 線程模型

常用的 Reactor 線程模型有三種,Reactor 單線程模型, Reactor 多線程模型, 主從 Reactor 多線程模型。

Reactor 單線程模型

Reactor 單線程模型,指的是所有的 IO 操作都在同一個 NIO 線程上面完成,NIO 線程的職責(zé)如下:

  1. 作為 NIO 服務(wù)端,接收客戶端的 TCP 連接;

  2. 作為 NIO 客戶端,向服務(wù)端發(fā)起 TCP 連接;

  3. 讀取通信對端的請求或者應(yīng)答消息;

  4. 向通信對端發(fā)送消息請求或者應(yīng)答消息。

image

由于 Reactor 模式使用的是異步非阻塞 IO,所有的 IO 操作都不會導(dǎo)致阻塞,理論上一個線程可以獨(dú)立處理所有 IO 相關(guān)的操作。從架構(gòu)層面看,一個 NIO 線程確實(shí)可以完成其承擔(dān)的職責(zé)。例如,通過Acceptor 接收客戶端的 TCP 連接請求消息,鏈路建立成功之后,通過 Dispatch 將對應(yīng)的 ByteBuffer派發(fā)到指定的 Handler 上進(jìn)行消息解碼。用戶 Handler 可以通過 NIO 線程將消息發(fā)送給客戶端。

Reactor 多線程模型

Rector 多線程模型與單線程模型最大的區(qū)別就是有一組 NIO 線程處理 IO 操作。 有專門一個NIO 線程-Acceptor 線程用于監(jiān)聽服務(wù)端,接收客戶端的 TCP 連接請求; 網(wǎng)絡(luò) IO 操作-讀、寫等由一個 NIO 線程池負(fù)責(zé),線程池可以采用標(biāo)準(zhǔn)的 JDK 線程池實(shí)現(xiàn),它包含一個任務(wù)隊(duì)列和 N個可用的線程,由這些 NIO 線程負(fù)責(zé)消息的讀取、解碼、編碼和發(fā)送;

image

主從 Reactor 多線程模型

服務(wù)端用于接收客戶端連接的不再是個 1 個單獨(dú)的 NIO 線程,而是一個獨(dú)立的 NIO 線程池。Acceptor 接收到客戶端 TCP 連接請求處理完成后(可能包含接入認(rèn)證等),將新創(chuàng)建的SocketChannel 注冊到 IO 線程池(sub reactor 線程池)的某個 IO 線程上,由它負(fù)責(zé)SocketChannel 的讀寫和編解碼工作。Acceptor 線程池僅僅只用于客戶端的登陸、握手和安全認(rèn)證,一旦鏈路建立成功,就將鏈路注冊到后端 subReactor 線程池的 IO 線程上,由 IO 線程負(fù)責(zé)后續(xù)的 IO 操作。

image

無鎖設(shè)計(jì)、線程綁定

Netty 采用了串行無鎖化設(shè)計(jì),在 IO 線程內(nèi)部進(jìn)行串行操作,避免多線程競爭導(dǎo)致的性能下降。表面上看,串行化設(shè)計(jì)似乎 CPU 利用率不高,并發(fā)程度不夠。但是,通過調(diào)整 NIO 線程池的線程參數(shù),可以同時啟動多個串行化的線程并行運(yùn)行,這種局部無鎖化的串行線程設(shè)計(jì)相比一個隊(duì)列-多個工作線程模型性能更優(yōu)。

image

Netty 的 NioEventLoop 讀取到消息之后,直接調(diào)用 ChannelPipeline 的
fireChannelRead(Object msg),只要用戶不主動切換線程,一直會由 NioEventLoop 調(diào)用到用戶的 Handler,期間不進(jìn)行線程切換,這種串行化處理方式避免了多線程操作導(dǎo)致的鎖的競爭,從性能角度看是最優(yōu)的。

高性能的序列化框架

Netty 默認(rèn)提供了對 Google Protobuf 的支持,通過擴(kuò)展 Netty 的編解碼接口,用戶可以實(shí)現(xiàn)其它的高性能序列化框架,例如 Thrift 的壓縮二進(jìn)制編解碼框架。

1. SO_RCVBUF 和 SO_SNDBUF:通常建議值為 128K 或者 256K。

小包封大包,防止網(wǎng)絡(luò)阻塞

2. SO_TCPNODELAY:NAGLE 算法通過將緩沖區(qū)內(nèi)的小封包自動相連,組成較大的封包,阻止大量小封包的發(fā)送阻塞網(wǎng)絡(luò),從而提高網(wǎng)絡(luò)應(yīng)用效率。但是對于時延敏感的應(yīng)用場景需要關(guān)閉該優(yōu)化算法。

軟中斷 Hash 值和 CPU 綁定

3. 軟中斷:開啟 RPS 后可以實(shí)現(xiàn)軟中斷,提升網(wǎng)絡(luò)吞吐量。RPS 根據(jù)數(shù)據(jù)包的源地址,目的地址以及目的和源端口,計(jì)算出一個 hash 值,然后根據(jù)這個 hash 值來選擇軟中斷運(yùn)行的 cpu,從上層來看,也就是說將每個連接和 cpu 綁定,并通過這個 hash 值,來均衡軟中斷在多個 cpu 上,提升網(wǎng)絡(luò)并行處理性能。

持續(xù)更新中…………

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容