深入分析dubbo线程池耗尽异常的问题

一、事故现象:

买家端订单列表加载不出来,购物车服务异常。

二、事故现象分析

首先,soa服务原来查询订单是单线程查询,查询过程中会调用其它方法补充订单数据,后来为了提升响应时间,将补充订单数据的方法开启了并行调用

关键点:订单查询和订单数据补充查询,使用的是同一个线程池(线程池大小128),并且线程池队列非常大(队列大小1024)。

以下是过程分析,从上往下是请求发展的时间线

过程分析:

1、soa中的父线程和子线程使用同一个自定义线程池order-pool

2、soa中只要某次请求里有一个子线程没有释放,对应的父线程就不会释放,父线程一直在等待子线程返回数据,从而引发父线程堆积,同时父线程长时间的等待导致调用方的dubbo超时。

买家端的购物车获取和订单查询都出现了超时异常,如下图

 为什么订单和购物车都受到了影响?因为购物车和订单查询使用的soa中同一个dubbo线程池,当时soa的对外的provider的dubbo配置如下图

3、最终自定义线程池order-pool数量在某次请求后变为0,线程池order-poo用尽后,并行的子线程开始在队列中排队。

4、因为soa中自定义线程池是为dubbo传递过来的请求服务的,因此soa中每一个父线程对应着一个dubbo的provider线程,自定义线程不是发,dubbo的provider线程池也不会释放,进而dubbo线程池耗尽,触发dubbo线程池耗尽异常,调用soa服务的订单和购物车都受到了影响,如下图

 5、在dubbo层面将流量拒绝后,就没有流量进入到自定义线程池的队列中了,所以内部线程池order-pool中排队数会慢慢减小,过一段时间dubbo线程池就会随着之前的请求得到响应而释放,进而继续响应,然后再次被打满,循环以上过程,也就是下图所示在持续一段时间后耗时降下来,然后又上去。

三、改进方案

1、将soa对外提供不同服务的接口,拆分成使用不同的dubbo线程池,如下图将soa中购物车和订单对外的dubbo服务拆分成不同的dubbo服务,每一个配置200线程大小

 

2、将自定义线程池队列减少,尽量减少排队的出现,这样就不会长时间等待,大不了自定义线程拒绝异常,虽然会损失部分数据,但不至于引起大面积瘫痪

3、soa中自定义线程池大大小大于soa中对外服务的jsf线程池大小,这样在soa内部并行的时候,能够保证自定义线程数是够用的,也能避免一些问题

猜你喜欢

转载自blog.csdn.net/bingxuesiyang/article/details/119839877