前言
在之前的文章Netty 入門初體驗簡單介紹了 Netty 服務端和客戶端的例子,下面依舊以Netty 服務端 demo 為例,來簡單闡述下 Netty 的基本元件。
基本元件概覽
以Netty服務端的一個例子來闡述其中用到的基本元件,程式碼如下:
public class EchoServer {
private final int port;
public EchoServer(int port) {
this.port = port;
}
public static void main(String[] args) throws InterruptedException {
new EchoServer(8888).start();
}
public void start() throws InterruptedException {
final EchoServerHandler serverHandler = new EchoServerHandler();
//建立EventLoopGroup,處理事件
EventLoopGroup group = new NioEventLoopGroup();
EventLoopGroup worker = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(group,worker)
//指定所使用的NIO傳輸 Channel
.channel(NioServerSocketChannel.class)
//使用指定的埠設定套接字地址
.localAddress(new InetSocketAddress(port))
//新增一個EchoServerHandler到子Channel的ChannelPipeline
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
//EchoServerHandler別標誌為@Shareable,所以我們可以總是使用同樣的例項
socketChannel.pipeline().addLast(serverHandler);
}
});
//非同步的繫結伺服器,呼叫sync()方法阻塞等待直到繫結完成
ChannelFuture future = b.bind().sync();
future.channel().closeFuture().sync();
} finally {
//關閉EventLoopGroup,釋放所有的資源
group.shutdownGracefully().sync();
worker.shutdownGracefully().sync();
}
}
}
複製程式碼
服務端建立流程:
- 建立 ServerBootStrap例項
- 設定並繫結
NioEventLoopGroup
執行緒池 - 通過
ServerBootStrap
的channel
方法設定並繫結服務端 Channel - 建立並初始化
ChannelPipeline
- 新增並設定
ChannelHandler
- 繫結並啟動監聽埠
上面簡述了服務端的建立流程,其中包含了 Netty的基本元件的使用,下面這張導圖也簡單的敘述了Netty各大元件的概念與作用
Channel
Channel是 Netty中的網路操作抽象類,對應JDK底層的Socket,它除了包含基本的I/O操作,如 bind(),connect(),read(),write()之外,還包括了Netty框架相關的一些功能,如獲取 Channel的EventLoop。
EventLoop
EventLoop定義了Netty的核心抽象,用於處理連線的生命週期中所發生的事件。EventLoop 為Channel處理I/O操作,下圖是 Channel,EventLoop,Thread以及EventLoopGroup之間的關係(摘自《Netty In Action》):
這些關係是:
- 一個EventLoopGroup 包含一個或者多個EventLoop
- 一個 EventLoop 在它的生命週期內只和一個Thread繫結
- 所有由 EventLoop處理的 I/O事件都將在它專有的Thread上被處理
- 一個 Channel 在它的生命週期內只註冊一個EventLoop
- 一個 EventLoop 可能會被分配給一個或多個 Channel
EventLoopGroup實際上就是處理I/O操作的執行緒池,負責為每個新註冊的Channel分配一個EventLoop,Channel在整個生命週期都有其繫結的 EventLoop來服務。
而上面服務端用的 NioEventLoop 就是 EventLoop的一個重要實現類,NioEventLoop 是Netty內部的I/O執行緒,而 NioEventLoopGroup是擁有 NioEventLoop的執行緒池,在Netty服務端中一般存在兩個這樣的NioEventLoopGroup執行緒池,一個 "Boss" 執行緒池,用於接收客戶端連線,實際上該執行緒池中只有一個執行緒,一個 "Worker"執行緒池用於處理每個連線的讀寫。而Netty客戶端只需一個執行緒池即可,主要用於處理連線中的讀寫操作。
ChannelHandler
ChannelHandler是Netty的主要元件,它主要用於對出站和入站資料進行處理,它有兩個重要的子介面:
- ChannelInboundHandler——處理入站資料以及各種狀態變化
- ChannelOutboundHandler——處理出站資料並且允許攔截所有的操作
ChannelPipeline
ChannelPipeline提供了 ChannelHandler鏈的容器,換句話說,就是一個邏輯處理鏈,用於攔截流經Channel的入站和出站事件的ChannelHandler。還是就是當 Channel被建立時,它會被自動地分配到它的專屬的 ChannelPipeline。
當一個訊息或者任何其他的入站事件被讀取時,那麼它會從 ChannelPipeline的頭部開始流動,並被傳遞給第一個 ChannelInboundHandler,第一個處理完成之後傳遞給下一個 ChannelInboundHandler,一直到ChannelPipeline的尾端,與之對應的是,當資料被寫出時,資料從 ChannelOutboundHandler 鏈的尾端開始流動,直到它到達鏈的頭部為止。
ChannelFuture
Netty中所有I/O操作都是非同步的,使用ChannelFuture可以獲取操作完成的結果,其 addListener()
方法註冊了一個 ChannelFutureListener,以便在某個操作完成時(無論是否成功)得到通知。
ByteBuf
ByteBuf是Netty中的位元組緩衝區,相比於Java NIO中的 ByeBuffer,ByteBuf做了很多改進,ByteBuf的功能性和靈活性更好。
BootStrap
Netty提供的啟動輔助類,幫助Netty客戶端或服務端的Netty初始化,服務端對應的是 ServerBootStrap引導類。
小結
上面簡單的介紹了Netty的一些基本元件,後續文章會詳細對每個元件進行分析