在以前的文章Netty 入門初體驗簡單介紹了 Netty 服務端和客戶端的例子,下面依舊以Netty 服務端 demo 爲例,來簡單闡述下 Netty 的基本組件。java
以Netty服務端的一個例子來闡述其中用到的基本組件,代碼以下:git
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();
}
}
}
複製代碼
服務端建立流程:github
NioEventLoopGroup
線程池ServerBootStrap
的channel
方法設置並綁定服務端 ChannelChannelPipeline
ChannelHandler
上面簡述了服務端的建立流程,其中包含了 Netty的基本組件的使用,下面這張導圖也簡單的敘述了Netty各大組件的概念與做用服務器
Channel是 Netty中的網絡操做抽象類,對應JDK底層的Socket,它除了包含基本的I/O操做,如 bind(),connect(),read(),write()以外,還包括了Netty框架相關的一些功能,如獲取 Channel的EventLoop。網絡
EventLoop定義了Netty的核心抽象,用於處理鏈接的生命週期中所發生的事件。EventLoop 爲Channel處理I/O操做,下圖是 Channel,EventLoop,Thread以及EventLoopGroup之間的關係(摘自《Netty In Action》):框架
這些關係是:異步
EventLoopGroup實際上就是處理I/O操做的線程池,負責爲每一個新註冊的Channel分配一個EventLoop,Channel在整個生命週期都有其綁定的 EventLoop來服務。socket
而上面服務端用的 NioEventLoop 就是 EventLoop的一個重要實現類,NioEventLoop 是Netty內部的I/O線程,而 NioEventLoopGroup是擁有 NioEventLoop的線程池,在Netty服務端中通常存在兩個這樣的NioEventLoopGroup線程池,一個 "Boss" 線程池,用於接收客戶端鏈接,實際上該線程池中只有一個線程,一個 "Worker"線程池用於處理每一個鏈接的讀寫。而Netty客戶端只需一個線程池便可,主要用於處理鏈接中的讀寫操做。ide
ChannelHandler是Netty的主要組件,它主要用於對出站和入站數據進行處理,它有兩個重要的子接口:oop
ChannelPipeline提供了 ChannelHandler鏈的容器,換句話說,就是一個邏輯處理鏈,用於攔截流經Channel的入站和出站事件的ChannelHandler。仍是就是當 Channel被建立時,它會被自動地分配到它的專屬的 ChannelPipeline。
當一個消息或者任何其餘的入站事件被讀取時,那麼它會從 ChannelPipeline的頭部開始流動,並被傳遞給第一個 ChannelInboundHandler,第一個處理完成以後傳遞給下一個 ChannelInboundHandler,一直到ChannelPipeline的尾端,與之對應的是,當數據被寫出時,數據從 ChannelOutboundHandler 鏈的尾端開始流動,直到它到達鏈的頭部爲止。
Netty中全部I/O操做都是異步的,使用ChannelFuture能夠獲取操做完成的結果,其 addListener()
方法註冊了一個 ChannelFutureListener,以便在某個操做完成時(不管是否成功)獲得通知。
ByteBuf是Netty中的字節緩衝區,相比於Java NIO中的 ByeBuffer,ByteBuf作了不少改進,ByteBuf的功能性和靈活性更好。
Netty提供的啓動輔助類,幫助Netty客戶端或服務端的Netty初始化,服務端對應的是 ServerBootStrap引導類。
上面簡單的介紹了Netty的一些基本組件,後續文章會詳細對每一個組件進行分析