一次dubbo客户端消费者超时-线程池耗尽问题处理

1、问题起因

上线一个文件下载服务,运行一直稳定,偶有异常(连接国外网络不稳定导致),一天突然消费端频繁抛出超时异常(不是所有请求都超时,大部分超时),
起初以为下载文件过大导致超时,测试发现不是该问题(使用小文件测试),猜测可能是服务端出了问题

2、查看问题

查看服务端最近异常log,发现如下异常(异常信息从网上down的,不是原始信息,原始信息当时删了,懒得去找了。。)
[DUBBO] An exception was thrown by a user handler while handling an exception event ([id: 0xa7e4b981, /172.16.*.*:4216 :> /172.16.*.*:20882] EXCEPTION: java.nio.channels.ClosedChannelException), dubbo version: resourcecenter, current host: 172.16.*.* com.alibaba.dubbo.remoting.ExecutionException: class com.alibaba.dubbo.remoting.transport.dispatcher.all.AllChannelHandler error when process caught event . at com.alibaba.dubbo.remoting.transport.dispatcher.all.AllChannelHandler.caught(AllChannelHandler.java:67) ~[resourcecenter.jar:?] at com.alibaba.dubbo.remoting.transport.AbstractChannelHandlerDelegate.caught(AbstractChannelHandlerDelegate.java:44) ~[resourcecenter.jar:?] at com.alibaba.dubbo.remoting.transport.AbstractChannelHandlerDelegate.caught(AbstractChannelHandlerDelegate.java:44) ~[resourcecenter.jar:?] ... Caused by: java.util.concurrent.RejectedExecutionException: Thread pool is EXHAUSTED! Thread Name: DubboServerHandler-172.16.*.*:20882, Pool Size: 200 (active: 185, core: 200, max: 200, largest: 200), Task: 1341173 (completed: 1340996), Executor status:(isShutdown:false, isTerminated:false, isTerminating:false), in dubbo://172.16.*.*:20882! at com.alibaba.dubbo.common.threadpool.support.AbortPolicyWithReport.rejectedExecution(AbortPolicyWithReport.java:53) ~[resourcecenter.jar:?] at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823) ~[?:1.8.0_111] at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369) ~[?:1.8.0_111] at com.alibaba.dubbo.remoting.transport.dispatcher.all.AllChannelHandler.caught(AllChannelHandler.java:65) ~[resourcecenter.jar:?] ...

从字面意思可以看出,dubbo默认业务线程池线程为200个,目前所有线程都被占用了。目前问题大概定位了,通过
jstack -l pid > dubbo.dump
输出当前线程堆栈信息,查看堆栈信息,发现所有dubbo线程都被同一个方法堵住了
在这里插入图片描述

找到对应代码(很古老一段代码,很久没有维护的),发现使用httpclient发送http请求没有设置超时,导致线程阻塞线程池资源耗尽(至于以前为什么没有出现这个问题,没有去深究不在此次记录范围,不在此分享了)
在这里插入图片描述
知道问题了也就好解决了,修改代码设置超时时间
在这里插入图片描述
重新发版问题解决

3、思考

既然服务端没有线程资源处理业务了为什么客户端没有收到异常信息,而是一直等到超时?这个问题与dubbo的默认配置有关,默认dispatcher(线程派发器)为all
线程请求模型dubbo官方文档(http://dubbo.apache.org/zh-cn/docs/source_code_guide/service-invoking-process.html)
在这里插入图片描述

默认dispatcher(线程派发器)处理handler为AllChannelHandler继承WrappedChannelHandler,可以看到请求、连接等都是交给业务线程池处理,问题也出在这里,当业务线程池耗尽时,本来应该抛出执行拒绝异常,该处理方法caught也是交给业务线程池处理,而业务线程池所有线程都堵住了,所以客户端消费者只能傻傻等到超时
在这里插入图片描述
解决办法可以设置dispatcher为message,实现为MessageOnlyChannelHandler继承WrappedChannelHandler,只有请求和响应交给业务线程池处理,其他的在IO线程处理,配置如下
<dubbo:protocol name="dubbo" dispatcher="message" />
在这里插入图片描述

简单看了源码有个疑惑,响应并没有看到交给业务线程池处理,都是调用WrappedChannelHandler的sent方法,欢迎大佬指教原因

参考
https://www.iteye.com/blog/manzhizhen-2391177

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值