Dubbo源码解析

Dubbo之线程模型

2020-03-24  本文已影响0人  土豆肉丝盖浇饭

以netty传输层实现为例

Dubbo的线程模型其实就是netty的线程模型,主从Refactor模型。



主Refactor用于建立连接,子Refactor用于监听所有事件进行处理。子Refactor在处理事件时,通常会把读事件交给业务线程池处理。

Dubbo对于这些事件的分发逻辑封装到Dispatcher扩展点

事件对应关系

为了保证Dubbo传输层不依赖于特定框架,Dubbo封装了自己的事件接口用于适配各个传输层框架。下面是dubbo和netty中事件接口的对应关系。

Netty Dubbo 描述
channelActive connected 连接
channelInactive disconnected 断连
channelRead received 收到报文
write sent 发送报文
exceptionCaught caught 发生异常
userEventTriggered 使用netty接口 用户事件

Dispatcher扩展点

而我们的Dispatcher扩展点会决定在上面的事件中使用那些线程池。

Dispatcher connected disconnected received sent caught
AllDispatcher(默认) 业务线程池 业务线程池 业务线程池 IO线程池 业务线程池
ConnectionOrderedDispatcher 连接专属线程池 连接专属线程池 业务线程池 IO线程池 业务线程池
DirectDispatcher IO线程池 IO线程池 IO线程池 IO线程池 IO线程池
ExecutionDispatcher IO线程池 IO线程池 业务线程池(只针对Request) IO线程池 IO线程池
MessageOnlyDispatcher IO线程池 IO线程池 业务线程池(全部) IO线程池 IO线程池

IO线程池是Netty 从Refactor所在的线程池,也就是EventLoop。

业务线程池指的是Dubbo的ThreadPool扩展点生成的线程池,创建逻辑如下。

executor = (ExecutorService) ExtensionLoader.getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url);

关于Dubbo的ThreadPool扩展点,可以看[这篇文章](https://www.jianshu.com/p/3decaaa00e00](https://www.jianshu.com/p/3decaaa00e00)

连接专属线程池是在ConnectionOrderedDispatcher模式下专门创建用于处理连接的一个线程池,逻辑如下

connectionExecutor = new ThreadPoolExecutor(1, 1,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(url.getPositiveParameter(Constants.CONNECT_QUEUE_CAPACITY, Integer.MAX_VALUE)),
                new NamedThreadFactory(threadName, true),
                new AbortPolicyWithReport(threadName, url)
        ); 

整体dispatcher的逻辑如下


最佳实践

Dubbo的默认使用AllDispatcher和core=max=200,queue为SynchronousQueue的FixedThreadPool。

这会出现一个问题,当FixedThreadPool中的200个线程都处于忙碌状态时,我们新的请求会被拒绝抛出异常,而这个异常会被caught方法捕获,但是caught方法也在这个业务线程池中执行,可能这个任务还是会被拒绝,客户端只能等到超时,抛出超时异常。

超时异常是相当的恐怖,我们无法确认它背后是否执行以及是否成功。

所以建议设置ThreadPool的queue为一个合理的数字,并且使用MessageOnlyDispatcher或ExecutionDispatcher。

参考

线程模型
dubbo的dispatcher设置原理

上一篇 下一篇

猜你喜欢

热点阅读