首页 > 其他分享 >记几次 [线上环境] Dubbo 线程池占满原因分析(第一次:HttpClient)

记几次 [线上环境] Dubbo 线程池占满原因分析(第一次:HttpClient)

时间:2023-04-04 18:35:34浏览次数:44  
标签:Dubbo 池占满 http dubbo 接口 port 线程 200

转载:https://blog.csdn.net/wsmalltiger/article/details/124236055

前言
  我们一个核心应用,线上部署了4台机器(4c8g),某天晚上8点左右线上忽然出现dubbo线程池占满告警,上游应用error日志也疯狂报警,整个过程持续了4分钟左右系统自动恢复正常。
  dubbo 默认200个线程池,报错日志信息:

03-26 20:22:32.740 ERROR 25110 --- [ThreadPoolMonitor-thread-1] c.*.*.c.scheduled.ScheduledContainer : [DUBBO] Pool status:OK, max:200, core:200, largest:200, active:0, task:260504, service port: 20881;Pool status:WARN, max:200, core:200, largest:200, active:200, task:5568440, service port: 20882, dubbo version: 3.2.3.8-RELEASE, current host: 10.*.*.7
03-26 20:23:32.740 ERROR 25110 --- [ThreadPoolMonitor-thread-1] c.*.*.c.scheduled.ScheduledContainer : [DUBBO] Pool status:OK, max:200, core:200, largest:200, active:0, task:261272, service port: 20881;Pool status:WARN, max:200, core:200, largest:200, active:200, task:5573570, service port: 20882, dubbo version: 3.2.3.8-RELEASE, current host: 10.*.*.7
03-26 20:24:32.740 ERROR 25110 --- [ThreadPoolMonitor-thread-1] c.*.*.c.scheduled.ScheduledContainer : [DUBBO] Pool status:OK, max:200, core:200, largest:200, active:0, task:262550, service port: 20881;Pool status:WARN, max:200, core:200, largest:200, active:200, task:5578245, service port: 20882, dubbo version: 3.2.3.8-RELEASE, current host: 10.*.*.7
03-26 20:25:32.740 ERROR 25110 --- [ThreadPoolMonitor-thread-1] c.*.*.c.scheduled.ScheduledContainer : [DUBBO] Pool status:OK, max:200, core:200, largest:200, active:0, task:264110, service port: 20881;Pool status:WARN, max:200, core:200, largest:200, active:200, task:5582899, service port: 20882, dubbo version: 3.2.3.8-RELEASE, current host: 10.*.*.7

一、问题分析
1、查看监控
  公司的中间件监控系统做的比较完善,对dubbo框架的监控有进行定制化开发,并集成到统一运维平台,能够更加方便开发同学了解服务运行情况,出现问题时系统整体QPS流量:

对比前一天的系统QPS流量:

问题当天整体dubbo服务监控信息:

从上面监控信息中可以得出三个结论:
1、问题当天系统QPS流量开始相对平稳,下降的波动主要是由于问题期间dubbo线程池被占满导致无法处理其他请求,上升的波动是系统自动恢复后流量统计到同一时间上了,整体流量相比前一天流量没有明显增长;
2、Provider(服务端)平均RT上升较大,问题期间dubbo出现线程被长时间占用问题;
3、在RT上升机器,Consumer、Provider都有大量失败;

2、找到问题接口
查看dubbo接口RT监控,发现有一个接口问题期间平均RT达到 31秒多:

这么高的RT说明接口内部肯定出现了问题,继续查看接口RT耗时明细,最高RT将近达到 80秒:


3、分析接口
既然找到的问题接口,那么查看一下接口的日志信息,看看能否定位到原因:

  日志使用spring AOP做的切面,针对系统接口耗时如果超过3秒,则会自动打印出固定格式的日志,方便后续对高RT接口进行优化。这里AOP的好处一下就表现出来了,根据日志轻松找到相关信息,继续正对一条请求查看日志明细:

看到这个日志原因基本就可以确定了:dubbo接口内部请求了某个http接口,而这个http接口耗时较长导致长时间占用dubbo线程不释放,最终引起dubbo线程池被占满。

4、问题验证
  为什么http请求超时会导致dubbo线程长时间被占用呢?通过review接口代码,发现应用中使用了org. apache. http. impl. client. HttpClients工具类发送 http请求,继续 review 开源工具源码发现这个工具默认仅支持5个并发:

编写测试代码,验证一下超时是怎么形成的(为了模拟问题时的场景,请求的http接口内部会阻塞2秒):

for (int i = 0; i < 100; i++) {
new Thread(()->{
long tempTime = System.currentTimeMillis();
try {
String code = restfulServiceClient.get("http://10.*.*.88:7001/account/get?bId=" + bId + "&buyerId=" + buyerId, String.class);
} catch (Exception e) {
logger.error("请求超时:" , e);
}
long useTime = System.currentTimeMillis() - tempTime;
if (useTime < 1000 * 4) {
logger.info("i=" + index.incrementAndGet() + " 单次耗时:{} ms", useTime);
} else {
logger.error("i=" + index.incrementAndGet() + " 超时,单次耗时:{} ms", useTime);
}
}).start();
}


查看输出日志:

   这下原因清楚了:由于http工具默认仅支持 5 个并发,且有线程池队列,当请求量超过 5 个的时候,多余的请求会在队列中堆积。前一批http请求结束之后其他的请求才会继续执行,越到后面线程等待时间会越长。所以对应实际业务场景中dubbo线程等待的时间也会越长,当这个队列到一定数量之后,就会引起dubbo默认200个线程池被占满的情况,从而引起整个应用服务的报错。

二、解决方案
知道了问题原因,解决方案就变得简单起来:
1、系统中依赖 http 接口迁移到 java dubbo接口(对应业务方已经有相关dubbo接口);
2、工具类封装并进行优化,调整到合适的并发执行数量,修改队列方式,设置超时超时时间(参数值根据业务场景具体分析);
3、问题接口接入限流降级框架,配置限流阈值,防止在高流量的情况下导致接口被打挂;

总结
1、使用开源框架时要了解相关的原理,默认值不一定适合所有的场景,需要根据自己的场景分析选择对应的配置。
2、对代码存在敬畏之心,复杂的业务代码中,一个看似不起眼的http请求出现问题,最终会导致整个dubbo服务不可用。
3、完善监控系统,及时主动发现问题,及时处理降低影响面。


————————————————
版权声明:本文为CSDN博主「smatiger」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wsmalltiger/article/details/124236055

标签:Dubbo,池占满,http,dubbo,接口,port,线程,200
From: https://www.cnblogs.com/ceshi2016/p/17287344.html

相关文章

  • Dubbo——扩展(SPI)加载原理
    摘要Dubbo为了更好地达到OCP原则(即“对扩展开放,对修改封闭”的原则),采用了“微内核+插件”的架构。那什么是微内核架构呢?微内核架构也被称为插件化架构(Plug-inArchitecture),这是一种面向功能进行拆分的可扩展性架构。内核功能是比较稳定的,只负责管理插件的生命周期,不会因为系统功......
  • Dubbo——服务治理(dubbo-Admin)平台
    摘要本博文将介绍Dubbo最新的服务治理平台的实现原理。详细介绍服务治理中的路由规则、动态配置、访问控制、权重管理、负载均衡的实现原理。服务治理平台总体结构Dubbo有新旧两个服务治理平台,旧的服务治理平台在Dubbo2.6.0以后就从源码中被移除了,现在已经没有继续维护。新的服务......
  • dubbo 限制方法线程数_不可忽视的Dubbo线程池避坑指南
    转载:https://blog.csdn.net/weixin_39574140/article/details/110193195?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-110193195-blog-121764780.235%5Ev27%5Epc_relevant_recovery_v2&depth_1-ut......
  • dubbo线程池又被打爆(打满)了java.util.concurrent.RejectedExecutionException: Thread
    转载:https://blog.csdn.net/kevin_mails/article/details/121764780?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-121764780-blog-124236206.235%5Ev27%5Epc_relevant_recovery_v2&depth_1-utm_sourc......
  • 记几次 [线上环境] Dubbo 线程池占满原因分析(第三次:GC STW)
    转载:https://blog.csdn.net/wsmalltiger/article/details/124236206前言  某天晚上正在开开心心写代码,忽然收到了线上告警:dubbo线程池活跃线程数告警、应用错误日志告警、dubbo线程池队列长度告警;瞬间意识到要出大事情了,得赶紧定位到原因并解决问题,不然时间长了肯定会影响商......
  • Kotlin 协程真的比 Java 线程更高效吗?
    vivo互联网技术微信公众号 作者:吴越网上几乎全部介绍Kotlin的文章都会说Kotlin的协程是多么的高效,比线程性能好很多,然而事情的真相真是如此么?协程的概念本身并不新鲜,使用C++加上内嵌汇编,一个基本的协程模型50行代码之内就可以完全搞出来。早在2013年国内就有团队开源了号称支持......
  • 多线程任务怎么选 Thread,ThreadPoll,Task
    提问多线程任务怎么选Thread,ThreadPoll,Task回答Task原因Thread:创建销毁代价昂贵ThreadPoll:管理线程资源Task基于线程池......
  • Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了
    如何阻止JavaSpringBootTest单元测试中包括多线程时,没跑完就结束了使用CountDownLatchCountDownLatch、CyclicBarrier使用区别多线程ThreadPoolTaskExecutor应用JavaBasePooledObjectFactory对象池化技术@SpringBootTestpublicclassPoolTest{@Test......
  • 线程池之FutureTask、ThreadPoolExecutor源码分析
    前言在我们日常工作中,我们经常会用到多线程的来处理一些异步任务,提高系统吞吐量,但是线程毕竟是一种昂贵的系统的资源,我们不应该频繁的去申请销毁。在java的projectloom还未正式release的时候,我们常用池化的方式来使用线程。所以了解线程池的设计思想能够有助于我们更好的使用它,......
  • 线程间数据传递之ThreadLocal、InheritableThreadLocal、TransmittableThreadLocal
    前言在JAVA中线程之间传输数据的方式有多种,而本文旨在探讨ThreadLocal及其衍生类的使用场景。使用场景业务系统的参数传递:在我们的业务系统中可能会用到许多公共参数,可能是用户的token信息,在我们链路中可能某一个方法需要用到它,那么我们又不想一层层的传递它。分布式系统要打......