1. 程式人生 > >關於Netty的一些學習心得

關於Netty的一些學習心得

最近開始學習一個新的框架,為了防止自己學過之後就忘的壞習慣,所以寫一些心得在這裡。

1.首先Netty是個什麼東西呢?

假設你正在為一個重要的大型公司開發一款全新的任務關鍵型的應用程式。在第一次會議
上,你得知該系統必須要能夠擴充套件到支撐 150 000 名併發使用者,並且不能有任何的效能損失,這
時所有的目光都投向了你。你會怎麼說呢?
如果你可以自信地說:“當然,沒問題。”那麼大家都會向你脫帽致敬。但是,我們大多數人
可能會採取一個更加謹慎的立場,例如:“聽上去是可行的。”然後,一回到計算機旁,我們便開
始搜尋“high performance Java networking”(高效能 Java 網路程式設計)。

如果你現在搜尋它,在第一頁結果中,你將會看到下面的內容:

Netty: Home
netty.io/
Netty 是一款非同步的事件驅動的網路應用程式框架,支援快速地開發可維護的高效能的面向協議的伺服器

和客戶端。

最早期的java只是支援一些阻塞I/O,效能極差,每個執行緒只能處理一個客戶端,如果訪問客戶稍多一點就會不停地建立執行緒,而我們都知道jvm的記憶體資源是極其寶貴得,如果一直建立執行緒就會導致jvm宕機或者記憶體溢位,所以早期一些大公司的處理方式都是通過c語言去處理這一塊的邏輯。

後來出現了NIO,可以看做是NO I/O,也可以看做是NEW I/O。非阻塞式設計是可以一個執行緒對多個連線,執行緒池的建立可以把執行緒所佔用的資源控制在自己手裡,這樣就可以避免記憶體溢位的異常。java中的選擇器就是一個非阻塞式設計實現的關鍵,它可以使用較少的執行緒去處理較多的連線,沒有I/O操作的時候也可以去處理其他業務。

儘管有一些公司直接去使用java NIO Api去構建一些工程,但是要正確和安全的使用這些Api卻並不容易,所以最好還是把這些工作直接交給網路程式設計專家——Netty來實現。

2.Netty的一些特性

設計:

        統一的API,支援多種傳輸型別,阻塞式和非阻塞式。

        簡單而強大的執行緒模型。

        連結邏輯支援複用。

易於使用:

        詳細的javadoc和大量的例子

        不需要超過java1.6+支援(一些特性需要java1.7+支援)

效能:

        擁有比java核心API更高的吞吐量和更低的延遲

        因為池化,消耗更低的資源

        最少的記憶體複製

健壯性:

        不會因為快速、慢速或者超載而引發記憶體溢位異常

        消除在高速網路I/O中出現不公平讀寫的比率

社群:

        版本更新快速而且頻繁

3.Netty核心元件

Channel、Future、回撥、ChannelHandler、事件。

Channel代表了Netty的每一個基本構件,代表了Netty對每一個硬體的操作,開啟關閉連線,讀寫操作。

Future提供了對應用程式的非同步通知,可以把它看做是一個結果的佔位符。它在未來的某個時刻完成。

回撥是提供給另外方法對本方法的一個引用,後者可以適當的時候呼叫前者。

ChannelHandler是對進站的資料的邏輯處理,用來寫我們的核心邏輯。

事件是Netty用來通知我們狀態的改變或者是操作的狀態得,通過事件的不同我們可以執行一些自己的操作,例如寫一些日誌啊,資料轉換啊之類的事。

在這裡我多說兩個Netty的元件,它們是ChannelPipeline和EventLoop。ChannelPipeline可以看做是多個ChannelHandler的有序排列,資料是按照ChannelPipeline中ChannelHandler的順序依次進行邏輯處理,進站和出站的ChannelHandler可以放在一個ChannelPipeline中,Netty會自動判斷它是進站和出站的CahnnelHandler。EventLoop是Netty分給每個Channel的一個事件迴圈,用來註冊事件,將事件分派給ChannelHandler,安排進一步的動作。

4.Channel、EventLoop、ChannelFuture、ChannelHandler、ChannelPipeline、編碼器、解碼器、載入程式

 Channel—Socket, Netty的Cahnnel介面提供的API大大降低了使用Socket類的複雜性。

 EventLoop—控制流、多執行緒處理、併發;

     一個 EventLoopGroup 包含一個或者多個 EventLoop
     一個 EventLoop 在它的生命週期內只和一個 Thread 繫結;
     所有由 EventLoop 處理的 I/O 事件都將在它專有的 Thread 上被處理;
     一個 Channel 在它的生命週期內只註冊於一個 EventLoop;
     一個 EventLoop 可能會被分配給一個或多個 Channel。
注意,在這種設計中,一個給定 Channel 的 I/O 操作都是由相同的 Thread 執行的,實際
上消除了對於同步的需要。

 ChannelFuture—非同步通知。

        Netty 中所有的 I/O 操作都是非同步的。因為一個操作可能不會立即返回,所以我們需要一種用於在之後的某個時間點確定其結果的方法。為此,Netty 提供了ChannelFuture 介面,其 addListener()方法註冊了一個 ChannelFutureListener,以便在某個操作完成時(無論是否成功)得到通知。

 ChannelHandler——Netty主要元件

        它充當了所有處理入站和出站資料的應用程式邏輯的容器。因為 ChannelHandler 的方法是由網路事件(其中術語“事件”的使用非常廣泛)觸發的。事實上,ChannelHandler 可專門用於幾乎任何型別的動作,例如將資料從一種格式轉換為另外一種格式,或者處理轉換過程中所丟擲的異常。

 ChannelPipeline——ChannelHandler 鏈的容器

        ChannelPipeline定義了用於在該鏈上傳播入站和出站事件流的 API,當 Channel 被建立時,它會被自動地分配到它專屬的 ChannelPipeline。

        ChannelHandler 安裝到 ChannelPipeline 中的過程如下所示:

 一個ChannelInitializer的實現被註冊到了ServerBootstrap中 ;
       當 ChannelInitializer.initChannel()方法被呼叫時,ChannelInitializer將在 ChannelPipeline 中安裝一組自定義的 ChannelHandler;

       ChannelInitializer 將它自己從 ChannelPipeline 中移除。

如果一個訊息或者任何其他的入站事件被讀取,那麼它會從 ChannelPipeline 的頭部開始流動,並被傳遞給第一個 ChannelInboundHandler。這個 ChannelHandler 不一定會實際地修改資料,具體取決於它的具體功能,在這之後,資料將會被傳遞給鏈中的下一個ChannelInboundHandler。最終,資料將會到達 ChannelPipeline 的尾端,屆時,所有處理就都結束了。

當ChannelHandler 被新增到ChannelPipeline 時,它將會被分配一個ChannelHandlerContext,其代表了 ChannelHandler 和 ChannelPipeline 之間的繫結。雖然這個物件可以被用於獲取底層的 Channel,但是它主要還是被用於寫出站資料。

在 Netty 中,有兩種傳送訊息的方式。你可以直接寫到 Channel 中,也可以 寫到和 ChannelHandler相關聯的ChannelHandlerContext物件中。前一種方式將會導致訊息從ChannelPipeline 的尾端開始流動,而後者將導致訊息從 ChannelPipeline 中的下一個 ChannelHandler 開始流動。

為什麼需要介面卡類?
有一些介面卡類可以將編寫自定義的 ChannelHandler 所需要的努力降到最低限度,因為它們提
供了定義在對應介面中的所有方法的預設實現。
下面這些是編寫自定義 ChannelHandler 時經常會用到的介面卡類:
 ChannelHandlerAdapter
 ChannelInboundHandlerAdapter
 ChannelOutboundHandlerAdapter

 ChannelDuplexHandler

編碼器和解碼器

Netty傳送一次訊息就會發生一次資料轉碼,你將會發現對於入站資料來說,channelRead 方法/事件已經被重寫了。對於每個從入站Channel 讀取的訊息,這個方法都將會被呼叫。隨後,它將呼叫由預置解碼器所提供的 decode()方法,並將已解碼的位元組轉發給 ChannelPipeline 中的下一個 ChannelInboundHandler。

載入程式(Bootstrap和ServerBootstrap)

載入程式對於客戶端和服務端是不同的,對於客戶端來說是Bootstrap,對於服務端來說是ServerBootstrap。

這兩種的區別是:

BootStrap和ServerBootStrap的比較
類別BootStrapServerBootStrap
網路程式設計中的作用連結到遠端主機和埠繫結到一個本地埠
EventLoopGroup中的數量12

ServerBootstrap 將繫結到一個埠,因為伺服器必須要監聽連線,而 Bootstrap 則是由想要連線到遠端節點的客戶端應用程式所使用的