Netty很強!Netty 威力很大!

一,Netty簡介

1,什麼是Netty?爲什麼要使用Netty?

netty是jboss提供的一個java開源框架,netty提供異步的、事件驅動的網絡應用程序框架和工具,用以快速開發高性能、高可用性的網絡服務器和客戶端程序。也就是說netty是一個基於nio的編程框架,使用netty可以快速的開發出一個網絡應用。由於java 自帶的nio api使用起來非常複雜,並且還可能出現 Epoll Bug,這使得我們使用原生的nio來進行網絡編程存在很大的難度且非常耗時。但是netty良好的設計可以使開發人員快速高效的進行網絡應用開發。

2,Netty的特點

2.1 設計優雅。適用於各種傳輸類型的統一API,阻塞和非阻塞Socket基於靈活且可擴展的事件模型,可以清晰地分離關注點。2.2 使用方便 詳細記錄的Javadoc,用戶指南和示例 沒有其他依賴項,只需要提供JDK即可。2.3 高性能。延遲更低,減少資源消耗,最小化不必要的內存複製。2.4 安全完整的SSL / TLS和StartTLS支持。2.5 社區活躍,不斷更新 社區活躍,版本迭代週期短,發現的BUG可以被及時修復,同時,更多的新功能會被加入。

3,常用的使用場景

分佈式開源框架中dubbo,Zookeeper,RocketMQ底層rpc通訊使用就是netty.

3.1 互聯網行業

  1. 互聯網行業:在分佈式系統中,各個節點之間需要遠程服務調用,高性能的 RPC 框架必不可少,Netty 作爲異步高性能的通信框架,往往作爲基礎通信組件被這些 RPC 框架使用.
  2. 典型的應用有:阿里分佈式服務框架 Dubbo 的 RPC 框架使用 Dubbo 協議進行節點間通信,Dubbo 協議默認使用 Netty 作爲基礎通信組件,用於實現各進程節點之間的內部通信.

3.2 遊戲行業

  1. 無論是手遊服務端還是大型的網絡遊戲,Java 語言得到了越來越廣泛的應用
  2. Netty 作爲高性能的基礎通信組件, 提供了 TCP/UDP 和 HTTP 協議棧,方便定製和開發私有協議棧, 賬號登錄服務器
  3. 地圖服務器之間可以方便的通過 Netty 進行高性能的通信

二,Netty的功能特性和架構思想

1. Netty的整體架構

下面我們通過一張圖片大致瞭解一下netty框架前面有說,netty是基於NIO的一個網絡編程框架,故而上圖NIO的模型圖可以最爲間接的說明netty的一個基本流程--當一個Socket建立好之後,Thread並不會阻塞去接受這個Socket,而是將這個請求交給Selector,Selector會不斷的去遍歷所有的Socket,一旦有一個Socket建立完成,他會通知Thread,然後Thread處理完數據再返回給客戶端——這個過程是不阻塞的,這樣就能讓一個Thread處理更多的請求了.

2.Netty線程模型

netty的線程模型在主從Reactor多線程模型基礎上做了一定的改進,這個會在以後的文章中單獨敘述,這裏爲了文章的完整性所以簡述一下.

三,Netty核心API簡介

1.Bootstrap、ServerBootstrap

  1. Bootstrap 意思是引導,一個 Netty 應用通常由一個 Bootstrap 開始,主要作用是配置整個 Netty 程序,串聯各個組件,Netty 中 Bootstrap 類是客戶端程序的啓動引導類,ServerBootstrap 是服務端啓動引導類
  2. 常見的方法有
  • public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup),該方法用於服務器端,用來設置兩個 EventLoop;
  • public B group(EventLoopGroup group) ,該方法用於客戶端,用來設置一個 EventLoop public B channel(Class<? extends C> channelClass),該方法用來設置一個服務器端的通道實現;
  • public B option(ChannelOption option, T value),用來給 ServerChannel 添加配置;
  • public ServerBootstrap childOption(ChannelOption childOption, T value),用來給接收到的通道添加配置;
  • public ServerBootstrap childHandler(ChannelHandler childHandler),該方法用來設置業務處理類(自定義的 handler);
  • public ChannelFuture bind(int inetPort) ,該方法用於服務器端,用來設置佔用的端口號;
  • public ChannelFuture connect(String inetHost, int inetPort) ,該方法用於客戶端,用來連接服務器。

2.Future、ChannelFuture

  1. Netty 中所有的 IO 操作都是異步的,不能立刻得知消息是否被正確處理。但是可以過一會等它執行完成或者直接註冊一個監聽,具體的實現就是通過 Future 和 ChannelFutures,他們可以註冊一個監聽,當操作執行成功或失敗時監聽會自動觸發註冊的監聽事件.
  2. 常見的方法有:
  • Channel channel(),返回當前正在進行 IO 操作的通道
  • ChannelFuture sync(),等待異步操作執行完畢

3.Channel

  1. Netty 網絡通信的組件,能夠用於執行網絡 I/O 操作;
  2. 通過Channel 可獲得當前網絡連接的通道的狀態;
  3. 通過Channel 可獲得 網絡連接的配置參數 (例如接收緩衝區大小);
  4. Channel 提供異步的網絡 I/O 操作(如建立連接,讀寫,綁定端口),異步調用意味着任何 I/O 調用都將立即返回,並且不保證在調 用結束時所請求的 I/O 操作已完成;
  5. 調用立即返回一個 ChannelFuture 實例,通過註冊監聽器到 ChannelFuture 上,可以 I/O 操作成功、失敗或取消時回調通知調用方;
  6. 支持關聯 I/O 操作與對應的處理程序 不同協議、不同的阻塞類型的連接都有不同的 Channel 類型與之對應;
  7. 常用的 Channel 類型:
  • NioSocketChannel,異步的客戶端 TCP Socket 連接;
  • NioServerSocketChannel,異步的服務器端 TCP Socket 連接;
  • NioDatagramChannel,異步的 UDP 連接;
  • NioSctpChannel,異步的客戶端 Sctp 連接;
  • NioSctpServerChannel,異步的 Sctp 服務器端連接,這些通道涵蓋了 UDP 和 TCP 網絡 IO 以及文件 IO。

4.Selector

  1. Netty 基於 Selector 對象實現 I/O 多路複用,通過 Selector 一個線程可以監聽多個連接的 Channel 事件;
  2. 當向一個 Selector 中註冊 Channel 後,Selector 內部的機制就可以自動不斷地查詢(Select) 這些註冊的 Channel 是否有已就緒的 I/O 事件(例如可讀,可寫,網絡連接完成等),這樣程序就可以很簡單地使用一個線程高效地管理多個 Channel。

5.ChannelHandler 及其實現類

  1. ChannelHandler 是一個接口,處理 I/O 事件或攔截 I/O 操作,並將其轉發到其 ChannelPipeline(業務處理鏈)中的下一個處理程序。
  2. ChannelHandler 本身並沒有提供很多方法,因爲這個接口有許多的方法需要實現,方便使用期間,可以繼承它的子類.
  3. ChannelHandler 及其實現結構圖如下 1)ChannelInboundHandler 用於處理入站 I/O 事件。2)ChannelOutboundHandler 用於處理出站 I/O 操作。3)ChannelInboundHandlerAdapter 適配器用於處理入站 I/O 事件。4)ChannelOutboundHandlerAdapter 適配器用於處理出站 I/O 操作。5)ChannelDuplexHandler 適配器處理入站和出站事件。
  4. Handler使用,我們經常需要自定義一個 Handler 類去繼承 ChannelInboundHandlerAdapter,然後通過重寫相應方法實現業務邏輯,下面列出一些常用的需要重寫的方法.
public class ChannelInboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelInboundHandler {
public ChannelInboundHandlerAdapter() {

    }
    
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelRegistered();
    }

    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelUnregistered();
    }
 
    //通道就緒事件
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelActive();
    }
    
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelInactive();
    }
    
    //通道讀取數據事件
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ctx.fireChannelRead(msg);
    }
    //數據讀取完畢事件
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelReadComplete();
    }

    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        ctx.fireUserEventTriggered(evt);
    }

    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelWritabilityChanged();
    }
    //通道發生異常事件
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.fireExceptionCaught(cause);
    }
}

6.Pipeline 和 ChannelPipeline

  1. ChannelPipeline 是一個 Handler 的集合,它負責處理和攔截 inbound 或者 outbound 的事件和操作,相當於一個貫穿 Netty 的鏈。(也可以這樣理解:ChannelPipeline 是 保存 ChannelHandler 的 List,用於處理或攔截 Channel 的入站事件和出站操作)
  2. ChannelPipeline 實現了一種高級形式的攔截過濾器模式,使用戶可以完全控制事件的處理方式,以及 Channel 中各個的 ChannelHandler 如何相互交互.

7.ChannelHandlerContex

  1. 保存 Channel 相關的所有上下文信息,同時關聯一個 ChannelHandler 對象;
  2. ChannelHandlerContext 中 包 含 一 個 具 體 的 事 件 處 理 器 ChannelHandler , 同 時ChannelHandlerContext 中也綁定了對應的 pipeline 和 Channel 的信息,方便對 ChannelHandler進行調用.
  3. 常用方法 : 1)ChannelFuture close(),關閉通道 2)ChannelOutboundInvoker flush(),刷新 3)ChannelFuture writeAndFlush(Object msg) , 將 數 據 寫 到 ChannelPipeline 中 當 前 4)ChannelHandler 的下一個 ChannelHandler 開始處理(出棧).

8.ChannelOption

  1. Netty 在創建 Channel 實例後,一般都需要設置 ChannelOption 參數。
  2. ChannelOption 參數如下:
  • 「ChannelOption.SO_BACKLOG」--對應 TCP/IP 協議 listen 函數中的 backlog 參數,用來初始化服務器可連接隊列大小。服  務端處理客戶端連接請求是順序處理的,所以同一時間只能處理一個客戶端連接。多個客戶端來的時候,服務端將不能處理的客戶端連接請求放在隊列中等待處理,backlog 參數指定了隊列的大小;
  • 「ChannelOption.SO_KEEPALIVE」--一直保持連接活動狀態.

9.EventLoopGroup 和其實現類 NioEventLoopGroup

  1. EventLoopGroup 是一組 EventLoop 的抽象,Netty 爲了更好的利用多核 CPU 資源,一般會有多個 EventLoop 同時工作,每個 EventLoop 維護着一個 Selector 實例;
  2. EventLoopGroup 提供 next 接口,可以從組裏面按照一定規則獲取其中一個 EventLoop來處理任務。在 Netty 服務器端編程中,我們一般都需要提供兩個 EventLoopGroup,例如:BossEventLoopGroup 和 WorkerEventLoopGroup;
  3. 通常一個服務端口即一個 ServerSocketChannel對應一個Selector 和一個EventLoop線程。BossEventLoop 負責接收客戶端的連接並將 SocketChannel 交給 WorkerEventLoopGroup 來進行 IO 處理.

10.Unpooled 類

  1. Netty 提供一個專門用來操作緩衝區(即Netty的數據容器)的工具類
  2. 常用方法:
//通過給定的數據和字符編碼返回一個 ByteBuf 對象(類似於 NIO 中的 ByteBuffer 但有區別)
public static CompositeByteBuf compositeBuffer(int maxNumComponents) {
return new CompositeByteBuf(ALLOC, false, maxNumComponents);
}

好啦,以上內容就是Netty的一個基本介紹了,希望大家互相學習共同進步.






0、最後一天了,四個關鍵字回顧程序員小躍的2020

1、程序員小躍:三十而立,和大家一起「乘風破浪」

本文分享自微信公衆號 - 程序員小躍(runningdimple)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章