Netty的线程模型
Reactor模型
Netty的模型就是基于Reactor(反应堆)模式实现的,所以一定要先认识下Reactor。
Reactor模型也叫Dispatch(派遣)模型。当一个或多个请求同时传给服务端,服务端将它们同步分派给各个请求的处理线程。
Reactor模型的三种角色
- Acceptor:处理客户端新连接,并分配请求到处理链中
- Reactor:负责监听和分配事件,将I/O事件分配给对应的Handler
- Handler:事件处理,如编码、业务处理、解码等
Reactor的线程模型
一共有三种模型:单Reactor单线程模型、单Reactor多线程模型、主从Reactor多线程模型。
Netty使用的是主从Reactor多线程模型。
1.单Reactor单线程模型
该线程模型下,所有的请求连接建立、I/O读写、业务处理都是在一个线程完成的。如果业务处理出现了耗时操作,因为在一个线程上所有操作时同步的,就会导致所有请求都会延时处理,造成阻塞。
2.单Reactor多线程模型
为了防止阻塞,该线程模型下,请求连接建立(包括授权认证等)、I/O读写在一个Reactor线程完成,另外业务处理在一个线程池中异步处理完成,处理完再回写。
3.主从Reactor多线程模型
因为单Reactor还能不能榨干CPU多核的能力,所以可以建立多个Reactor线程。该线程模型下,有一主多从Reactor。主Reactor是进行请求连接建立(包括授权认证等),从Reactor们用于处理I/O读写,业务处理同样还是在一个线程池中异步处理。
Netty的线程模型
成员组成
Netty线程模型组成大概有ServerBootStrap、NioEventLoopGroup和它的成份NioEventLoop、NioChannel、ChannelPipeline、ChannelHandler等等。
Netty采用的是主从Reactor多线程模型来实现,主Reactor就对应的是BossGroup,从Reactor对应是WorkerGroup。BossGroup用于接收连接,并把建立好的连接通过Channel方式注册到WorkerGroup,当IO事件触发时,由Pipeline来处理,Pipeline由对应的Handler来实际处理。
EventLoop
事件循环器
从名字可以得知它其实是一个不断循环的进程。就是相当于之前nio模型的while(true)
里的那对代码段。
EvnetLoop里主要由一个Selector多路复用选择器来处理IO事件的,和一个TaskQueue存储提交的任务。
EventLoop的启动方式是初始时不启动,当有任务提交过来,就启动处理任务,并一直跑一下去。
EventLoop相关源码(删减)
@Override
protected void run() {
int selectCnt = 0;
for (;;) {
try {
int strategy;
try {
strategy = selectStrategy.calculateStrategy(selectNowSupplier, hasTasks());
switch (strategy) {
case SelectStrategy.CONTINUE:
case SelectStrategy.BUSY_WAIT:
case SelectStrategy.SELECT:
}
boolean ranTasks;
if (ioRatio == 100) {
try {
if (strategy > 0) {
processSelectedKeys();
}
} finally {
// Ensure we always run tasks.
ranTasks = runAllTasks();
}
} else if (strategy > 0) {
final long ioStartTime = System.nanoTime();
try {
processSelectedKeys();
} finally {
// Ensure we always run tasks.
final long ioTime = System.nanoTime() - ioStartTime;
ranTasks = runAllTasks(ioTime * (100 - ioRatio