dubbo的provider有2种线程池: 

  • IO处理线程池。(直接通过netty等来配置)
  • 服务调用线程池。

  如果事件处理的逻辑能迅速完成,并且不会发起新的 IO 请求,比如只是在内存中记个标识,则直接在 IO 线程上处理更快,因为减少了线程池调度。

  但如果事件处理逻辑较慢,或者需要发起新的 IO 请求,比如需要查询数据库,则必须派发到线程池,否则 IO 线程阻塞,将导致不能接收其它请求。

  如果用 IO 线程处理事件,又在事件处理过程中发起新的 IO 请求,比如在连接事件中发起登录请求,会报“可能引发死锁”异常,但不会真死锁。

因此,需要通过不同的派发策略和不同的线程池配置的组合来应对不同的场景:

<dubbo:protocol name="dubbo" dispatcher="all" threadpool="fixed" threads="100" />
  • Dispatcher

all 所有消息都派发到线程池,包括请求,响应,连接事件,断开事件,心跳等。
direct 所有消息都不派发到线程池,全部在 IO 线程上直接执行。
message 只有请求响应消息派发到线程池,其它连接断开事件,心跳等消息,直接在 IO 线程上执行。
execution 只请求消息派发到线程池,不含响应,响应和其它连接断开事件,心跳等消息,直接在 IO 线程上执行。
connection 在 IO 线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池。

  • ThreadPool

fixed 固定大小线程池,启动时建立线程,不关闭,一直持有。(缺省)
cached 缓存线程池,空闲一分钟自动删除,需要时重建。
limited 可伸缩线程池,但池中的线程数只会增长不会收缩。只增长不收缩的目的是为了避免收缩时突然来了大流量引起的性能问题。
eager 优先创建Worker线程池。在任务数量大于corePoolSize但是小于maximumPoolSize时,优先创建Worker来处理任务。当任务数量大于maximumPoolSize时,将任务放入阻塞队列中。阻塞队列充满时抛出RejectedExecutionException。(相比于cached:cached在任务数量超过maximumPoolSize时直接抛出异常而不是将任务放入阻塞队列)

  上面是摘自官方的解释,下面进行研究:

producer.xml

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="hello-world-app">
<!-- 关闭QOS:Quality of Service -->
<dubbo:parameter key="qos.enable" value="false" />
<dubbo:parameter key="qos.accept.foreign.ip" value="true" />
<dubbo:parameter key="qos.port" value="2222" />
</dubbo:application> <dubbo:registry address="zookeeper://127.0.0.1:2181"
subscribe="false" dynamic="false" /> <!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880"/> <!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="dubbo.DubboService" ref="demoService"
timeout="500000" /> <!-- 和本地bean一样实现服务 -->
<bean id="demoService" class="dubbo.DubboServiceImpl" />
</beans>

consumer.xml

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="consumer-of-helloworld-app">
<!-- 关闭QOS:Quality of Service -->
<dubbo:parameter key="qos.enable" value="false" />
</dubbo:application> <!-- 使用multicast广播注册中心暴露发现服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" /> <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
<dubbo:reference id="dubboService" interface="dubbo.DubboService" />
</beans>

Consumer.java开启20个线程消费服务

package dubbo;

import java.util.concurrent.CountDownLatch;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Consumer { private static final Logger LOGGER = LoggerFactory.getLogger(Consumer.class); public static void main(String[] args) throws InterruptedException {
final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "consumer.xml" });
context.start();
for (int i = 0; i < 20; i++) {
new Thread(new Runnable() { @Override
public void run() {
DubboService service = (DubboService) context.getBean("dubboService");
LOGGER.info(service.sayHello(" china "));
}
}).start();
} CountDownLatch countDownLatch = new CountDownLatch(1);
countDownLatch.await();
}
}

多次访问之后,消费者线程数量会一直增加,并且消费完成之后线程并不会结束,并且每次访问结束都会增加20个线程。如下:

(1)测试  direct  所有消息都不派发到线程池,全部在 IO 线程上直接执行。(多个线程同时请求是一种同步执行的方式,服务端始终只有一条线程处理请求),如下:

    <!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" dispatcher="direct"/>

查看线程信息:

(2)使用固定fixed线程池处理并且大小定为20

    <!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" dispatcher="all"
threadpool="fixed" threads="20" />

多次访问线程数量仍然定在最高的20,不会增加。(这种情况适用于最大并发量是20的请求)

如果同时访问超过20个,会报下面错误:

Exception in thread "Thread-0" com.alibaba.dubbo.rpc.RpcException: Failed to invoke the method sayHello in the service dubbo.DubboService. Tried 3 times of the providers [192.168.0.232:20880] (1/13) from the registry 127.0.0.1:2181 on the consumer 192.168.0.232 using the dubbo version 2.6.6. Last error is: Failed to invoke remote method: sayHello, provider: dubbo://192.168.0.232:20880/dubbo.DubboService?anyhost=true&application=consumer-of-helloworld-app&bean.name=dubbo.DubboService&check=false&dubbo=2.0.2&dynamic=false&generic=false&interface=dubbo.DubboService&methods=sayHello&pid=5132&qos.enable=false&register.ip=192.168.0.232&remote.timestamp=1554373603443&side=consumer&timeout=500000&timestamp=1554374765210, cause: Server side(192.168.0.232,20880) threadpool is exhausted ,detail msg:Thread pool is EXHAUSTED! Thread Name: DubboServerHandler-192.168.0.232:20880, Pool Size: 20 (active: 20, core: 20, max: 20, largest: 20), Task: 67 (completed: 47), Executor status:(isShutdown:false, isTerminated:false, isTerminating:false), in dubbo://192.168.0.232:20880!
at com.alibaba.dubbo.rpc.cluster.support.FailoverClusterInvoker.doInvoke(FailoverClusterInvoker.java:102)
(3)limited  在同时访问超过线程数的时候多余请求被拒绝

  并且在生产者控制台打印如下信息

18:54:22 [com.alibaba.dubbo.common.threadpool.support.AbortPolicyWithReport]-[WARN]  [DUBBO] Thread pool is EXHAUSTED! Thread Name: DubboServerHandler-192.168.0.232:20880, Pool Size: 20 (active: 20, core: 0, max: 20, largest: 20), Task: 21 (completed: 1), Executor status:(isShutdown:false, isTerminated:false, isTerminating:false), in dubbo://192.168.0.232:20880!, dubbo version: 2.6.6, current host: 192.168.0.232

  多余的客户端请求报错同上面一样,

Server side(192.168.0.232,20880) threadpool is exhausted ,detail msg:Thread pool is EXHAUSTED! Thread Name: DubboServerHandler-192.168.0.232:20880, Pool Size: 20 (active: 20, core: 0, max: 20, largest: 20), Task: 21 (completed: 1), Executor status:(isShutdown:false, isTerminated:false, isTerminating:false), in dubbo://192.168.0.232:20880!

dubbo线程模型的更多相关文章

  1. 第十章 dubbo线程模型

    一 netty的线程模型 在netty中存在两种线程:boss线程和worker线程. 1 boss线程 作用: accept客户端的连接: 将接收到的连接注册到一个worker线程上 个数: 通常情 ...

  2. dubbo线程模型配置

    首先了解一下dubbo线程模型 如果事件处理的逻辑能迅速完成,并且不会发起新的IO请求,比如只是在内存中记个标识.则直接在IO线程上处理更快,因为减少了线程池调度. 但如果事件处理逻辑较慢,或者需要发 ...

  3. Dubbo入门到精通学习笔记(十一):Dubbo服务启动依赖检查、Dubbo负载均衡策略、Dubbo线程模型(结合Linux线程数限制配置的实战分享)

    文章目录 Dubbo服务启动依赖检查 Dubbo负载均衡策略 Dubbo线程模型(结合Linux线程数限制配置的实战分享) 实战经验分享( ** 属用性能调优**): Dubbo服务启动依赖检查 Du ...

  4. Dubbo学习笔记8:Dubbo的线程模型与线程池策略

    Dubbo默认的底层网络通讯使用的是Netty,服务提供方NettyServer使用两级线程池,其中 EventLoopGroup(boss) 主要用来接受客户端的链接请求,并把接受的请求分发给 Ev ...

  5. Dubbo -- 系统学习 笔记 -- 示例 -- 线程模型

    Dubbo -- 系统学习 笔记 -- 目录 示例 想完整的运行起来,请参见:快速启动,这里只列出各种场景的配置方式 线程模型 事件处理线程说明 如果事件处理的逻辑能迅速完成,并且不会发起新的IO请求 ...

  6. 【原创】Dubbo 2.7.5在线程模型上的优化

    这是why技术的第30篇原创文章 这可能是全网第一篇解析Dubbo 2.7.5里程碑版本中的改进点之一:客户端线程模型优化的文章. 先劝退:文本共计8190字,54张图.阅读之前需要对Dubbo相关知 ...

  7. 彻底搞懂 netty 线程模型

    编者注:Netty是Java领域有名的开源网络库,特点是高性能和高扩展性,因此很多流行的框架都是基于它来构建的,比如我们熟知的Dubbo.Rocketmq.Hadoop等.本文就netty线程模型展开 ...

  8. 面试官:Netty的线程模型可不只是主从多Reactor这么简单

    笔者看来Netty的内核主要包括如下图三个部分: 其各个核心模块主要的职责如下: 内存管理 主要提高高效的内存管理,包含内存分配,内存回收. 网通通道 复制网络通信,例如实现对NIO.OIO等底层JA ...

  9. 一文弄懂-Netty核心功能及线程模型

    目录 一. Netty是什么? 二. Netty 的使用场景 三. Netty通讯示例 1. Netty的maven依赖 2. 服务端代码 3. 客户端代码 四. Netty线程模型 五. Netty ...

随机推荐

  1. 面向对象内置方法之--__str__、__call__、__del__

    __str__: 在对象被打印的时候触发,可以用来定义对象被打印的输出格式 __del__:在对象被删除的时候触发,可以 用来回收对象以外的其他相关资源,比如系统资源等. __call__:在对象呗调 ...

  2. 网络安全实验室--SQL注入关

    第一关 万能密码:username='or '1'='1'#    password=1    即可登录得到flag. 第二关 最基础的注入,order by 判断字段数,然后 union selec ...

  3. DSP到底是个什么鬼?看完你就懂了

    DSP 即数字信号处理技术, DSP 芯片即指能够实现数字信号处理技术的芯片. DSP芯片是一种快速强大的微处理器,独特之处在于它能即时处理资料. DSP 芯片的内部采用程序和数据分开的哈佛结构,具有 ...

  4. 三十、小程序解析HTML(对富文本返回数据的处理)

    1.首先需要下载插件wxParse 下载地址 https://github.com/ZCLegendary/WXNews 百度云盘有保存 WXML <import src="../.. ...

  5. 04-JavaScript之常见运算符

    JavaScript之常见运算符 1.赋值运算符 以var x=12,y=5来演示示例 运算符 例子 等同于 运算结果 = x=y   x=5 += x+=y x=x+y x=17 -= x-=y x ...

  6. (hdu) 4857 逃生 (拓扑排序+优先队列)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4857 Problem Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄 ...

  7. JAVA获取计算机CPU、硬盘、主板、网络等信息

    通过使用第三方开源jar包sigar.jar我们可以获得本地的信息 1.下载sigar.jar sigar官方主页 sigar-1.6.4.zip 2.按照主页上的说明解压包后将相应的文件copy到j ...

  8. jQuery文件分片上传

    前端代码: <input type="file" id="file6" multiple> <button type="button ...

  9. 控制结构(9): 管道(pipeline)

    // 上一篇:线性化(linearization) // 下一篇:指令序列(opcode) 最近阅读了酷壳上的一篇深度好文:LINUX PID 1 和 SYSTEMD.这篇文章介绍了systemd干掉 ...

  10. LODOP、C-Lodop简短排查语句

    https使用,故障:1.是https网站吗,https扩展版C-Lodop如何使用 参考http://www.c-lodop.com/faq/pp32.html2.双击桌面上的c-lodop快捷方式 ...