【說(shuō)明】本文原載于碼農(nóng) IO(manong.io)官方微信 developerWorks,轉(zhuǎn)載、引用請(qǐng)注明出處及作者。
1.Netty 是什么?
Netty 是一個(gè)基于 JAVA NIO 類(lèi)庫(kù)的異步通信框架,它的架構(gòu)特點(diǎn)是:異步非阻塞、基于事件驅(qū)動(dòng)、高性能、高可靠性和高可定制性。
2.使用 Netty 能夠做什么?
開(kāi)發(fā)異步、非阻塞的 TCP 網(wǎng)絡(luò)應(yīng)用程序;
開(kāi)發(fā)異步、非阻塞的 UDP 網(wǎng)絡(luò)應(yīng)用程序;
開(kāi)發(fā)異步文件傳輸應(yīng)用程序;
開(kāi)發(fā)異步 HTTP 服務(wù)端和客戶端應(yīng)用程序;
提供對(duì)多種編解碼框架的集成,包括谷歌的 Protobuf、Jbossmarshalling、Java 序列化、壓縮編解碼、XML 解碼、字符串編解碼等,這些編解碼框架可以被用戶直接使用;
提供形式多樣的編解碼基礎(chǔ)類(lèi)庫(kù),可以非常方便的實(shí)現(xiàn)私有協(xié)議棧編解碼框架的二次定制和開(kāi)發(fā);
基于職責(zé)鏈模式的 Pipeline-Handler 機(jī)制,用戶可以非常方便的對(duì)網(wǎng)絡(luò)事件進(jìn)行攔截和定制;
所有的 IO 操作都是異步的,用戶可以通過(guò) Future-Listener 機(jī)制主動(dòng) Get 結(jié)果或者由 IO 線程操作完成之后主動(dòng) Notify 結(jié)果,用戶的業(yè)務(wù)線程不需要同步等待;
IP 黑白名單控制;
打印消息碼流;
流量控制和整形;
性能統(tǒng)計(jì);
基于鏈路空閑事件檢測(cè)的心跳檢測(cè)
……
3.Netty 在哪些行業(yè)得到了應(yīng)用?
互聯(lián)網(wǎng)行業(yè):隨著網(wǎng)站規(guī)模的不斷擴(kuò)大,系統(tǒng)并發(fā)訪問(wèn)量也越來(lái)越高,傳統(tǒng)基于 Tomcat 等 Web 容器的垂直架構(gòu)已經(jīng)無(wú)法滿足需求,需要拆分應(yīng)用進(jìn)行服務(wù)化,以提高開(kāi)發(fā)和維護(hù)效率。從組網(wǎng)情況看,垂直的架構(gòu)拆分之后,系統(tǒng)采用分布式部署,各個(gè)節(jié)點(diǎn)之間需要遠(yuǎn)程服務(wù)調(diào)用,高性能的 RPC 框架必不可少,Netty 作為異步高性能的通信框架,往往作為基礎(chǔ)通信組件被這些 RPC 框架使用。
典型的應(yīng)用有:阿里分布式服務(wù)框架 Dubbo 的 RPC 框架使用 Dubbo 協(xié)議進(jìn)行節(jié)點(diǎn)間通信,Dubbo 協(xié)議默認(rèn)使用 Netty 作為基礎(chǔ)通信組件,用于實(shí)現(xiàn)各進(jìn)程節(jié)點(diǎn)之間的內(nèi)部通信。它的架構(gòu)圖如下:
圖1-1 Dubbo 節(jié)點(diǎn)間調(diào)用關(guān)系圖
其中,服務(wù)提供者和服務(wù)消費(fèi)者之間,服務(wù)提供者、服務(wù)消費(fèi)者和性能統(tǒng)計(jì)節(jié)點(diǎn)之間使用 Netty 進(jìn)行異步/同步通信。
除了 Dubbo 之外,淘寶的消息中間件 RocketMQ 的消息生產(chǎn)者和消息消費(fèi)者之間,也采用 Netty 進(jìn)行高性能、異步通信。
除了阿里系和淘寶系之外,很多其它的大型互聯(lián)網(wǎng)公司或者電商內(nèi)部也已經(jīng)大量使用 Netty 構(gòu)建高性能、分布式的網(wǎng)絡(luò)服務(wù)器。
游戲行業(yè):無(wú)論是手游服務(wù)端、還是大型的網(wǎng)絡(luò)游戲,Java 語(yǔ)言得到了越來(lái)越廣泛的應(yīng)用。Netty 作為高性能的基礎(chǔ)通信組件,它本身提供了 TCP/UDP 和 HTTP 協(xié)議棧,非常方便定制和開(kāi)發(fā)私有協(xié)議棧。賬號(hào)登陸服務(wù)器、地圖服務(wù)器之間可以方便的通過(guò) Netty 進(jìn)行高性能的通信,架構(gòu)示意圖如下:
圖1-2 Netty 在游戲服務(wù)器架構(gòu)中的應(yīng)用
大數(shù)據(jù)領(lǐng)域:經(jīng)典的 Hadoop 的高性能通信和序列化組件 Avro 的 RPC 框架,默認(rèn)采用 Netty 進(jìn)行跨節(jié)點(diǎn)通信,它的 Netty Service 基于 Netty 框架二次封裝實(shí)現(xiàn)。
大數(shù)據(jù)計(jì)算往往采用多個(gè)計(jì)算節(jié)點(diǎn)和一個(gè)/N個(gè)匯總節(jié)點(diǎn)進(jìn)行分布式部署,各節(jié)點(diǎn)之間存在海量的數(shù)據(jù)交換。由于 Netty 的綜合性能是目前各個(gè)成熟 NIO 框架中最高的,因此,往往會(huì)被選中用作大數(shù)據(jù)各節(jié)點(diǎn)間的通信。
企業(yè)軟件:企業(yè)和 IT 集成需要 ESB,Netty 對(duì)多協(xié)議支持、私有協(xié)議定制的簡(jiǎn)潔性和高性能是 ESB RPC 框架的首選通信組件。事實(shí)上,很多企業(yè)總線廠商會(huì)選擇 Netty 作為基礎(chǔ)通信組件,用于企業(yè)的 IT 集成。
通信行業(yè):Netty 的異步高性能、高可靠性和高成熟度的優(yōu)點(diǎn),使它在通信行業(yè)得到了大量的應(yīng)用。
4.使用傳統(tǒng)的 Socket 開(kāi)發(fā)挺簡(jiǎn)單的,我為什么要切換到 NIO 進(jìn)行編程呢?
首先我們看下傳統(tǒng)基于同步阻塞 IO(BIO)的線程模型圖:
圖1-3 同步阻塞 IO(BIO)線程模型圖
由上圖我們可以看出,傳統(tǒng)的同步阻塞 IO 通信存在如下幾個(gè)問(wèn)題:
線程模型存在致命缺陷:一連接一線程的模型導(dǎo)致服務(wù)端無(wú)法承受大量客戶端的并發(fā)連接;
性能差:頻繁的線程上下文切換導(dǎo)致 CPU 利用效率不高;
可靠性差:由于所有的 IO 操作都是同步的,所以業(yè)務(wù)線程只要進(jìn)行 IO 操作,也會(huì)存在被同步阻塞的風(fēng)險(xiǎn),這會(huì)導(dǎo)致系統(tǒng)的可靠性差,依賴(lài)外部組件的處理能力和網(wǎng)絡(luò)的情況。
采用非阻塞 IO(NIO)之后,同步阻塞 IO 的三個(gè)缺陷都將迎刃而解:
Nio 采用 Reactor 模式,一個(gè) Reactor 線程聚合一個(gè)多路復(fù)用器 Selector,它可以同時(shí)注冊(cè)、監(jiān)聽(tīng)和輪詢成百上千個(gè) Channel,一個(gè) IO 線程可以同時(shí)并發(fā)處理N個(gè)客戶端連接,線程模型優(yōu)化為1:N(N < 進(jìn)程可用的最大句柄數(shù))或者 M : N (M通常為 CPU 核數(shù) + 1, N < 進(jìn)程可用的最大句柄數(shù));
由于 IO 線程總數(shù)有限,不會(huì)存在頻繁的 IO 線程之間上下文切換和競(jìng)爭(zhēng),CPU 利用率高;
所有的 IO 操作都是異步的,即使業(yè)務(wù)線程直接進(jìn)行 IO 操作,也不會(huì)被同步阻塞,系統(tǒng)不再依賴(lài)外部的網(wǎng)絡(luò)環(huán)境和外部應(yīng)用程序的處理性能。
由于切換到 NIO 編程之后可以為系統(tǒng)帶來(lái)巨大的可靠性、性能提升,所以,目前采用 NIO 進(jìn)行通信已經(jīng)逐漸成為主流。
5.為什么不直接基于 JDK 的 NIO 類(lèi)庫(kù)編程呢?
我們通過(guò) JDK NIO 服務(wù)端和客戶端的工作時(shí)序圖來(lái)回答下這個(gè)問(wèn)題:
圖1-4 JDK NIO 服務(wù)端創(chuàng)建和通信序列圖
即便拋開(kāi)代碼和 NIO 類(lèi)庫(kù)復(fù)雜性不談,一個(gè)高性能、高可靠性的 NIO 服務(wù)端開(kāi)發(fā)和維護(hù)成本都是非常高的,開(kāi)發(fā)者需要具有豐富的 NIO 編程經(jīng)驗(yàn)和網(wǎng)絡(luò)維護(hù)經(jīng)驗(yàn),很多時(shí)候甚至需要通過(guò)抓包來(lái)定位問(wèn)題。也許開(kāi)發(fā)出一套 NIO 程序需要 1 個(gè)月,但是它的穩(wěn)定很可能需要 1 年甚至更長(zhǎng)的時(shí)間,這也就是為什么我不建議直接使用 JDK NIO 類(lèi)庫(kù)進(jìn)行通信開(kāi)發(fā)的一個(gè)重要原因。
下面再一起看下 JDK NIO 客戶端的通信時(shí)序圖:它同樣非常復(fù)雜。
圖1-5 JDK NIO 客戶端創(chuàng)建和通信序列圖
6.為什么要選擇 Netty 框架?
Netty 是業(yè)界最流行的 NIO 框架之一,它的健壯性、功能、性能、可定制性和可擴(kuò)展性在同類(lèi)框架中都是首屈一指的,它已經(jīng)得到成百上千的商用項(xiàng)目驗(yàn)證,例如 Hadoop 的 RPC 框架 Avro 使用 Netty 作為通信框架。很多其它業(yè)界主流的 RPC 和分布式服務(wù)框架,也使用 Netty 來(lái)構(gòu)建高性能的異步通信能力。
Netty 的優(yōu)點(diǎn)總結(jié)如下:
API 使用簡(jiǎn)單,開(kāi)發(fā)門(mén)檻低;
功能強(qiáng)大,預(yù)置了多種編解碼功能,支持多種主流協(xié)議;
定制能力強(qiáng),可以通過(guò) ChannelHandler 對(duì)通信框架進(jìn)行靈活的擴(kuò)展;
性能高,通過(guò)與其它業(yè)界主流的 NIO 框架對(duì)比,Netty 的綜合性能最優(yōu);
社區(qū)活躍,版本迭代周期短,發(fā)現(xiàn)的 BUG 可以被及時(shí)修復(fù),同時(shí),更多的新功能會(huì)被加入;
經(jīng)歷了大規(guī)模的商業(yè)應(yīng)用考驗(yàn),質(zhì)量得到驗(yàn)證。在互聯(lián)網(wǎng)、大數(shù)據(jù)、網(wǎng)絡(luò)游戲、企業(yè)應(yīng)用、電信軟件等眾多行業(yè)得到成功商用,證明了它完全滿足不同行業(yè)的商用標(biāo)準(zhǔn)。
正是因?yàn)檫@些優(yōu)點(diǎn),Netty 逐漸成為 Java NIO 編程的首選框架。
7.聽(tīng)說(shuō) Netty 各版本的 API 變化比較頻繁,我該如何選擇版本?
事實(shí)上,Netty 各版本之間的 API 變更并沒(méi)有一些人講的那么可怕,最大的變更就是 3.X 系列到 4.X/5.X 的變更,Netty 不僅僅重構(gòu)了包路徑,對(duì)于之前一直想改但是考慮到前向兼容性沒(méi)改的類(lèi)庫(kù)進(jìn)行了優(yōu)化和修改。這次變更的主要原因是 Netty 脫離了 Jboss 獨(dú)立發(fā)展,這對(duì)于 Netty 的長(zhǎng)遠(yuǎn)發(fā)展是件好事。
在我看來(lái),Netty4.X 系列版本的架構(gòu)和 API 設(shè)計(jì)更加合理,同時(shí),它提供了更多新的特性。因此,我個(gè)人建議用戶可以選擇 4.X 系列版本,以免未來(lái)升級(jí)遇到困難和問(wèn)題。
對(duì)于已經(jīng)使用 3.X 系列版本的用戶,如果現(xiàn)有功能已經(jīng)滿足需求,短期內(nèi)暫時(shí)不需要升級(jí)。如果需要使用更多新特性和功能,建議在充分評(píng)估之后進(jìn)行升級(jí),這可能需要一些工作量。
由于 Netty5 最新版本仍處于測(cè)試階段,從學(xué)習(xí)和研究角度可以試用一下,Netty5 相比于 Netty4 是前向兼容的,因此,未來(lái)用戶升級(jí)到 Netty5 會(huì)更加容易。
8.Netty 和 Mina 我究竟該選擇哪個(gè)?
根據(jù)我的經(jīng)驗(yàn),無(wú)論選擇哪個(gè),都是個(gè)正確的選擇。兩者各有千秋,Netty 在內(nèi)存管理方面更勝一籌,綜合性能也更優(yōu)。但是,API 變更的管理和兼容性做的不是太好。相比于 Netty,Mina 的前向兼容性、內(nèi)聚的可維護(hù)性功能更多,例如 JMX 的集成、性能統(tǒng)計(jì)、狀態(tài)機(jī)等。
建議用戶可以根據(jù)自己對(duì)兩者的熟悉程度和實(shí)際項(xiàng)目需求,做出最佳選擇。如果你鎖定了兩者,本身就意味著你做出了正確選擇,不需要再糾結(jié)于選擇哪個(gè)而和領(lǐng)導(dǎo)、同事吵得面紅耳赤。
9.Netty 使用簡(jiǎn)單嗎?
Netty 的基礎(chǔ)開(kāi)發(fā)和應(yīng)用非常簡(jiǎn)單,開(kāi)發(fā)一個(gè) Echo 服務(wù)端只需要 28 行代碼,開(kāi)發(fā)對(duì)應(yīng)的 Echo 客戶端只需要 26 行代碼!
但是,如果你要利用它進(jìn)行私有協(xié)議棧開(kāi)發(fā)、HTTP 服務(wù)端和客戶端開(kāi)發(fā)等,仍然需要深入的學(xué)習(xí) Netty 的一些高級(jí)類(lèi)庫(kù)和功能,了解 Netty 的設(shè)計(jì)原理。只有這樣,才能恰到好處的使用 Netty,為項(xiàng)目和公司帶來(lái)更大的價(jià)值。
10.有沒(méi)有 Netty 相關(guān)的書(shū)籍供學(xué)習(xí)和參考?
2014 年5-6 月,中國(guó)第一本學(xué)習(xí) Netty 的教材《Netty 權(quán)威指南》將由電子工業(yè)出版社博文視點(diǎn)出版。
全書(shū)共 23 個(gè)章節(jié),從 JAVA IO 的歷史演進(jìn)講起,包括 NIO 基礎(chǔ)入門(mén)、Netty 基礎(chǔ)入門(mén)、Netty 編解碼框架的使用和開(kāi)發(fā)、UDP 開(kāi)發(fā)、異步文件傳輸、基于 Netty 的異步 HTTP 協(xié)議棧開(kāi)發(fā)和應(yīng)用、半包解碼器的定制和使用、私有協(xié)議棧的設(shè)計(jì)和開(kāi)發(fā)、行業(yè)應(yīng)用、架構(gòu)剖析、核心類(lèi)庫(kù)的功能講解和源碼分析等。
無(wú)論你是初學(xué)者,還是 NIO 高手,都能從本書(shū)中汲取營(yíng)養(yǎng),為掌握乃至精通 Netty 提供快捷通道。
11.我是大學(xué)畢業(yè)生,正在學(xué)習(xí) Java,聽(tīng)說(shuō)掌握 Netty 等 NIO 框架找工作會(huì)相對(duì)容易一些,是真的嗎?
從我的經(jīng)驗(yàn)和 Netty 行業(yè)應(yīng)用來(lái)看,前景無(wú)限好!下面我們通過(guò)谷歌搜索簡(jiǎn)單看下現(xiàn)在市場(chǎng)對(duì) Netty 和 Mina 的需求。
下面是我的一小部分搜索結(jié)果:
由于搜索結(jié)果太多,我就不一一枚舉。市場(chǎng)上對(duì) Netty 和 Mina 的需求非常旺盛,而且相對(duì)高端,所以薪水會(huì)更高些。例如,深圳某國(guó)企開(kāi)出的薪水在 20W 以上,上不封頂,這足以說(shuō)明 Netty 的“高大上”。
就個(gè)人而言,我無(wú)意冒犯或者貶低其它技術(shù),但是,相比于 WEB 前臺(tái)開(kāi)發(fā)/精通 Spring 框架等,精通和熟悉 Netty 的人畢竟是非常少的。一個(gè)原因是異步網(wǎng)絡(luò)編程的復(fù)雜性,另一個(gè)原因是中國(guó)的 NIO 編程正處于方興未艾階段,市場(chǎng)需求在逐漸增大,開(kāi)始出現(xiàn)井噴。但是精通 NIO 編程和具有相關(guān)經(jīng)驗(yàn)的人太少,導(dǎo)致供需不平衡,這也是最近 Netty 越來(lái)越火的一個(gè)重要原因,市場(chǎng)需求決定技術(shù)導(dǎo)向。
【作者簡(jiǎn)介】李林鋒:現(xiàn)就職于某世界五百?gòu)?qiáng)通信公司,擁有 5 年 NIO 設(shè)計(jì)、開(kāi)發(fā)和維護(hù)經(jīng)驗(yàn),長(zhǎng)期從事高性能通信軟件的架構(gòu)設(shè)計(jì)和開(kāi)發(fā)工作,設(shè)計(jì)的多款平臺(tái)軟件已經(jīng)成功在N個(gè)商業(yè)局點(diǎn)穩(wěn)定運(yùn)行多年。
聯(lián)系方式:新浪微博:@Nettying 郵箱:neu_lilinfeng@sina.com
聯(lián)系客服