导读
我们都知道,Dubbo使用默认的网络传输框架是Netty,服务提供方NettyServer使用两个NIO线程池EventLoopGroup(boss)和EventLoopGroup(worker),前者负责接收客户端的连接,并分发给后者处理。我们把这两个线程组成为I/O线程(或Netty线程)。
如果服务提供方能快速处理客户端的请求,那么直接在I/O线程(Netty线程)上处理比较合适。否则(如查DB、请求三方接口等),需要将客户端的请求,分派(Dispatcher)给业务线程池(Dubbo线程池),我们称之为I/O线程与业务线程分离。
如果大家对Reactor或Netty的线程模型不够熟悉的话,推荐阅读深入理解Netty线程模型。
下面的内容,我为大家深入讲解Dubbo线程模型与线程池策略等相关内容,通过本章内容,大家可以学到如下知识点:
-
Dubbo线程模型分类
-
Dubbo线程模型源码分析
-
Dubbo线程模型的确认时机
-
如何自定义线程模型
Dubbo线程模型分类
Dubbo提供了如下几种线程模型:
1、all(Dubbo默认),对应于AllDispatcher类,该线程模型表示,所有的消息事件都分派给业务线程池,包括请求响应、连接事件、断开连接事件、心跳事件等。
2、direct,对应于DirectDispatcher类,该线程模型表示,所有消息事件都不派发到业务线程池,全部在I/O线程池上处理。
3、message,对应于MessageOnlyDispatcher类,该线程模型表示,只有请求和响应事件分派给业务线程池,其他的事件如连接事件、心跳事件等,直接在I/O线程池中处理。
4、execution,对应于ExecutionDispatcher类,该线程模型表示,只把请求事件分派给业务线程池,其他事件如心跳、连接、响应等直接在I/O线程池中执行
5、connection,对应于ConnectionOrderedDispatcher类,该线程模型表示,将连接事件、断开连接事件等放入一个队列有序等I/O线程池执行,其他类型事件直接分派给业务线程池执行。
Dubbo线程模型源码分析
首先,我们看一下Dispatcher接口,这个接口是所有线程模型需要实现的接口,代码如下
@SPI(AllDispatcher.NAME)
public interface Dispatcher {
@Adaptive({Constants.DISPATCHER_KEY, "dispather", "channel.handler"})
ChannelHandler dispatch(ChannelHandler handler, URL url);
}
我们可以看到,这个接口只有一个dispatch方法,并且是一个SPI的扩展点(如果大家对Dubbo的SPI机制不熟悉的话,请务必熟悉该机制,推荐阅读Apache Dubbo系列:增强SPI),并且默认的线程模型是all,即AllDispatcher类,接下来我们分析AllDispatcher类。
public class AllDispatcher implements Dispatcher {
public static final String NAME = "all";
@Override
public ChannelHandler dispatch(ChannelHandler handler, URL url) {
return new AllChannelHandler(handler, url);
}
}
public class AllChannelHandler extends WrappedCh