參考文獻:極客時間傅健老師的《Netty源碼剖析與實戰》Talk is cheap.show me the code!
什么是Reactor及三種版本
反應堆設計模式(Reactor pattern):是一種為處理並發服務請求,並將請求提交到一個或者多個服務處理程序的事件設計模式。當客戶端請求抵達后,服務處理程序使用多路分配策略,由一個非阻塞的線程來接收所有的請求,然后派發這些請求至相關的工作線程進行處理。
三種版本:Reactor單線程(一個人包攬),Reactor多線程模式(多人分擔),主從Reactor多線程模式(多人細工分擔)。
Reactor是一種開發模式,模式的核心流程為:注冊感興趣的事件---->掃描是都有感興趣的事件發生---->事件發生后做出相應的處理。
對於每一種的SocketChannel它監聽的事件也不同,如下圖!
如何在Netty中使用Reactor模式
上圖中非主從Reactor多線程模式中"EventLoopGroup eventGroup = new NioEventLoopGroup()"中沒有給參數,參考Reactor單線程模式給的參數是1,這里沒有參數為什么是多線程模式?那是因為如果我們不去設置的話,它會根據CPU核數去計算出一個最優的線程數,現在單核CPU幾乎沒有了,所以現在幾乎可以百分百的肯定這樣就是多線程模式。
源碼解釋
public class MyServer { public static void main(String[] args) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap sb = new ServerBootstrap(); sb.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)).childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast(new LoggingHandler(LogLevel.INFO)); p.addLast(new MyServerHandler()); } }); ChannelFuture f = sb.bind(8090).sync(); f.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }
代碼中標粗標大的就是主從Reactor模式的核心點,其中bossGroup(可以理解為主)和workerGroup(可以理解為從)都是需要被設置到ServerBootstrap中去,“sb.group(bossGroup,workerGroup)”則是綁定,進入group()方法:
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) { super.group(parentGroup); ObjectUtil.checkNotNull(childGroup, "childGroup"); if (this.childGroup != null) { throw new IllegalStateException("childGroup set already"); } this.childGroup = childGroup; return this; }
進入super.group(parentGroup);
可以看到"this.group = group”;group則是傳入的“bossGroup”;this.group則是該類定義的成員。
volatile EventLoopGroup group;
而該成員在group()被return.
接下來需要查看哪里調用了該方法(windows下的idea按ctrl+alt+h可以查詢),如圖:
圖上標記的“ChannelFuture regFuture = config().group().register(channel);”不難看出我們取到了group,再將channel綁定進去,這里的channel指的是:在服務器的開發那就是ServerSocketChannel。所以可以簡單的理解:我們將ServerSocketChannel綁定到bossGroup上,有了ServerSocketChannel就能創建子的SocketChannel,再將子的SocketChannel綁定到之前的workerGroup上。
源碼驗證
還是之前的那張圖,進入sb.group()中:
這里的“this.childGroup = childGroup;”的this.childGroup 也是定義的成員
private volatile EventLoopGroup childGroup;
查看this.childGroup誰在用,搜索發現:
final EventLoopGroup currentChildGroup = childGroup;
msg即SocketChannel,下面標紅框的就是將msg進行綁定到workerGroup中,簡單說就是兩種SocketChannel綁定到兩個Group里面去。這樣就完成了主從Reactor模式的支持。
我只想做的更好,僅此而已