這篇文章將為大家詳細(xì)講解有關(guān)傳統(tǒng)的BIO編程中Netty開(kāi)發(fā)環(huán)境如何搭建,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
讓客戶(hù)滿(mǎn)意是我們工作的目標(biāo),不斷超越客戶(hù)的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶(hù),將通過(guò)不懈努力成為客戶(hù)在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名注冊(cè)、網(wǎng)絡(luò)空間、營(yíng)銷(xiāo)軟件、網(wǎng)站建設(shè)、湟源網(wǎng)站維護(hù)、網(wǎng)站推廣。
1.1 傳統(tǒng)的BIO編程
網(wǎng)絡(luò)編程的基本模型是 Client/Server 模型,也就是兩個(gè)進(jìn)程之間進(jìn)行相互通信,其中服務(wù)端提供位置信息(綁定的 IP 地址和監(jiān)聽(tīng)端口),客戶(hù)端通過(guò)連接操作向服務(wù)端監(jiān)聽(tīng)的地址發(fā)起連接請(qǐng)求,通過(guò)三次握手建立連接,如果連接建立成功,雙方就可以通過(guò)網(wǎng)絡(luò)套接字(Socket)進(jìn)行通信。
在基于傳統(tǒng)同步阻塞模型開(kāi)發(fā)中,ServerSocket 負(fù)責(zé)綁定 IP 地址,啟動(dòng)監(jiān)聽(tīng)端口;Socket 負(fù)責(zé)發(fā)起連接操作。連接成功之后,雙方通過(guò)輸入和輸出流進(jìn)行同步阻塞式通信。
1.1.1 BIO 通信模型圖
首先,我們通過(guò)圖 2-1 所示的通信模型圖來(lái)熟悉下 BIO 的服務(wù)端通信模型:
采用 BIO 通信模型的服務(wù)端,通常由一個(gè)獨(dú)立的 Acceptor 線(xiàn)程負(fù)責(zé)監(jiān)聽(tīng)客戶(hù)端的連接,它接收到客戶(hù)端連接請(qǐng)求之后為每個(gè)客戶(hù)端創(chuàng)建一個(gè)新的線(xiàn)程進(jìn)行鏈路處理,處理完成之后,通過(guò)輸出流返回應(yīng)答給客戶(hù)端,線(xiàn)程銷(xiāo)毀。這就是典型的一請(qǐng)求一應(yīng)答通信模型。
圖1-1同步阻塞 1/0服務(wù)端通信模型(1客戶(hù)端1線(xiàn)程)
該模型最大的問(wèn)題就是缺乏彈性伸縮能力,當(dāng)客戶(hù)端并發(fā)訪(fǎng)問(wèn)量增加后,服務(wù)端的線(xiàn)程個(gè)數(shù)和客戶(hù)端并發(fā)訪(fǎng)問(wèn)數(shù)呈 1:1 的正比關(guān)系,由于線(xiàn)程是 Java 虛擬機(jī)非常寶貴的系統(tǒng)資源,當(dāng)線(xiàn)程數(shù)膨脹之后,系統(tǒng)的性能將急劇下降,隨著并發(fā)訪(fǎng)問(wèn)量的繼續(xù)增大,系統(tǒng)會(huì)發(fā)生線(xiàn)程堆棧溢出、創(chuàng)建新線(xiàn)程失敗等問(wèn)題,并最終導(dǎo)致進(jìn)程宕機(jī)或者僵死,不能對(duì)外提供服務(wù)。
1.2 偽異步I/O編程
為了解決同步阻塞 I/O 面臨的一個(gè)鏈路需要一個(gè)線(xiàn)程處理的問(wèn)題,后來(lái)有人對(duì)它的線(xiàn)程模型進(jìn)行了優(yōu)化,后端通過(guò)一個(gè)線(xiàn)程池來(lái)處理多個(gè)客戶(hù)端的請(qǐng)求接入,形成客戶(hù)端個(gè)數(shù) M:線(xiàn)程池最大線(xiàn)程數(shù) N 的比例關(guān)系,其中 M 可以遠(yuǎn)遠(yuǎn)大于 N,通過(guò)線(xiàn)程池可以靈活的調(diào)配線(xiàn)程資源,設(shè)置線(xiàn)程的最大值,防止由于海量并發(fā)接入導(dǎo)致線(xiàn)程耗盡。
下面,我們結(jié)合連接模型圖和源碼,對(duì)偽異步 I/O 進(jìn)行分析,看它是否能夠解決同步阻塞 I/O 面臨的問(wèn)題。
1.2.1 偽異步 I/O 模型圖
采用線(xiàn)程池和任務(wù)隊(duì)列可以實(shí)現(xiàn)一種叫做偽異步的 I/O 通信框架,它的模型圖如圖 1-2 所示。
當(dāng)有新的客戶(hù)端接入的時(shí)候,將客戶(hù)端的 Socket 封裝成一個(gè) Task(該任務(wù)實(shí)現(xiàn) java.lang.Runnable 接口)投遞到后端的線(xiàn)程池中進(jìn)行處理,JDK 的線(xiàn)程池維護(hù)一個(gè)消息隊(duì)列和 N 個(gè)活躍線(xiàn)程對(duì)消息隊(duì)列中的任務(wù)進(jìn)行處理。由于線(xiàn)程池可以設(shè)置消息隊(duì)列的大小和最大線(xiàn)程數(shù),因此,它的資源占用是可控的,無(wú)論多少個(gè)客戶(hù)端并發(fā)訪(fǎng)問(wèn),都不會(huì)導(dǎo)致資源的耗盡和宕機(jī)。
圖 1-2 偽異步I/0服務(wù)端通信模型(M: N)
偽異步 I/O 實(shí)際上僅僅只是對(duì)之前 I/O 線(xiàn)程模型的一個(gè)簡(jiǎn)單優(yōu)化,它無(wú)法從根本上解決同步 I/O 導(dǎo)致的通信線(xiàn)程阻塞問(wèn)題。下面我們就簡(jiǎn)單分析下如果通信對(duì)方返回應(yīng)答時(shí)間過(guò)長(zhǎng),會(huì)引起的級(jí)聯(lián)故障。
1. 服務(wù)端處理緩慢,返回應(yīng)答消息耗費(fèi)60s,平時(shí)只需要10ms。
2. 采用偽異步I/O的線(xiàn)程正在讀取故障服務(wù)節(jié)點(diǎn)的響應(yīng),由于讀取輸入流是阻塞的,因此,它將會(huì)被同步阻塞60s。
3. 假如所有的可用線(xiàn)程都被故障服務(wù)器阻塞,那后續(xù)所有的I/O消息都將在隊(duì)列中排隊(duì)。
4. 由于線(xiàn)程池采用阻塞隊(duì)列實(shí)現(xiàn),當(dāng)隊(duì)列積滿(mǎn)之后,后續(xù)入隊(duì)列的操作將被阻塞。
5. 由于前端只有一個(gè)Accptor線(xiàn)程接收客戶(hù)端接入,它被阻塞在線(xiàn)程池的同步阻塞隊(duì)列之后,新的客戶(hù)端請(qǐng)求消息將被拒絕,客戶(hù)端會(huì)發(fā)生大量的連接超時(shí)。
6. 由于幾乎所有的連接都超時(shí),調(diào)用者會(huì)認(rèn)為系統(tǒng)已經(jīng)崩潰,無(wú)法接收新的請(qǐng)求消息。
1.3 NIO編程
在介紹 NIO 編程之前,我們首先需要澄清一個(gè)概念:NIO 到底是什么的簡(jiǎn)稱(chēng)?
有人稱(chēng)之為 New I/O,因?yàn)樗鄬?duì)于之前的 I/O 類(lèi)庫(kù)是新增的,所以被稱(chēng)為 NewI/O,這是它的官方叫法。但是,由于之前老的 I/O 類(lèi)庫(kù)是阻塞 I/O,New I/O 類(lèi)庫(kù)的目標(biāo)就是要讓 Java 支持非阻塞 I/O,所以,更多的人喜歡稱(chēng)之為非阻塞 I/O(Non-block I/O),由于非阻塞 I/O 更能夠體現(xiàn) NIO 的特點(diǎn),所以本文使用的NIO 都指的是非阻塞 I/O。
與 Socket 類(lèi)和 ServerSocket 類(lèi)相對(duì)應(yīng),NIO 也提供了 SocketChannel 和ServerSocketChannel 兩種不同的套接字通道實(shí)現(xiàn)。這兩種新增的通道都支持阻塞和非阻塞兩種模式。阻塞模式使用非常簡(jiǎn)單,但是性能和可靠性都不好,非阻塞模式則正好相反。開(kāi)發(fā)人員一般可以根據(jù)自己的需要來(lái)選擇合適的模式,一般來(lái)說(shuō),低負(fù)載、低并發(fā)的應(yīng)用程序可以選擇同步阻塞 I/O 以降低編程復(fù)雜度,但是對(duì)于高負(fù)載、高并發(fā)的網(wǎng)絡(luò)應(yīng)用,需要使用 NIO 的非阻塞模式進(jìn)行開(kāi)發(fā)。
1.4 AIO編程
NIO2.0 引入了新的異步通道的概念,并提供了異步文件通道和異步套接字通道的實(shí)現(xiàn)。異步通道提供兩種方式獲取獲取操作結(jié)果:
通過(guò)java.util.concurrent.Future類(lèi)來(lái)表示異步操作的結(jié)果;
在執(zhí)行異步操作的時(shí)候傳入一個(gè)java.nio.channels;
CompletionHandler接口的實(shí)現(xiàn)類(lèi)作為操作完成的回調(diào)。
NIO2.0 的異步套接字通道是真正的異步非阻塞 I/O,它對(duì)應(yīng) UNIX 網(wǎng)絡(luò)編程中的事件驅(qū)動(dòng) I/O(AIO),它不需要通過(guò)多路復(fù)用器(Selector)對(duì)注冊(cè)的通道進(jìn)行輪詢(xún)操作即可實(shí)現(xiàn)異步讀寫(xiě),從而簡(jiǎn)化了 NIO 的編程模型。
1.5 幾種I/O模型對(duì)比
不同的 I/O 模型由于線(xiàn)程模型、API 等差別很大,所以用法的差異也非常大。
由于之前的幾個(gè)小節(jié)已經(jīng)集中對(duì)這幾種 I/O 的 API 和用法進(jìn)行了說(shuō)明,本小節(jié)會(huì)重點(diǎn)對(duì)這幾種 I/O 進(jìn)行功能對(duì)比。如表 2-1 所示。
表 1-1 幾種 I/O 模型的功能和特性對(duì)比
1.6 業(yè)界主流的NIO框架介紹
隨著移動(dòng)互聯(lián)網(wǎng)的發(fā)展和大數(shù)據(jù)時(shí)代的到來(lái),大規(guī)模分布式服務(wù)框架、分布式流計(jì)算框架已經(jīng)成為架構(gòu)主流,分布式服務(wù)節(jié)點(diǎn)之間的通信形式往往是內(nèi)部長(zhǎng)連接,例如 FaceBook 的 Thrift 協(xié)議,為了提升節(jié)點(diǎn)間的通信吞吐量、提升通信性能,目前主流的內(nèi)部通信框架均使用 NIO 框架,對(duì)于大公司、技術(shù)積累比較深的團(tuán)隊(duì)可能會(huì)使用自研的 NIO 框架來(lái)滿(mǎn)足個(gè)性化或者行業(yè)特殊的需求,但是大多數(shù)架構(gòu)師會(huì)選擇業(yè)界主流的 NIO 框架進(jìn)行異步通信開(kāi)發(fā)。
目前,業(yè)界主流的 NIO 框架主要有兩款:Mina 和 Netty,兩者都使用 ApacheLICENSE-2.0 進(jìn)行開(kāi)源。不同之處是 Mina 是 Apache 基金會(huì)的官方 NIO 框架,Netty 之前是 Jboss 的 NIO 框架,后來(lái)脫離 Jboss 獨(dú)立申請(qǐng)了 netty.io 域名,與 Jboss 脫離關(guān)系,并對(duì)版本進(jìn)行了重構(gòu),導(dǎo)致 API 無(wú)法向上兼容。
Mina 和 Netty 還 有一段 歷 史 淵 源,Mina 最 初 版 本 的 架 構(gòu) 師 是 TrustinLee,后來(lái),由于種種原因,Trustin Lee 離開(kāi)了 Mina 社區(qū)加入到了 Netty 團(tuán)隊(duì),重新設(shè)計(jì)并開(kāi)發(fā)了 Netty。很多讀者會(huì)發(fā)現(xiàn) Netty 中透著 Mina 的影子,兩個(gè)框架的架構(gòu)理念也有很多相似之處,甚至一些代碼都非常相似,原因就在這里。
目前,Mina 和 Netty 的應(yīng)用已經(jīng)非常廣泛,很多開(kāi)源框架都使用兩者做底層的 NIO 框架,例如 Hadoop 的通信組件 Avro 使用 Netty 做底層的通信框架,
Openfire 則使用 Mina 做底層通信框架,相比于 Mina,Netty 社區(qū)目前更活躍,版本應(yīng)用范圍也更廣。
1.7 為什么選擇Netty
1.7.1 不選擇 Java 原生 NIO 編程的原因
現(xiàn)在我們總結(jié)一下為什么不建議開(kāi)發(fā)者直接使用 JDK 的 NIO 類(lèi)庫(kù)進(jìn)行開(kāi)發(fā),具體原因如下。
1. NIO的類(lèi)庫(kù)和API繁雜,使用麻煩,你需要熟練掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等。
2. 需要具備其他的額外技能做鋪墊,例如熟悉Java多線(xiàn)程編程。這是因?yàn)镹IO編程涉及到Reactor模式,你必須對(duì)多線(xiàn)程和網(wǎng)路編程非常熟悉,才能編寫(xiě)出高質(zhì)量的NIO程序。
3. 可靠性能力補(bǔ)齊,工作量和難度都非常大。例如客戶(hù)端面臨斷連重連、網(wǎng)絡(luò)閃斷、半包讀寫(xiě)、失敗緩存、網(wǎng)絡(luò)擁塞和異常碼流的處理等問(wèn)題,NIO編程的特點(diǎn)是功能開(kāi)發(fā)相對(duì)容易,但是可靠性能力補(bǔ)齊的工作量和難度都非常大。
4. JDK NIO的BUG,例如臭名昭著的epoll bug,它會(huì)導(dǎo)致Selector空輪詢(xún),最終導(dǎo)致CPU 100%。官方聲稱(chēng)在JDK1.6版本的update18修復(fù)了該問(wèn)題,但是直到JDK1.7版本該問(wèn)題仍舊存在,只不過(guò)該BUG發(fā)生概率降低了一些而已,它并沒(méi)有被根本解決。該BUG以及與該BUG相關(guān)的問(wèn)題單可以參見(jiàn)以下鏈接內(nèi)容。
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6403933
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=2147719
由于上述原因,在大多數(shù)場(chǎng)景下,不建議大家直接使用 JDK 的 NIO 類(lèi)庫(kù),除非你精通 NIO 編程或者有特殊的需求。在絕大多數(shù)的業(yè)務(wù)場(chǎng)景中,我們可以使用NIO 框架 Netty 來(lái)進(jìn)行 NIO 編程,它既可以作為客戶(hù)端也可以作為服務(wù)端,同時(shí)
支持 UDP 和異步文件傳輸,功能非常強(qiáng)大。
1.7.2 選擇 Netty 的理由
Netty 是業(yè)界最流行的 NIO 框架之一,它的健壯性、功能、性能、可定制性和可擴(kuò)展性在同類(lèi)框架中都是首屈一指的,它已經(jīng)得到成百上千的商用項(xiàng)目驗(yàn)證,例如 Hadoop 的 RPC 框架 avro 使用 Netty 作為底層通信框架;很多其他業(yè)界主流的 RPC 框架,也使用 Netty 來(lái)構(gòu)建高性能的異步通信能力。
通過(guò)對(duì) 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)行靈活地?cái)U(kuò)展;
性能高,通過(guò)與其他業(yè)界主流的NIO框架對(duì)比,Netty的綜合性能最優(yōu);
成熟、穩(wěn)定,Netty修復(fù)了已經(jīng)發(fā)現(xiàn)的所有JDK NIO BUG,業(yè)務(wù)開(kāi)發(fā)人員不需要再為NIO的BUG而煩惱;
社區(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è)得到成功商用,證明了它已經(jīng)完全能夠滿(mǎn)足不同行業(yè)的商業(yè)應(yīng)用了。
正是因?yàn)檫@些優(yōu)點(diǎn),Netty 逐漸成為 Java NIO 編程的首選框架。
Netty 的架構(gòu)圖如下所示。
1.8 Netty開(kāi)發(fā)環(huán)境搭建
首先假設(shè)你已經(jīng)在本機(jī)安裝了 JDK1.7,配置了 JDK 的環(huán)境變量 path,同時(shí)下載并正確啟動(dòng)了 IDE 工具 Eclipse。如果你是個(gè) Java 初學(xué)者,從來(lái)沒(méi)有在本機(jī)搭建過(guò) Java 開(kāi)發(fā)環(huán)境,建議你先選擇一本 Java 基礎(chǔ)入門(mén)的書(shū)籍或者課程學(xué)習(xí)。
假如你習(xí)慣于使用其他 IDE 工具進(jìn)行 Java 開(kāi)發(fā),例如 NetBeans IDE,也可以運(yùn)行本節(jié)的入門(mén)例程。但是,你需要根據(jù)自己實(shí)際使用的 IDE 進(jìn)行對(duì)應(yīng)的配置修改和調(diào)整,本書(shū)統(tǒng)一使用 eclipse-jee-kepler-SR1-win32 作為 Java 開(kāi)發(fā)工具。
1.8.1 下載 Netty 類(lèi)庫(kù)
訪(fǎng)問(wèn) Netty 的官網(wǎng) http://netty.io/,從【Downloads】標(biāo)簽頁(yè)選擇下載4.1.5.Final 軟件包,包含了源碼、編譯類(lèi)庫(kù)和 Java Doc,18.1M 左右,解壓之后的軟件包如下所示。
這時(shí)會(huì)發(fā)現(xiàn)里面包含了各個(gè)模塊的.jar 包和源碼,由于我們直接以二進(jìn)制類(lèi)庫(kù)的方式使用 Netty,所以只需要獲取 netty-all-4.1.5.Final.jar 即可。
1.8.2 開(kāi)發(fā)工程搭建
將 netty-all-4.1.5.Final.jar 導(dǎo)入到 Java 工程的 lib 目錄下(lib 目錄需要自建),右鍵單擊 netty
-all-4.1.5.Final.jar,在彈出的菜單中,選擇將.jar包添加到 Build Path 中,即可完成 Netty 開(kāi)發(fā)環(huán)境的搭建。
關(guān)于“傳統(tǒng)的BIO編程中Netty開(kāi)發(fā)環(huán)境如何搭建”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
當(dāng)前標(biāo)題:傳統(tǒng)的BIO編程中Netty開(kāi)發(fā)環(huán)境如何搭建
瀏覽路徑:http://www.chinadenli.net/article44/peipee.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站內(nèi)鏈、品牌網(wǎng)站設(shè)計(jì)、網(wǎng)站改版、建站公司、自適應(yīng)網(wǎng)站、企業(yè)網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)