Netty采用主从Reactor多线程模型,主 Reactor 单独监听server socket,accept新连接,然后将建立的 SocketChannel 注册给指定的 从Reactor,从Reactor 将连接加入到连接队列进行监听,并创建handler进行事件处理。执行事件的读写、分发,把业务处理就扔给worker线程池完成。master EventLoopGroup中有一个EventLoop,绑定某个特定端口进行监听,在slave EventLoopGroup中,是有多个EventLoop组成的 “多selector + 多个单线程“ 模型,

NioEventLoop 中维护了一个线程和任务队列,支持异步提交执行任务,线程启动时会调用 NioEventLoop 的 run 方法,执行 I/O 任务和非 I/O 任务:I/O 任务,即 selectionKey 中 ready 的事件,如 accept、connect、read、write 等,由 processSelectedKeys 方法触发。非 IO 任务,添加到 taskQueue 中的任务,如 register0、bind0 等任务,由 runAllTasks 方法触发。两种任务的执行时间比由变量 ioRatio 控制,默认为 50,则表示允许非 IO 任务执行的时间与 IO 任务的执行时间相等。

一个EventLoop会处理一个channel全生命周期的所有事件。从消息的读取、编码以及后续Handler的执行,始终都由I/O线程NioEventLoop负责。每个EventLoop会有自己独立的任务队列。整个流程不会进行线程上下文的切换,数据也不会面临被并发修改的风险。

NioEventLoopGroup,主要管理 eventLoop 的生命周期,可以理解为一个线程池,内部维护了一组线程,每个线程(NioEventLoop)负责处理ChannelPipeline。


读事件:I/O线程NioEventLoop从SocketChannel中读取数据,将ByteBuf投递到ChannelPipeline,触发ChannelRead事件;I/O线程NioEventLoop调用ChannelHandler链,直到将消息投递到业务线程,然后I/O线程返回,继续后续的操作。

写事件:业务线程调用ChannelHandlerContext.write(Object msg)方法进行消息发送。ChannelHandlerInvoker将发送消息封装成 任务,放入到EventLoop的Mpsc任务队列中,业务线程返回。后续由EventLoop在循环中统一调度和执行。I/O线程EventLoop在进行 任务处理 时,从Mpsc任务队列中获取任务,调用ChannelPipeline进行处理,处理Outbound事件,直到将消息放入发送队列,然后唤醒Selector,执行写操作。

一、RocketMQ\Pulsar

rocketMQ 使用了 Netty 作为网络通信框架,自然而然使用了 Ractor 模型,即一个线程管理 N 个 Socket 的模式,此模式可管理海量连接,基本是所有网络服务器的首选。在这里,我们可以确定,RocketMQ 的 Boss 线程数为 1, Worker 线程数为 CPU * 2. 其中bossGroup只是用来接受消息的group,workerGroup是真正进行处理的group,handler对应bossGroup,childHandler对应workerGroup,EventExecutorGroup 就是专门来处理耗时业务的线程池。

二、Kafka

1+N+M处理模型

1. Acceptor 监听到来自请求者(请求者可以是来自 client,也可以来自 server)的新的连接,Acceptor 将这个请求者按照 round robin 的方式交给对对应的 Processor 进行处理;

2. Processor 注册这个 SocketChannel 的 OP_READ 的事件,如果有请求发送过来就可以被 Processor 的 Selector 选中;

3. Processor 将请求者发送的请求放入到一个 Request Queue 中,这是所有 Processor 共有的一个队列;

4. KafkaRequestHandler 从 Request Queue 中取出请求;

5. 调用 KafkaApis 进行相应的处理;

6. 处理的结果放入到该 Processor 对应的 Response Queue 中(每个 request 都标识它们来自哪个 Processor),Request Queue 的数量与 Processor 的数量保持一致;

7. Processor 从对应的 Response Queue 中取出 response;

8. Processor 将处理的结果返回给对应的请求者。

三、MSON

1、Golang 经典 netpoll 模型:goroutine-per-connection,每个goroutine负责accept、read和write等io事件,适用于在连接数不是瓶颈的情况。








2、多Reactor+workerpool模式, 基于 Netpoll 重写 epoll 机制,将 IO 和 PROXY 均进行池化,MOSN 对于网络层的操作,无论是调用端还是服务端,都封装在eventloop.go文件中,每当连接建立以后,MOSN 都会开启两个协程分别处理该连接上的读写操作