$kernelink route --hydrate --safe

页面加载 /
跳到正文
22.md
workspace / posts
~/posts/22.md 阅读中

微服务线程数暴涨10倍P0故障排查:从32000线程告警到根治

CASE STUDY

微服务线程数暴涨10倍P0故障排查

从32000线程告警到根治,一次Spring Cloud生产事故复盘 · IT中华技术日记

生产服务器突然告警:创建线程总数超过32000个,服务濒临崩溃。本文复盘一次真实的P0故障,从线程组成分析到逐层治理,给出可直接落地的配置代码。

一、故障现场

某微服务节点线程总数达到 5000+,监控告警提示创建线程总数逼近 32000 上限。服务框架栈如下:

  • Spring Boot 2 + Spring Cloud
  • 服务间 Feign 调用 + Ribbon + Hystrix
  • Undertow 容器 + MyBatis-Plus + Redis + RabbitMQ
  • 自定义线程池与 @Async 混用

二、线程组成拆解

一个 Spring Cloud 微服务的线程数大致等于以下各项之和:

总线程数 ≈
Undertow Worker 线程
+ Feign 调用线程池 / HTTP 连接池线程
+ Hystrix 线程池(THREAD 隔离策略)
+ RabbitMQ Listener 线程池
+ Redis 连接池(Lettuce Netty EventLoop)
+ 业务线程池(@Async / 自定义 ThreadPool)
+ Spring 内部线程 + JVM 系统线程

告警时的统计:

  • NIO 线程:1000(达到设置上限)
  • 普通 thread 线程:2000+(未使用线程池,无限创建)
  • Hystrix 线程:3000+(配置未生效)
  • 数据库连接、Redis、MQ 线程:少量

三、三大元凶

3.1 Undertow 设置过大

Worker 线程数配到了 1000,而 8 核节点通常 IO 线程 8 个、Worker 线程 512 个已经足够。改成按 CPU 核数配比:

server:
undertow:
threads:
worker: 512 # CPU核数 * 8
io: 8 # CPU核数
buffer-size: 1024
direct-buffers: true

3.2 业务代码未使用线程池

大量异步任务直接用 new Thread() 或默认 @Async,没有线程池兜底,导致线程无限膨胀。正确做法是统一配置 ThreadPoolTaskExecutor:

@Configuration
@EnableAsync
public class ThreadPoolConfig {
@Bean("businessExecutor")
public ThreadPoolTaskExecutor businessExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(20);
executor.setMaxPoolSize(50);
executor.setQueueCapacity(200);
executor.setThreadNamePrefix("biz-");
return executor;
}
}

3.3 Hystrix 线程池配置未生效

Hystrix 默认使用 THREAD 隔离策略,每个 Feign Client 都会创建一个独立线程池。如果依赖了 10 个下游服务,默认就会创建 10 个线程池;每个 coreSize=100,仅 Hystrix 一项就能占满 1000 个线程。

hystrix:
threadpool:
default:
coreSize: 10
maxQueueSize: 50
queueSizeRejectionThreshold: 50
base-server: # 可为特定服务单独覆盖
coreSize: 20
maxQueueSize: 100
command:
default:
execution:
isolation:
strategy: THREAD
thread:
timeoutInMilliseconds: 5000

关键认知hystrix.threadpool.default 是模板,不是全局共享池。每个 Feign Client 都会按这个模板独立初始化自己的线程池。10 个下游服务就是 10 份资源。

四、其他组件配置参考

4.1 Druid 数据源

spring:
datasource:
druid:
initial-size: 5
max-active: 20
min-idle: 5

4.2 Redis Lettuce 连接池

spring:
redis:
lettuce:
pool:
max-active: 16
max-idle: 8
min-idle: 4

4.3 RabbitMQ Listener

spring:
rabbitmq:
listener:
simple:
concurrency: 5
max-concurrency: 20
prefetch: 10
acknowledge-mode: auto

五、IT中华观点

微服务线程问题往往不是某个单点,而是「容器 + RPC + 线程池 + 连接池」层层叠加的结果。排查时要先画出线程组成全景,再按占比从高到低治理。配置时牢记一个原则:没有边界的资源,最终都会变成故障。

关于 IT中华

IT中华(www.itzh.vip)持续记录技术实战与踩坑经验。关注 IT中华,获取更多系统架构、性能排查与自动化实践。

本文转载自博客园并改写,仅供学习交流。

comments.cmd 可写入
guest@kernelink:~/posts/22$ comment --compose
identity.env 访客信息
插入 访客会话 Text + UBB · UTF-8 · LF 0 字符