Netty簡介
Netty是由JBoss開發,基于JAVA NIO的一個高性能通信框架。之前幾篇文章介紹了Java NIO的一些基本的概念和API。但在實際的網絡開發中,其實很少使用Java NIO原生的API。主要有以下原因:
- 原生API使用單線程模型,不能很好利用多核優勢,如果自己去寫多線程結合起來比較麻煩;
- 原生API是直接使用的IO數據,沒有做任何封裝處理,對數據的編解碼、TCP的粘包和拆包、客戶端斷連、網絡的可靠性和安全性方面沒有做處理;
在《Netty權威指南》這本書里提到一個真實的故事,兩個項目團隊都要做基于NIO非阻塞特性構建高性能、異步和高可靠性的底層通信框架,但一個團隊選擇了基于Java NIO API從頭開發,另一個團隊選擇了基于Netty開發。最終,從頭開發的團隊遇到了各種各樣的問題,導致項目延遲,而基于Netty開發的團隊則進展順利。
其實網絡開發是一個比較復雜的事情,因為網絡的不穩定性,通常會遇到各種各樣的問題,比如前面提到的客戶端突然斷連、TCP的拆包和沾包等等。
幸運的是,網絡上已經有了這么一個成熟的框架幫我們處理了這些事情,這個框架就是Netty。Netty主要應用于以下領域:
- 高性能的RPC框架:常用于微服務之間的高性能遠程調用(如Dubbo)
- 游戲行業:Netty可以很輕松地定制和開發一個私有協議棧,
- 即時通訊:Netty基于Java NIO,并且做了一些優化,支持高性能的即時通訊
Netty可以做什么?
這里有一個Netty的功能特性的圖:
Netty Core提供了基本功能,包括文件零拷貝、基本的API、可擴展的基于事件的模型(下文詳細介紹)。
Netty支持非常多的協議,比如HTTP、WebSocket等。當然,Netty也可以自定義協議。常見協議的示例代碼可以參考netty源碼里面的example包。
Netty同時支持Java的BIO和NIO兩種方式。且很容易與Spring等主流框架進行集成。
Reactor 線程模型
首先介紹處理事件的兩種方式:
- 輪詢方式:線程不斷輪詢訪問相關事件發生源有沒有發生事件,有發生事件就調用事件處理邏輯。Java 原生的NIO就是使用的輪詢方式。
- 事件驅動方式,發生事件,主線程把事件放入事件隊列,在另外線程不斷循環消費事件列表中的事件,調用事件對應的處理邏輯處理事件。事件驅動方式也被稱為消息通知方式,其實是設計模式中觀察者模式的思路。
Reactor是反應堆的意思。Reactor線程模型是指通過一個或多個輸入,同時傳遞給服務處理器的服務請求的事件驅動處理模式。
Reactor模式主要工作原理如下圖:
Reactor 有一個專門負責監聽和分發事件的線程,如圖中的Service Handler,所有請求進來后,被它分發到具體的處理線程,如圖中的EventHandler去處理。
Reactor可能有多個,而Netty正是使用了多Reactor的線程模型。
Netty是怎么工作的?
Netty里面有兩個Group,分別是Boss Group和Worker Group。其中,Boss Group用于處于連接,Worker Group用于處理實際的讀寫IO。
Boss Group里面的NioEventLoop會輪詢accept事件,遇到有新的連接,就生成NIOSocketChannel,并把這個Channel注冊到Worker Group的Selector上。
Worker Group輪詢read和write事件,在可讀或者可寫條件滿足時,就進行處理。
Worker Group和Boss Group都是通過里面的NioEventLoop來操作的。NioEventLoop中維護了一個線程和任務隊列,支持異步提交執行任務,線程啟動時會調用NioEventLoop的run方法。
最后都會執行一個runAllTasks方法,它用于處理任務隊列中的任務。任務隊列中的任務包括用戶調用 eventloop.execute或schedule執行的任務,或者其他線程提交到該eventloop的任務。
示例代碼
以下是使用Netty創建一個Server的示例代碼。Client也可以使用Netty來創建,也可以使用之前文章里面的NIO示例代碼。這里就不展示基于Netty的Client端的代碼,只展示Server端的代碼了。
文章來源:xy的技術圈作者:xy的技術圈