Netty服务端创建时序图
- 创建ServerBootstrap实例
ServerBootstrap是一个用于启动Netty服务端的辅助类,提供一系列方法设置启动参数。因为ServerBootstrap需要设置的各项信息很多,所以这里采用builder模式实现。
- 设置并绑定Reactor线程池
通过构造函数创建ServerBootstrap实例之后,通常会创建两个EventLoopGroup(并不是必须要创建两个不同的EventLoopGroup,也可以只创建一个并共享),代码如下所示:
BossEventLooPGroup和WorkerEventLoopGroup。BossEventLoopGroup通常是一个单线程的EventLoop,EventLoop维护着一个注册了ServerSocketChannel的Selector实例,BoosEventLoop不断轮询Selector将连接事件分离出来,通常是OP_ACCEPT事件,然后将accept得到的SocketChannel交给WorkerEventLoopGroup。WorkerEventLoopGroup会选择其中一个EventLoopGroup来将这个SocketChannel注册到其维护的Selector并对其后续的IO事件进行处理。在Reactor模式中BossEventLoopGroup主要是对多线程的扩展,而每个EventLoop的实现涵盖IO事件的分离和分发。EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup();
NioEventLoopGroup实际就是Reactor线程池,负责调度和执行客户端的接入、网络读写事件的处理、用户自定义任务和定时任务的执行。通过ServerBootstrap的group方法将两个EventLoopGroup实例传入,代码如下:public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) { super.group(parentGroup); if (childGroup == null) { throw new NullPointerException("childGroup"); } if (this.childGroup != null) { throw new IllegalStateException("childGroup set already"); } this.childGroup = childGroup; return this; }
Netty为了更好的利用多核CPU的资源对Reactor模式进行了改进,每个Netty服务端程序中有多个EventLoop同时运行,每一个EventLoop维护一个Selector实例,进行Reactor模式的工作。此外,EventLoop的职责除了处理IO事件,还包括处理定时任务和用户自定义任务。Netty还提供了一个ioRatio参数,供使用者调整EventLoop运行不同任务时间的比例。这样的设计避免了多线程并发操作和锁竞争,提升了I/O线程的处理和调度性能。
Netty基于单线程设计的EventLoop能够同时处理成千上万的客户端连接的IO事件,缺点是单线程不能够处理时间过长的任务,这样会阻塞使得IO事件的处理被阻塞,严重的时候回造成IO事件堆积,服务不能够高效响应客户端请求。,当我们遇到需要处理时间很长的任务的时候,我们可以将它交给子线程来处理,主线程继续去EventLoop,当子线程计算完毕再讲结果交给主线程。 - 设置并绑定服务端Channel
线程组和线