生产环境出现的几次线程池被占满的问题分析

问题描述

  1. dubbo的线程池内所有线程在极短时间内占用完,导致新来的RPC调用无线程可用,导致出现dubbo自定义的异常信息:RejectedExecutionException,错误描述为:Thread pool is EXHAUSTED!

问题分析

1. dubbo线程池的分析

项目发布后,发现生产上面dubbo的线程池迅速被耗尽,查看日志看到如下信息:

Caused by: java.util.concurrent.RejectedExecutionException: Thread pool is EXHAUSTED! Thread Name: DubboServerHandler-10.3.6.32:20890, Pool Size: 200 (active: 200, core: 200, max: 200, largest: 200), Task: 31662 (completed: 31462), Executor status:(isShutdown:false, isTerminated:false, isTerminating:false), in dubbo://10.3.6.32:20890!

RejectedExecutionException是dubbo provide线程池的拒绝策略(详情见:引入dubbo的实战记录),默认200大小的线程池被占满了,随后我们在这段日志的上面发现了另外一段日志:

java.io.IOException: Server returned HTTP response code: 502 for URL: http://backend.ifaclub.com/backend

发现这个http请求调用异常了,并且发现整个接口调用花了100秒,那么问题就显而易见了,前端一个请求,发送到A系统,A系统通过dubbo调用B系统,B系统http调用php提供的一个接口,php的这个服务由于一些未知原因特别慢,导致我们的http请求花了很长时间,这时候dubbo的线程一直得不到释放,由于A系统这时候频繁调用B系统,导致B系统的dubbo线程池线程很快被耗尽(dubbo服务提供方线程池默认固定大小200,并且SynchronousQueue的初始化大小为0,也就是说线程池总的容量为200)。后来的解决方案:1.减小http的超时时长(之前设置的是60秒);2.加大dubbo线程池容量;这样就算http调用会发生超时,超时时间也很短,会让dubbo线程很快释放,增加线程池最大容量就不说了。当线程池已满时,使用界队列来存储未执行的任务有这样一个好处,当发生异常情况导致线程池被撑满时,问题能尽快的暴露出来,如果是无界队列,这样未执行的任务会一直积压在队列中,极有可能会撑满内存,最终导致整个应用不可用。

你可能感兴趣的:(生产环境出现的几次线程池被占满的问题分析)