dubbo提供了自己的线程池以及派发策略,其实官方文档上讲的是比较清楚的,只需要结合着源码看下,就能明白具体的原理
dubbo官方文档地址
线程模型
用简单的总结来说,dubbo中的线程模型是有netty本身的io线程 + dubbo提供的线程池组成的,也就是说,不管是正常的请求、还是响应、还是连接请求、断开连接请求,要么是有netty的io线程来执行,要么是线程池中的线程来执行
不同的派发策略,会有不同的处理效果
派发策略以及源码
根据官网的解释,有以下五种派发策略,在自己去学习这五个策略的时候,我一直不明白是如何实现有些请求可以交给线程池去处理,有些请求会交给io线程去处理,看了源码之后,就理解了
问题:
1、首先有五个派发策略,其中有四个都继承了WrappedChannelHandler, 为什么单单direct没有继承?
2、是如何实现请求是要到线程池中?还是到io线程中执行呢?
先回答第二个问题,wrappedChannelHandler是一个handler,是会被netty执行的,所以,如果我们没有做其他处理,默认执行wrappedChannelHandler中的方法,那其实就是把请求交给了netty的io线程去执行
在dubbo中,五个dispatcher类,通过覆写wrappedChannelHandler的方法,来决定是要交给线程池执行?还是io线程执行
也就是说,如果连接事件,要交给线程池执行,那就覆写connect()方法,在子类的connect方法中,将请求交给线程池即可
如果断开连接事件,要交给io线程执行,就不需要在子类中覆写disConnect()方法
WrappedChannelHandler#getExecutorService()
这里先插一段代码,因为这段代码是前提,就是根据dubbo的自适应扩展机制以及我们的配置,来获取一个线程池,默认是fix
public WrappedChannelHandler(ChannelHandler handler, URL url) {
this.handler = handler;
this.url = url;
//初始化线程池,根据adaptive机制,获取dubbo提供的线程池
executor = (ExecutorService) ExtensionLoader.getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url);
String componentKey = Constants.EXECUTOR_SERVICE_COMPONENT_KEY;
if (Constants.CONSUMER_SIDE.equalsIgnoreCase(url.getParameter(Constants.SIDE_KEY))) {
componentKey = Constants.CONSUMER_SIDE;
}
DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();
dataStore.put(componentKey, Integer.toString(url.getPort()), executor);
}
// 获取线程池
public ExecutorService getExecutorService() {
ExecutorService cexecutor = executor;
if (cexecutor == null || cexecutor.isShutdown()) {
cexecutor = SHARED_EXECUTOR;
}
return cexecutor;
}
AllDispatcher
所有消息都派发到线程池,包括请求,响应,连接事件,断开事件,心跳等。
可以看到,这个dispatch的类,覆写了父类的所有方法,在子类的实现方法中,都是调用的cexecutor.execute()去提交的任务
getExecutorService()就是获取当前程序员配置的要使用的线程池,如果不配置,默认是fix
@Override
public void connected(Channel channel) throws RemotingException {
ExecutorService cexecutor = getExecutorService();
try {
cexecutor.execute(new ChannelEventRunnable(channel, handler, ChannelState.CONNECTED));
} catch (Throwable t) {
throw new ExecutionException("connect event", channel, getClass() + &#