選擇Netty作為基礎通信框架 .


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

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

從可維護性角度看,由於NIO采用了異步非阻塞編程模型,而且是一個I/O線程處理多條鏈路,它的調試和跟蹤非常麻煩,特別是生產環境中的問題,我們無法進行有效的調試和跟蹤,往往只能靠一些日志來輔助分析,定位難度很大。

不選擇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%。官方聲稱在JDK 1.6版本的update18修復了該問題,但是直到JDK 1.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

異常堆棧如下。

java.lang.Thread.State: RUNNABLE

        at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)

        at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:210)

        at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:65)

        at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:69)

        - locked <0x0000000750928190> (a sun.nio.ch.Util$2)

        - locked <0x00000007509281a8> (a java.util.Collections$ UnmodifiableSet)

        - locked <0x0000000750946098> (a sun.nio.ch.EPollSelectorImpl)

        at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:80)

        at net.spy.memcached.MemcachedConnection.handleIO(Memcached Connection.java:217)

        at net.spy.memcached.MemcachedConnection.run(MemcachedConnection. java:836)

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

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

為什么選擇Netty

Netty是業界最流行的NIO框架之一,它的健壯性、功能、性能、可定制性和可擴展性在同類框架中都是首屈一指的,它已經得到成百上千的商用項目驗證,例如Hadoop的RPC框架Avro就使用了Netty作為底層通信框架,其他還有業界主流的RPC框架,也使用Netty來構建高性能的異步通信能力。

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

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

◎    功能強大,預置了多種編解碼功能,支持多種主流協議;

◎    定制能力強,可以通過ChannelHandler對通信框架進行靈活地擴展;

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

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

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

◎    經歷了大規模的商業應用考驗,質量得到驗證。Netty在互聯網、大數據、網絡游戲、企業應用、電信軟件等眾多行業已經得到了成功商用,證明它已經完全能夠滿足不同行業的商業應用了。

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM