一、前言
Netty是一種可以輕松快速的開發協定伺服器和用戶端網絡應用程式的NIO架構,它大大簡化了TCP或者UDP伺服器的網絡程式設計,但是你仍然可以通路和使用底層的API,Netty隻是對其進行了高層的抽象。
Netty的簡易和快速開發并不意味着由它開發的程式将失去可維護性或者存在性能問題。Netty是被精心設計的,它的設計參考了許多協定的實作,比如FTP,SMTP,HTTP和各種二進制和基于文本的傳統協定,是以 Netty成功的實作了兼顧快速開發,性能,穩定性,靈活性為一體,不需要為了考慮一方面原因而妥協其他方面。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiADNyEzLcd3LcJzLcJzdllmVldWYtl2Q3UCcpJHdz9CX05WZpJ3bt8Gd1F2LcJjcn9WTldWYtl2P1EDO1EGN4gDMhRzNjRDO20CN5ITO3gTNvw1cldWYtl2XkF2bsBXdvw1bp5SdoNnbhlmauMXZnFWbp1CZh9GbwV3Lc9CX6MHc0RHaiojIsJye.jpg)
二、基礎概念
Channel也就是通道,這個概念是在JDK NIO類庫裡面提供的一個概念,JDK中其實作類有用戶端套接字通道java.nio.channels.SocketChannel和服務端監聽套接字通道java.nio.channels.ServerSocketChannel,Channel的出現是為了支援異步IO操作,JDK裡面的通道是java.nio.channels.Channel。
io.netty.channel.Channel是Netty架構自己定義的一個通道接口,Netty實作的用戶端NIO套接字通道是NioSocketChannel,提供的伺服器端NIO套接字通道是NioServerSocketChannel。
-
NioSocketChannel
用戶端套接字通道,内部管理了一個Java NIO中的java.nio.channels.SocketChannel執行個體,用來建立SocketChannel執行個體和設定該執行個體的屬性,并調用Connect方法向服務端發起TCP連結等。
-
NioServerSocketChannel
伺服器端監聽套接字通道,内部管理了一個Java NIO中的java.nio.channels.ServerSocketChannel執行個體,用來建立ServerSocketChannel執行個體和設定該執行個體屬性,并調用該執行個體的bind方法在指定端口監聽用戶端的連結。
-
Channel與socket的關系
在Netty中Channel有兩種,對應用戶端套接字通道NioSocketChannel,内部管理java.nio.channels.SocketChannel套接字,對應伺服器端監聽套接字通道NioServerSocketChannel,其内部管理自己的java.nio.channels.ServerSocketChannel套接字。也就是Channel是對socket的裝飾或者門面,其封裝了對socket的原子操作。
-
EventLoopGroup
Netty之是以能提供高性能網絡通訊,其中一個原因是因為它使用Reactor線程模型。在netty中每個EventLoopGroup本身是一個線程池,其中包含了自定義個數的NioEventLoop,每個NioEventLoop是一個線程,并且每個NioEventLoop裡面持有自己的selector選擇器。
在Netty中用戶端持有一個EventLoopGroup用來處理網絡IO操作,在伺服器端持有兩個EventLoopGroup,其中boss組是專門用來接收用戶端發來的TCP連結請求的,worker組是專門用來具體處理完成三次握手的連結套接字的網絡IO請求的。
-
Channel 與 EventLoop 的關系
Netty中NioEventLoop是EventLoop的一個實作,每個NioEventLoop中會管理自己的一個selector選擇器和監控選擇器就緒事件的線程;每個Channel隻會關聯一個NioEventLoop;
當Channel是用戶端通道NioSocketChannel時候,會注冊NioSocketChannel管理的SocketChannel執行個體到自己關聯的NioEventLoop的selector選擇器上,然後NioEventLoop對應的線程會通過select指令監控感興趣的網絡讀寫事件;
當Channel是服務端通道NioServerSocketChannel時候,NioServerSocketChannel本身會被注冊到boss EventLoopGroup裡面的某一個NioEventLoop管理的selector選擇器上,而完成三次握手的連結套接字是被注冊到了worker EventLoopGroup裡面的某一個NioEventLoop管理的selector選擇器上;
需要注意是多個Channel可以注冊到同一個NioEventLoop管理的selector選擇器上,這時候NioEventLoop對應的單個線程就可以處理多個Channel的就緒事件;但是每個Channel隻能注冊到一個固定的NioEventLoop管理的selector選擇器上。
-
ChannelPipeline
Netty中的ChannelPipeline類似于Tomcat容器中的Filter鍊,屬于設計模式中的責任鍊模式,其中鍊上的每個節點就是一個ChannelHandler。在netty中每個Channel有屬于自己的ChannelPipeline,對從Channel中讀取或者要寫入Channel中的資料進行依次處理,如下圖是netty源碼裡面的一個圖:
需要注意一點是雖然每個Channel(更底層說是每個socket)有自己的ChannelPipeline,但是每個ChannelPipeline裡面可以複用一個ChannelHandler。
三、總結
Netty作為高性能異步通訊架構,其應用還是比較廣泛的,比如阿裡巴巴開源的高性能Rpc架構Dubbo的網絡通訊預設實作使用的是Netty, 螞蟻金服開源的金融級Sofa-Bolt 架構,底層網絡通訊也是基于 Netty 來實作的,還有最近剛開源的Zuul2.0使用Netty重寫了其接受與處理請求的邏輯。