1. 程式人生 > >第一章:Netty介紹

第一章:Netty介紹

start 做到 封裝 ssl 核心 需要 機制 情況 可用

1. Netty介紹

Netty是一款異步的事件驅動的網絡應用程序框架,支持快速地開發可維護的高性能的面向協議的服務器和客戶端Netty是基於NIO實現的,所以整個Netty都是異步操作,網絡應用程序通常需要有較高的可擴展性,無論是Netty還是其他的基於Java NIO的框架,都會提供可擴展性的解決方案。

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而煩惱;
3. Netty的功能非常豐富

Netty的包結構如下

技術分享

在這裏面,channelhandler兩部分比較復雜。我們不妨與Netty官方的結構圖對照一下,來了解其功能。

技術分享

  • Zero-Copy-Capable Rich Byte Buffer 零拷貝的Buffer。為什麽叫零拷貝?因為在數據傳輸時,最終處理的數據會需要對單個傳輸層的報文,進行組合或者拆分。NIO原生的ByteBuffer要做到這件事,需要對ByteBuffer內容進行拷貝,產生新的ByteBuffer,而Netty通過提供Composite(組合)和Slice(切分)兩種Buffer來實現零拷貝。這部分代碼在org.jboss.netty.buffer
    包中。
  • Universal Communication API 統一的通訊API。因為Java的Old I/O和New I/O,使用了互不兼容的API,而Netty則提供了統一的API(org.jboss.netty.channel.Channel)來封裝這兩種I/O模型。這部分代碼在org.jboss.netty.channel包中。

4. Netty的特性總結

分  類

Netty的特性

設計

統一的API,支持多種傳輸類型,阻塞的和非阻塞的簡單而強大的線程模型真正的無連接數據報套接字支持鏈接邏輯組件以支持復用

易於使用

詳實的Javadoc和大量的示例集不需要超過JDK 1.6的依賴。(一些可選的特性可能需要Java 1.7+和/或額外的依賴)

性能

擁有比Java的核心API更高的吞吐量以及更低的延遲得益於池化和復用,擁有更低的資源消耗最少的內存復制

健壯性

不會因為慢速、快速或者超載的連接而導致OutOfMemoryError消除在高速網絡中NIO應用程序常見的不公平讀/寫比率

安全性

完整的SSL/TLS以及StartTLS支持可用於受限環境下,如Applet和OSGI

社區驅動

發布快速而且頻繁

5. Netty的核心組件

Netty的主要構件塊:

  • Channel
  • 回調;
  • Future
  • 事件和ChannelHandler

這些構建塊代表了不同類型的構造:資源、邏輯以及通知。你的應用程序將使用它們來訪問網絡以及流經網絡的數據。

對於每個組件來說,我們都將提供一個基本的定義,並且在適當的情況下,還會提供一個簡單的示例代碼來說明它的用法。

5.1 Channel

Channel是Java NIO的一個基本構造。它代表一個到實體(如一個硬件設備、一個文件、一個網絡套接字或者一個能夠執行一個或者多個不同的I/O操作的程序組件)的開放連接,如讀操作和寫操作,目前,可以把Channel看作是傳入(入站)或者傳出(出站)數據的載體。因此,它可以被打開或者被關閉,連接或者斷開連接。

5.2 回調

一個回調其實就是一個方法,一個指向已經被提供給另外一個方法的方法的引用。這使得後者可以在適當的時候調用前者。回調在廣泛的編程場景中都有應用,而且也是在操作完成後通知相關方最常見的方式之一。

Netty在內部使用了回調來處理事件;當一個回調被觸發時,相關的事件可以被一個interface-ChannelHandler的實現處理。

代碼清單1-2展示了一個例子:

1) 當一個新的連接已經被建立時,ChannelHandlerchannelActive()回調方法將會被調用,並將打印出一條信息。

2) 被回調觸發的ChannelHandler

public class ConnectHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelActive(ChannelHandlerContext ctx)
        throws Exception {    -- 當一個新的連接已經被建立時,channelActive(ChannelHandlerContext)將會被調用
        System.out.println(
            "Client " + ctx.channel().remoteAddress() + " connected");
    }
}

5.3 Future

1) Future提供了另一種在操作完成時通知應用程序的方式。這個對象可以看作是一個異步操作的結果的占位符;它將在未來的某個時刻完成,並提供對其結果的訪問。
2) JDK預置了interface java.util.concurrent.Future,但是其所提供的實現,只允許手動檢查對應的操作是否已經完成,或者一直阻塞直到它完成。這是非常繁瑣的,所以Netty提供了它自己的實現——ChannelFuture,用於在執行異步操作的時候使用。
3) ChannelFuture提供了幾種額外的方法,這些方法使得我們能夠註冊一個或者多個ChannelFutureListener實例。監聽器的回調方法operationComplete(),將會在對應的操作完成時被調用。然後監聽器可以判斷該操作是成功地完成了還是出錯了。如果是後者,我們可以檢索產生的Throwable。簡而言之,由ChannelFutureListener提供的通知機制消除了手動檢查對應的操作是否完成的必要。

4) 每個Netty的出站I/O操作都將返回一個ChannelFuture;也就是說,它們都不會阻塞。正如我們前面所提到過的一樣,Netty完全是異步和事件驅動的。

5.4 事件和ChannelHandler

Netty使用不同的事件來通知我們狀態的改變或者是操作的狀態。這使得我們能夠基於已經發生的事件來觸發適當的動作。這些動作可能是:

  • 記錄日誌;
  • 數據轉換;
  • 流控制;
  • 應用程序邏輯。

Netty是一個網絡編程框架,所以事件是按照它們與入站或出站數據流的相關性進行分類的。可能由入站數據或者相關的狀態更改而觸發的事件包括:

  • 連接已被激活或者連接失活;
  • 數據讀取;
  • 用戶事件;
  • 錯誤事件。

出站事件是未來將會觸發的某個動作的操作結果,這些動作包括:

  • 打開或者關閉到遠程節點的連接;
  • 將數據寫到或者沖刷到套接字。

每個事件都可以被分發給ChannelHandler類中的某個用戶實現的方法。這是一個很好的將事件驅動範式直接轉換為應用程序構件塊的例子。圖展示了一個事件是如何被一個這樣的ChannelHandler鏈處理的。

技術分享

Netty提供了大量預定義的可以開箱即用的ChannelHandler實現,包括用於各種協議(如HTTP和SSL/TLS)的ChannelHandler。在內部,ChannelHandler自己也使用了事件和Future,使得它們也成為了你的應用程序將使用的相同抽象的消費者。

第一章:Netty介紹