Netty如何支持三种Reactor
参考文献:极客时间傅健老师的《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模式的支持。
我只想做的更好,仅此而已