Netty 原理及TCP連接池高并發(fā)相關(guān)

http://www.itdecent.cn/p/a618adef427c

Netty實戰(zhàn)入門詳解——讓你徹底記住什么是Netty

java socket連接池 實現(xiàn)

Spring Cloud Gateway 管理 Netty 長連接

單機(jī)下Java程序支持百萬長連接參數(shù)調(diào)優(yōu)

Netty 系列之 Netty 百萬級推送服務(wù)設(shè)計要點

1. Netty基本概念

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

作為當(dāng)前最流行的NIO框架,Netty在互聯(lián)網(wǎng)領(lǐng)域、大數(shù)據(jù)分布式計算領(lǐng)域、游戲行業(yè)、通信行業(yè)等獲得了廣泛的應(yīng)用,一些業(yè)界著名的開源組件也基于Netty的NIO框架構(gòu)建。如:Dubbo、 RocketMQ、Hadoop的Avro、Spark等。

Netty需要學(xué)習(xí)的內(nèi)容: 編解碼器、TCP粘包/拆包及Netty如何解決、ByteBuf、Channel和Unsafe、ChannelPipeline和ChannelHandler、EventLoop和EventLoopGroup、Future等。

編解碼器:

Java序列化的目的主要有兩個:

網(wǎng)絡(luò)傳輸

對象持久化

Java序列化僅僅是Java編解碼技術(shù)的一種,由于他的種種缺陷,衍生出多種編解碼技術(shù)和框架。

Java序列化的缺點:

無法跨語言

序列化后的碼流太大

序列化性能太低

業(yè)界主流的編解碼框架:

Google Protobuf:支持Java、C++、Python三種語言,高效的編碼性能,結(jié)構(gòu)化數(shù)據(jù)存儲格式(XML,JSON等)

Facebook Thrift:適用于靜態(tài)的數(shù)據(jù)交換,需要先確定好它的數(shù)據(jù)結(jié)構(gòu)。結(jié)構(gòu)變化后需要重新編譯IDL文件,這也是Thrift的弱項。

JBoss Marshalling:是一個Java對象的序列化API,修正了JDK自帶的序列化包的很多問題,但又保持跟java.io.Serializable接口的兼容。

Hessian:一個輕量級的remoting onhttp工具,使用簡單的方法提供了RMI的功能,采用的是二進(jìn)制RPC協(xié)議。

TCP粘包/拆包:

TCP是個“流”協(xié)議,所謂流,就是沒有界限的一串?dāng)?shù)據(jù)。TCP底層并不了解上層業(yè)務(wù)數(shù)據(jù)的具體含義,它會根據(jù)TCP緩存區(qū)的實際情況進(jìn)行包的劃分,所以在業(yè)務(wù)上的一個完整的包,可能被TCP拆分成多個包進(jìn)行發(fā)送,也可能把多個小包封裝成一個大的數(shù)據(jù)包發(fā)送,這就是TCP粘包和拆包問題。

有如下幾種情況:

正常情況

粘包

粘包和拆包同時發(fā)生

2. Netty線程模型

在JAVA NIO方面Selector給Reactor模式提供了基礎(chǔ),Netty結(jié)合Selector和Reactor模式設(shè)計了高效的線程模型。

關(guān)于Java NIO 構(gòu)造Reator模式,Doug Lea在《Scalable IO in Java》中給了很好的闡述,這里截取PPT對Reator模式的實現(xiàn)進(jìn)行說明。

(1)Reactor單線程模型

單線程模型

這是最簡單的Reactor單線程模型,由于Reactor模式使用的是異步非阻塞IO,所有的IO操作都不會被阻塞,理論上一個線程可以獨立處理所有的IO操作。這時Reactor線程是個多面手,負(fù)責(zé)多路分離套接字,Accept新連接,并分發(fā)請求到處理鏈中。

對于一些小容量應(yīng)用場景,可以使用到單線程模型。但對于高負(fù)載,大并發(fā)的應(yīng)用卻不合適,主要原因如下:

1. 當(dāng)一個NIO線程同時處理成百上千的鏈路,性能上無法支撐,即使NIO線程的CPU負(fù)荷達(dá)到100%,也無法完全處理消息。

2. 當(dāng)NIO線程負(fù)載過重后,處理速度會變慢,會導(dǎo)致大量客戶端連接超時,超時之后往往會重發(fā),更加重了NIO線程的負(fù)載。

3. 可靠性低,一個線程意外死循環(huán),會導(dǎo)致整個通信系統(tǒng)不可用。

為了解決這些問題,出現(xiàn)了Reactor多線程模型。

(2)Reactor多線程模型

多線程模型

相比上一種模式,該模型在處理鏈部分采用了多線程(線程池)。

在絕大多數(shù)場景下,該模型都能滿足性能需求。但是,在一些特殊的應(yīng)用場景下,如服務(wù)器會對客戶端的握手消息進(jìn)行安全認(rèn)證。這類場景下,單獨的一個Acceptor線程可能會存在性能不足的問題。為了解決這些問題,產(chǎn)生了第三種Reactor線程模型。

(3)Reactor主從模型?

主從模型

該模型相比第二種模型,是將Reactor分成兩部分,mainReactor負(fù)責(zé)監(jiān)聽server socket,accept新連接;并將建立的socket分派給subReactor。subReactor負(fù)責(zé)多路分離已連接的socket,讀寫網(wǎng)絡(luò)數(shù)據(jù),對業(yè)務(wù)處理功能,其扔給worker線程池完成。通常,subReactor個數(shù)上可與CPU個數(shù)等同。

利用主從NIO線程模型,可以解決一個服務(wù)端監(jiān)聽線程無法有效處理所有客戶端連接的性能不足問題,因此,在Netty的官方Demo中,推薦使用該線程模型。

(4)Netty模型

Netty的線程模型并不是一成不變,它實際取決于用戶的啟動參數(shù)配置。通過設(shè)置不同的啟動參數(shù),Netty可以同時支持Reactor單線程模型、多線程模型和主從模型。

前面介紹完 Netty 相關(guān)一些理論,下面從功能特性、模塊組件來介紹 Netty 的架構(gòu)設(shè)計。

3. Netty功能特性

Netty的功能特性

4. Netty模塊組件

Netty主要有下面一些組件:

Selector

NioEventLoop

NioEventLoopGroup

ChannelHandler

ChannelHandlerContext

ChannelPipeline

Selector

Netty 基于 Selector 對象實現(xiàn) I/O 多路復(fù)用,通過 Selector 一個線程可以監(jiān)聽多個連接的 Channel 事件。

NioEventLoop

其中維護(hù)了一個線程和任務(wù)隊列,支持異步提交執(zhí)行任務(wù),線程啟動時會調(diào)用 NioEventLoop 的 run 方法,執(zhí)行 I/O 任務(wù)和非 I/O 任務(wù)。

NioEventLoopGroup

主要管理 eventLoop 的生命周期,可以理解為一個線程池,內(nèi)部維護(hù)了一組線程,每個線程(NioEventLoop)負(fù)責(zé)處理多個 Channel 上的事件,而一個 Channel 只對應(yīng)于一個線程。

ChannelHandler

是一個接口,處理 I/O 事件或攔截 I/O 操作,并將其轉(zhuǎn)發(fā)到其 ChannelPipeline(業(yè)務(wù)處理鏈)中的下一個處理程序。

ChannelHandlerContext

保存 Channel 相關(guān)的所有上下文信息,同時關(guān)聯(lián)一個 ChannelHandler 對象。

ChannelPipeline 是保存 ChannelHandler 的 List,用于處理或攔截 Channel 的入站事件和出站操作。實現(xiàn)了一種高級形式的攔截過濾器模式,使用戶可以完全控制事件的處理方式,以及 Channel 中各個的 ChannelHandler 如何相互交互。

ChannelPipeline對事件流的攔截和處理流程:

ChannelPipeline入站出站圖

Netty中的事件分為Inbond事件和Outbound事件。

Inbound事件通常由I/O線程觸發(fā),如TCP鏈路建立事件、鏈路關(guān)閉事件、讀事件、異常通知事件等。

Outbound事件通常是用戶主動發(fā)起的網(wǎng)絡(luò)I/O操作,如用戶發(fā)起的連接操作、綁定操作、消息發(fā)送等。

在 Netty中,Channel 、ChannelHandler、ChannelHandlerContext、 ChannelPipeline的關(guān)系如下圖:

各組件關(guān)系圖

一個 Channel 包含了一個 ChannelPipeline,而 ChannelPipeline 中又維護(hù)了一個由 ChannelHandlerContext 組成的雙向鏈表,并且每個 ChannelHandlerContext 中又關(guān)聯(lián)著一個 ChannelHandler。

入站事件和出站事件在一個雙向鏈表中,入站事件會從鏈表 head 往后傳遞到最后一個入站的 handler,出站事件會從鏈表 tail 往前傳遞到最前一個出站的 handler,兩種類型的 handler 互不干擾。

以上是Netty的主要原理介紹,Netty源碼分析的話,后續(xù)有時間會繼續(xù)分享出來。

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

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

  • 前段時間在看RocketMQ源碼時,發(fā)現(xiàn)底層用了Netty,順便學(xué)習(xí)了一下,網(wǎng)上不少博客講的有錯誤之處,而...
    CleverApe閱讀 10,932評論 0 12
  • Netty簡介 Netty是一個高性能、異步事件驅(qū)動的NIO框架,基于JAVA NIO提供的API實現(xiàn)。它提供了對...
    java伯爵閱讀 516評論 0 0
  • Netty簡介 Netty是一個高性能、異步事件驅(qū)動的NIO框架,基于JAVA NIO提供的API實現(xiàn)。它提供了對...
    Java機(jī)械師閱讀 713評論 0 0
  • 本章包含 ChannelHandler和ChannelPipeline APIs 檢測資源泄露 異常處理 在前一章...
    達(dá)微閱讀 1,227評論 0 1
  • 首先來張網(wǎng)上盛傳的netty框架參考圖,以供讀者把握Netty的整體框架及核心組件,繼而發(fā)散出Netty的重點知識...
    小圣996閱讀 1,042評論 0 5

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