1. 程式人生 > >《Netty 權威指南》—— 選擇Netty的理由

《Netty 權威指南》—— 選擇Netty的理由

《Netty 權威指南》—— 選擇Netty的理由

宣告:本文是《Netty 權威指南》的樣章,感謝博文視點授權併發程式設計網站釋出樣章,禁止以任何形式轉載此文。

在開始本節之前,我先講一個親身經歷的故事:曾經有兩個專案組同時用到了NIO程式設計技術,一個專案組選擇自己開發NIO服務端,直接使用JDK原生的API,結果2個多月過去了,他們的NIO服務端始終無法穩定,問題頻出。由於NIO通訊是它們的核心元件之一,因此,專案的進度受到了嚴重的影響,領導對此非常惱火。另一個專案組直接使用Netty作為NIO服務端,業務的定製開發工作量非常小,測試表明,功能和效能都完全達標,專案組幾乎沒有在NIO服務端上花費額外的時間和精力,專案進展也非常順利。

這兩個專案組的不同遭遇提醒我們:開發出高質量的NIO程式並不是一件簡單的事情,除去NIO固有的複雜性和BUG不談,作為一個NIO服務端需要能夠處理網路的閃斷、客戶端的重複接入、客戶端的安全認證、訊息的編解碼、半包讀寫等等,如果你沒有足夠的NIO程式設計經驗積累,一個NIO框架的穩定往往需要半年甚至更長的時間。更為糟糕的是一旦在生產環境中發生問題,往往會導致跨節點的服務呼叫中斷,嚴重的可能會導致整個叢集環境都不可用,需要重啟伺服器,這種非正常停機會帶來巨大的損失。

從可維護性角度看,由於NIO採用了非同步非阻塞程式設計模型,而且是一個IO執行緒處理多條鏈路,它的除錯和跟蹤非常麻煩,特別是生產環境中的問題,我們無法有效除錯和跟蹤,往往只能靠一些日誌來輔助分析,定位難度很大。

 

2.6.1.不選擇JAVA原生NIO程式設計的原因

在本小節,我們總結下為什麼不建議開發者直接使用JDK的NIO類庫進行開發的原因:

1)      NIO的類庫和API繁雜,使用麻煩,你需要熟練掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等;

2)      需要具備其它的額外技能做鋪墊,例如熟悉Java多執行緒程式設計,因為NIO程式設計涉及到Reactor模式,你必須對多執行緒和網路程式設計非常熟悉,才能編寫出高質量的NIO程式;

3)      可靠效能力補齊,工作量和難度都非常大。例如客戶端面臨斷連重連、網路閃斷、半包讀寫、失敗快取、網路擁塞和異常碼流的處理等等,NIO程式設計的特點是功能開發相對容易,但是可靠效能力補齊工作量和難度都非常大;

4)      JDK NIO的BUG,例如臭名昭著的epoll bug,它會導致Selector空輪詢,最終導致CPU 100%。官方聲稱在JDK1.6版本的update18修復了該問題,但是直到JDK1.7版本該問題仍舊存在,只不過該bug發生概率降低了一些而已,它並沒有被根本解決。該BUG以及與該BUG相關的問題單如下:

http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6403933

http://bugs.java.com/bugdatabase/view_bug.do?bug_id=2147719

異常堆疊如下:

01 java.lang.Thread.State: RUNNABLE
02         at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
03         at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:210)
04         at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:65)
05         at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:69)
06         - locked <0x0000000750928190> (a sun.nio.ch.Util$2)
07         - locked <0x00000007509281a8> (a java.util.Collections$UnmodifiableSet)
08         - locked <0x0000000750946098> (a sun.nio.ch.EPollSelectorImpl)
09         at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:80)
10         at net.spy.memcached.MemcachedConnection.handleIO(MemcachedConnection.java:217)
11         at net.spy.memcached.MemcachedConnection.run(MemcachedConnection.java:836)

由於上述原因,在大多數場景下,我不建議大家直接使用JDK的NIO類庫,除非你精通NIO程式設計或者有特殊的需求,在絕大多數的業務場景中,我們可以使用NIO框架Netty來進行NIO程式設計,它既可以作為客戶端也可以作為服務端,同時支援UDP和非同步檔案傳輸,功能非常強大。

下個小節我們就看看為什麼選擇Netty作為基礎通訊框架。

2.6.2.為什麼選擇Netty

Netty是業界最流行的NIO框架之一,它的健壯性、功能、效能、可定製性和可擴充套件性在同類框架中都是首屈一指的,它已經得到成百上千的商用專案驗證,例如Hadoop的RPC框架avro使用Netty作為底層通訊框架。很多其它業界主流的RPC框架,也使用Netty來構建高效能的非同步通訊能力。

通過對Netty的分析,我們將它的優點總結如下:

1)      API使用簡單,開發門檻低;

2)      功能強大,預置了多種編解碼功能,支援多種主流協議;

3)      定製能力強,可以通過ChannelHandler對通訊框架進行靈活的擴充套件;

4)      效能高,通過與其它業界主流的NIO框架對比,Netty的綜合性能最優;

5)      成熟、穩定,Netty修復了已經發現的所有JDK NIO BUG,業務開發人員不需要再為NIO的BUG而煩惱;

6)      社群活躍,版本迭代週期短,發現的BUG可以被及時修復,同時,更多的新功能會被加入;

7)      經歷了大規模的商業應用考驗,質量已經得到驗證。在網際網路、大資料、網路遊戲、企業應用、電信軟體等眾多行業得到成功商用,證明了它可以完全滿足不同行業的商業應用。

正是因為這些優點,Netty逐漸成為Java NIO程式設計的首選框架。

2.7 .總結

本章通過一個簡單的demo開發-時間伺服器程式,讓大家熟悉傳統的同步阻塞IO、偽非同步IO、非阻塞IO(NIO)和非同步IO(AIO)的程式設計和使用差異。然後對比了各自的優缺點,給出了使用建議。

最後,我們詳細介紹了為什麼不建議讀者朋友們直接使用JDK的NIO原生類庫進行非同步IO的開發,同時對Netty的優點進行分析和總結,給出使用Netty進行NIO開發的理由。

相信學完本章之後,大家對Java的網路程式設計已經有了初步的認識,從下一個章節開始,我們正式進入Netty的世界,學習和掌握基於Netty的網路開發。

原創文章,轉載請註明: 轉載自併發程式設計網 – ifeve.com本文連結地址: 《Netty 權威指南》—— 選擇Netty的理由