jieye の 数字花园

Search

Search IconIcon to open search

使用LinkedBlockingQueue时线程池的坑

Last updated Unknown

最近遇到一个问题HTTP 线程快速上升,外部服务调用超时,服务本身响应时间超长

# 现象

应用平常运行正常没有任何问题,突然有一天应用的访问量爆增,出现外部服务调用超时,服务本身响应时间超长,HTTP线程快速上升,但CPU利用率并不高

# 定位思路

分析这类线程异常问题,最直接有效的方法是查看线程的 dump
根据dump极有可能是线程池设置不合理导致,查看线程池 cachedTreadPool 的定义,发现定义如下:

核心线程数为 cpu 的数量2倍,最大线程数为 cpu 的数量乘以配置的数量,任务队列为 LinkedBlockingQueue,也就是最大数量为 Integer.MAX_VALUE,对线程池了解的话,这样的设置会导致线程池的任务堆积。因为线程池默认实现是核心线程数满了之后,再填充任务队列,如果线程数量小于最大线程数再创建线程。而这儿设置的任务队列几乎是无界的,也就是说这个线程池真正工作的线程只会是 cpu 的数量的 2 倍。

# 根本原因

由以上分析,http 的请求处理的时候,部分逻辑会并发处理,并发处理过程当中使用到了配置的 cachedThreadPool 线程池,而线程池处理任务的逻辑,核心线程数满了之后,再填充任务队列,然后再创建线程如果线程数量小于最大线程数的话,所以我们系统里面的很多线程其实是在任务队列里进行排队,导致 http 线程挂起,通过 threaddump 也可以分析出来只有 cpu 数乘2个,任务都在排队

# 解决方案

线程池分级
1.核心线程池 队列:SynchronousQueue
2.非核心线程池 队列:LinkedBlockingQueue

过载保护
1.过载保护的策略
2.tomcat配置中acceptCount,maxConnections的影响
线程池监控

  1. 线程数量的监控
    2.线程创建数量的监控
    3.队列大小的监控

所以就有了
线程池的替代方案