对最近遇到的业务应用dubbo线程池爆满(异常:RejectedExecutionException:Thread pool is EXHAUSTED)问题进行了分析。

一、问题回顾:

业务应用dubbo配置如下:

<dubbo:protocol name="dubbo" port="${dubbo.port}" /}

在dubbo的spring配置中,业务应用并没有配置threadpool,threads等参数,查看dubbo.io用户文档,可知:默认配置为:

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

查看dubbo代码(版本为2.5.3)实现:FixedThreadPool.java

/** Copyright 1999-2011 Alibaba Group.*  * Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at*  *      http://www.apache.org/licenses/LICENSE-2.0*  * Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.alibaba.dubbo.common.threadpool.support.fixed;import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.threadpool.ThreadPool;
import com.alibaba.dubbo.common.threadpool.support.AbortPolicyWithReport;
import com.alibaba.dubbo.common.utils.NamedThreadFactory;/*** 此线程池启动时即创建固定大小的线程数,不做任何伸缩,来源于:<code>Executors.newFixedThreadPool()</code>* * @see java.util.concurrent.Executors#newFixedThreadPool(int)* @author william.liangf*/
public class FixedThreadPool implements ThreadPool {public Executor getExecutor(URL url) {String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME);int threads = url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS);int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES);return new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS, queues == 0 ? new SynchronousQueue<Runnable>() : (queues < 0 ? new LinkedBlockingQueue<Runnable>() : new LinkedBlockingQueue<Runnable>(queues)),new NamedThreadFactory(name, true), new AbortPolicyWithReport(name, url));}}

其中:

public class Constants {// the other constant// ......public static final String  DEFAULT_THREAD_NAME = "Dubbo";public static final int     DEFAULT_THREADS = 200;public static final int     DEFAULT_QUEUES = 0;
}

由代码可知:dubbo的线程池采用jdk的ThreadPoolExecutor,默认threads数为200,默认队列长度为0,此时默认采用了SynchronousQueue队列,而如果用户配置的队列长度大于0时,则会采用LinkedBlockingQueue队列。【注意:由此可见,dubbo.io用户文档中,默认threads=100是错误的,实际为200】

SynchronousQueue:是一个缓存为1的阻塞队列,某次添加元素后必须等待其他线程取走后才能继续添加。

LinkedBlockingQueue:线程安全的基于链表的阻塞队列,实现了入队出队的分离(分别采用putLock和takeLock锁,因此可以同时入队和出队操作)位于java.util.concurrent包下,是一个无界队列。

ThreadPoolExecutor的完整构造方法的签名是:ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) .corePoolSize - 池中所保存的线程数,包括空闲线程。
maximumPoolSize-池中允许的最大线程数。
keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
unit - keepAliveTime 参数的时间单位。
workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute方法提交的 Runnable任务。
threadFactory - 执行程序创建新线程时使用的工厂。
handler - 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序。
ThreadPoolExecutor是Executors类的底层实现。

dubbo默认创建固定大小的线程池(200), 每次提交一个任务就创建一个线程,直到线程数达到线程池大小200,线程池的大小一旦达到最大值就保持不变。如果某个线程因为执行异常而结束,那么线程池会补充一个新的线程。

由于dubbo默认采用了直接提交的SynchronousQueue工作队列,所以,所有的task会直接提交给线程池中的某一worker线程,如果没有可用线程,那么会拒绝任务的处理,而抛出异常RejectedExecutionException:Thread pool is EXHAUSTED.

/** Copyright 1999-2011 Alibaba Group.*  * Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at*  *      http://www.apache.org/licenses/LICENSE-2.0*  * Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.alibaba.dubbo.common.threadpool.support;import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;/*** Abort Policy.* Log warn info when abort.* * @author ding.lid*/
public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {protected static final Logger logger = LoggerFactory.getLogger(AbortPolicyWithReport.class);private final String threadName;private final URL url;public AbortPolicyWithReport(String threadName, URL url) {this.threadName = threadName;this.url = url;}@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor e) {String msg = String.format("Thread pool is EXHAUSTED!" +" Thread Name: %s, Pool Size: %d (active: %d, core: %d, max: %d, largest: %d), Task: %d (completed: %d)," +" Executor status:(isShutdown:%s, isTerminated:%s, isTerminating:%s), in %s://%s:%d!" ,threadName, e.getPoolSize(), e.getActiveCount(), e.getCorePoolSize(), e.getMaximumPoolSize(), e.getLargestPoolSize(),e.getTaskCount(), e.getCompletedTaskCount(), e.isShutdown(), e.isTerminated(), e.isTerminating(),url.getProtocol(), url.getIp(), url.getPort());logger.warn(msg);throw new RejectedExecutionException(msg);}}

因此,如果系统抛出异常RejectedExecutionException:Thread pool is EXHAUSTED.可以通过调大dubbo线程池解决该问题,或者降低对TPS的预期。

<dubbo:protocol name="dubbo" dispatcher="all" threadpool="fixed" threads="500" />

此处修改了dubbo线程池为500,以处理更多的任务。

原文地址:https://my.oschina.net/maliang1989/blog/994548?from=timeline&isappinstalled=0

Dubbo线程池耗尽原理分析Thread pool is EXHAUSTED相关推荐

  1. Dubbo线程池耗尽问题

    场景:dubbo 线程池耗尽,报错. Caused by: java.util.concurrent.RejectedExecutionException: Thread pool is EXHAUS ...

  2. Java 线程池(ThreadPoolExecutor)原理分析与使用 – 码农网

    线程池的详解 Java 线程池(ThreadPoolExecutor)原理分析与使用 – 码农网 http://www.codeceo.com/article/java-threadpool-exec ...

  3. Java 线程池(ThreadPoolExecutor)原理分析与使用

    ThreadPoolExecutor原理概述 在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使 ...

  4. ScheduledThreadPoolExecutor定时任务线程池执行原理分析

    一.示例代码 @Slf4j public class ScheduleThreadPoolTest {private static ScheduledExecutorService executor ...

  5. Dubbo线程池问题思考Thread pool is EXHAUSTED!

    问题 前几天,我们的生产上突然出现了这样一个问题,调下面的查询方法报错,线程池满的问题,如下图: 问题思路 简单思考:我们都知道线程池的参数都包含什么含义!核心线程数,可建线程数,存储任务队列,拒绝策 ...

  6. 并发编程五:java并发线程池底层原理详解和源码分析

    文章目录 java并发线程池底层原理详解和源码分析 线程和线程池性能对比 Executors创建的三种线程池分析 自定义线程池分析 线程池源码分析 继承关系 ThreadPoolExecutor源码分 ...

  7. 记几次 [线上环境] Dubbo 线程池占满原因分析(第三次:GC STW)

    [线上环境] Dubbo 线程池占满原因排查系列 记几次 [线上环境] Dubbo 线程池占满原因分析(第一次:HttpClient) 记几次 [线上环境] Dubbo 线程池占满原因分析(第二次:C ...

  8. 记一次线上压测Dubbo线程池队列满的问题

    本文记录一次线上全链路压测出现的Dubbo线程池队列满的问题. 1 问题描述 线上做全链路压测,其中涉及三个系统,调用关系A->B->C,均是dubbo调用.压测的时候C出现CPU满导致服 ...

  9. 如何使用Arthas定位线上 Dubbo 线程池满异常

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | 公众号「Kirito的技术分享」 前言 本文是 ...

  10. Arthas | 定位线上 Dubbo 线程池满异常

    作者 | 徐靖峰  阿里云高级开发工程师 前言 Dubbo 线程池满异常应该是大多数 Dubbo 用户都遇到过的一个问题,本文以 Arthas 3.1.7 版本为例,介绍如何针对该异常进行诊断,主要使 ...

最新文章

  1. 短途人生- 让自己慢下来(39)
  2. NYOJ练习题 又见Alice and Bob
  3. MY_Log,无缝替换原生Log,支持日志输出到文件、FirePHP
  4. jep290涉及jdk版本_JDK 14 – JEP 361从预览中切换表达式
  5. 啥?分布式啥?啥事务?
  6. Hbuilder开发app实战-识岁06-face++的js实现【完结】
  7. html加速度陀螺仪坐标,如何从Javascript访问加速度计/陀螺仪数据?
  8. IDEA如何打包可运行jar,外部引用jar包版
  9. 【转】android开发中如何结束所有的activity
  10. 【三维路径规划】基于matlab人工蜂群算法无人机三维路径规划【含Matlab源码 021期】
  11. scipy库中的stats模块
  12. [java编程题]打印指定年指定月份的日历
  13. Excel不用知道sumifs函数也可以多条件求和
  14. 硬件内存模型 Hardware Memory Models
  15. 机电学生写给十年后自己的一封信
  16. JS获取Json值以及通过值获取索引
  17. 游戏+与通用人工智能的实现
  18. QQ群霸屏优化技术之轻松日引3000+IP
  19. 一款json查询操作神器
  20. JAVA线程状态的10种转换

热门文章

  1. 软件架构-解密电商系统商品模块业务
  2. Mini CFA 考试练习题 Macroeconomics
  3. 南京大学计算机专业复试面试,2014 CS复试全面回忆 上机真题 面试血泪史
  4. Gris 游戏开发-day04
  5. 腾讯让企业微信连接微信,这是针对钉钉的精准打击吗?
  6. R 计算变量之间的相关性
  7. 无线通信蜂窝网络 的 覆盖范围
  8. 仙剑奇侠传3 全开注册表改法
  9. 程序猿头头(防抖节流)
  10. MODULE_DEVICE_TABLE宏的作用