在Netty中,能夠同時支持單線程,多線程和主從Reactor三種模式:
下圖為Netty的線程模型:

以常用的Netty代碼舉例分析:
// 配置服務端的NIO線程組 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 100) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) { // ch.pipeline().addLast( // new ProtobufVarint32FrameDecoder()); ch.pipeline().addLast( new ProtobufDecoder( SubscribeReqProto.SubscribeReq .getDefaultInstance())); ch.pipeline().addLast( new ProtobufVarint32LengthFieldPrepender()); ch.pipeline().addLast(new ProtobufEncoder()); ch.pipeline().addLast(new SubReqServerHandler()); } }); // 綁定端口,同步等待成功 ChannelFuture f = b.bind(port).sync(); // 等待服務端監聽端口關閉 f.channel().closeFuture().sync(); } finally { // 優雅退出,釋放線程池資源 bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); }
以上服務端啟動,創建了兩個EventLoopGroup,實際上就是兩個Selector線程組。其中boss線程組負責接收客戶端連接,work線程組負責處理IO操作和系統Task和定時任務的調度。每個EventLoopGroup里面都維護了一個selector。
為了減少鎖競爭,Netty的work線程組處理IO操作時,都是單線程的,如圖下圖所示:

如圖,work線程組接收到讀事件時,將讀事件往pipeline從頭到尾傳遞,處理完數據后,將寫事件往pipeline從尾到頭傳遞,整個過程都是同一條線程,避免了多線程操作,也避免了鎖競爭帶來的性能消耗。
EventLoopGroup的簡析:
EventLoopGroup是一個不僅具備IO操作線程,還具體系統Task和定時任務的調度的功能的線程組。

EventLoopGroup內部維護了一個selector,因此會出現空輪詢的bug,netty通過周期性的對select()為0的情況進行計數,當出現次數達到一定值,
則認為出現空輪詢的bug,此時會重新打開一個新的selector,將舊的替換掉。
