线程池:故障梳理总结

简介: 歌曲提供她

背景

团队新同学反馈想学习了解线程池类的故障,由笔者做梳理和分享(所梳理的故障材料来自团队多年积累的故障复盘报告),内容对外部开发者来说也有借鉴意义,因此发出来希望能帮助到一些开发者。

我会从故障视角和技术视角两个角度来分析总结,故障视角可以看到现象和血淋淋的教训,而技术视角可以透过现象看到本质更进一步可以看看如何避免。

故障视角

笔者经历了很多大大小小的故障,总结来看确实有很多线程池满导致服务不可用的故障。一般线程池满只是结果,诱因还是系统某个地方慢了,最典型的一类 Case 就是数据库 SQL 慢导致数据库连接池满,数据库连接池满进而导致对外提供服务的业务线程池(如 Dubbo 线程池)满,线程池一旦满了,就大概率无法响应新的请求,或者能响应新的请求但一直在排队无法及时处理请求导致请求耗时增加,在用户侧看来就变成了超时-服务不可用。

下面贴一些典型的常见 Case,开发同学基本一看就懂并不神奇。

数据库相关

热更新

在事务里热更新同一条数据容易引发锁等待造成慢 SQL,常见于一些 update count,update quota 类的业务场景。

  • 故障案例1:某次压测对 DB 产生瞬时 60w+ QPS 的压力,期间同一条数据(更新 count 字段)在事务里大量热点更新导致了行锁争抢产生慢 SQL。
  • 故障案例2:几个大用户高并发操作,其中涉及单条热点数据在事务里的更新,排查发现单次更新耗时高达5-6秒,积压的线程引起 Dubbo 对外服务线程池堆积,最终线程池满导致无法对外服务。
  • 线下模拟测试发现 1200 并发进行热点数据的更新(在特定的数据库版本和配置下),开启事务需要1分钟,不开启事务需要3秒。

大表加字段

DDL 变更有多种方式,最原始的方式会造成锁表问题进而引发大量相关联 SQL 锁等待产生慢 SQL;DDL 变更建议走 Online DDL。历史上出现过的一些锁表的 Case 应该是没有走 Online DDL,也可能当时数据库版本不支持 Online DDL。

  • 故障案例:大表添加字段未采用 Online DDL,在最后阶段会对表加 Metadata Lock 原子锁,使得大量相关 SQL 锁等待产生慢 SQL,进而快速打满应用线程池。

索引没走对(走了主键全表扫描)

常见于 order by id limit 场景,就算 where 条件里的字段有索引还是有可能走全表扫描。可以通过 IGNORE INDEX(PRIMARY),FORCE INDEX(idx_xxx) 等方式来解决。

  • 故障案例:凌晨 3 点多突然收到报警数据库 CPU 100%,排查发现某查询 SQL 走了主键索引触发了全表扫描(SQL 样例为:where a= and b= and c= and d= order by id desc limit 20,当时只有 idx_a_b_e 的联合索引),期间在数据库运维平台手工无差别限流 SQL 有所缓解但很快 CPU 又会飚上来,也尝试了物理删除一些无效数据减少数据量,多管齐下,最后通过临时增加一个 idx_a_b_c_d 新的全字段覆盖的索引止血。

深分页

数据量大时深分页引发慢 SQL 也是个常见的经典问题。解法可以是使用 NexToken 或者叫游标的方式查询,目前阿里云有很多 OpenAPI 已经提供了 NextToken 的查询方式。

  • 故障案例:某账号(数据量巨大)调用某查询接口分页查询引发慢 SQL 导致数据库连接池满进而导致 Dubbo 线程池满无法对外服务,紧急限流该账号对该接口的调用后恢复。

调用量大

故障案例1:故障恢复后,短时间重试待处理任务到单机执行,量太大导致单机线程池满导致服务受损。

  • 解法:系统层面需要做一定的限流策略,单机任务瓶颈时应切换到网格型任务。

故障案例2:压测未预热,直接一次性并发到压测值导致线程池满,导致数据库有很多事务等待的慢 SQL。

  • 解法:压测应按照一定节奏逐步上量,观察系统负载并及时暂定,而不是开局就决战。

其他

故障案例:查询没加 Limit 导致应用 Full GC

  • 该 Case 不涉及线程池满问题,但笔者觉得有一定的代表性因此也分享下。不管是查询还是删除还是更新数据,不管是代码还是日常的 SQL 订正,建议都增加 Limit 来兜底保护自己,缩小影响面。

技术视角

线程池类的故障,一般都是某个地方慢了堵了,从技术角度大多是:

1、远程调用 IO 慢导致耗时增加;

2、计算密集型应用 CPU 飙升导致耗时增加;

3、自定义业务线程池满造成排队等待导致耗时增加;

其中 2 不算常见,笔者也遇到过,发生于某 CPU 密集运算的应用系统,突增的高并发请求引起 CPU 100%;其中 1 比较常见,一般远程调用有:Dubbo、Http、DB、Redis,这些实践中都会使用连接池来与远程服务交互,凡是连接池都是有共性的,有两个需要关注的点:

  • 1、尽量减少远程调用本身的 超时时间 以实现 fast-fail 快速失败。一般是设置 ConnectionTimeout 即握手时间 和 SocketTimeout 即业务执行超时时间。
  • 2、在连接池满了以后,获取新的连接的 超时时间 也需要设置的小一些以实现 fast-fail 快速失败,这个是很容易忽略的一个点。如 Druid 里设置 MaxWait,Http 连接池里设置 ConnectionRequestTimeout。

下面列一下各个连接池需要关注的点。

Dubbo 线程池

1、线程池做好隔离,避免互相影响

  • 如内部运维接口和对外服务的接口做隔离。
  • 对外服务里核心接口和非核心接口做隔离。

2、Dubbo consumer 侧设置 timeout,根据 fast-fail 理念设置的越小越好;provider 侧的 timeout 仅仅是起到声明的效果供 consumer 参考,无实际超时杀线程的作用。

Http 连接池

1、设置 ConnectTimeout、SocketTimeout、ConnectionRequestTimeout

  • 故障案例:某次发布的代码引入了一个 SDK,该 SDK 集成了 HttpClient,但并没有设置 ConnectionTimeout,在某次网络抖动发生时,Http 连接池被迅速打满,进而导致业务线程池满导致服务受损。

2、DefaultMaxPerRoute 太小也容易导致阻塞。

  • 故障案例:某 SDK 默认设置的 128,在某次压测中发现客户端耗时较高,但服务端耗时并无波动,排查后怀疑是 DefaultMaxPerRoute 太小导致的阻塞,调大后问题解决。

数据库连接池 Druid

1、设置 ConnectTimeout、SocketTimeout。

  • 故障案例:凌晨 1 点多收到 API 成功率降低报警,排查发现部分 SQL 执行超时,原因是数据库发生了主备切换,进一步排查发现应用侧对数据库连接池没有设置 SocketTimeout 导致切换前的老的连接不会被超时 Kill 导致相关 SQL 执行超时,直到 900秒系统默认超时后才会断开连接再次重连。

2、设置 TransactionTimeout 即事务超时时间,事务就是一把锁,超时时间越长锁越久,导致不在事务里的相关 SQL 锁等待导致性能差。

  • 故障案例:在某次变更时由于代码有 bug 导致事务未提交,同时由于事务没设置超时时间,导致大量相关 SQL 超时服务受损。

3、设置 Ibatis 的 defaultStatementTimeout、queryTimeout。

4、设置 MaxWait:获取新连接的等待超时时间。

  • 小插曲:之前 Druid 默认设置的 60 秒,后来笔者与作者有过沟通反馈这个默认值太长容易坑大家,后来发现已经改为了 6 秒[1]

自定义线程池

1、线程池设置的队列过长容易造成阻塞影响吞吐。

2、future.get,默认没有超时时间,需显式传入。

  • 故障案例:Dubbo 线程池满报警,排查后发现是业务代码里使用了 future.get 没有设置超时时间,同时线程池的拒绝策略设置的是 DiscardPolicy,会导致在线程池满后新的任务被丢弃时 future.get 阻塞,进而导致 Dubbo 线程池满服务受损。
相关文章
|
敏捷开发 存储 搜索推荐
《阿里巴巴Java开发手册v1.4.0(详尽版)》更新,新增16条设计规约
阿里巴巴集团推出的《阿里巴巴Java开发手册》是阿里巴巴近万名开发同学集体智慧的结晶,以开发视角为中心,详细列举如何开发更加高效、更加容错、更加有协作性,力求知其然,更知其不然,结合正反例,让Java开发者能够提升协作效率、提高代码质量。
740706 3
|
3月前
|
人工智能 自然语言处理 网络安全
零门槛阿里云一键部署 Hermes Agent/OpenClaw +功能拓展攻略
在智能办公与自动化需求爆发的2026年,OpenClaw(前身为Clawdbot、Moltbot)凭借自然语言指令执行、多工具集成、主流大模型兼容等核心优势,成为个人与轻量团队打造专属智能助手的首选工具。与普通聊天机器人不同,它堪称“7×24小时不下班的AI数字员工”,能轻松完成文件处理、日程管理、信息提取、跨工具协同等实操任务,大幅降低重复劳动成本。
252 3
|
10月前
|
自然语言处理 前端开发 安全
别人还在摸索,你用这篇Hoobuy淘宝代购集运系统搭建攻略开拓欧美反向海淘市场!
淘宝代购集运系统为海外用户提供一站式中国电商购物解决方案,集成商品抓取、多语言展示、本地支付、国际物流与订单追踪功能,支持多平台数据同步与合规运营,通过技术整合破解语言、支付、物流难题,助力逆向海淘高效便捷。
|
12月前
|
JSON 文件存储 数据安全/隐私保护
微博超话自动签到神器, 微博自动签到神器app,贴吧微博签到脚本工具助手
核心模块包含超话列表获取和签到功能‌2使用配置文件存储cookies避免硬编码‌1
|
7月前
|
运维 监控 安全
单点登录SSO最佳实践:加强安全性与简化访问流程
单点登录(SSO)技术凭借“一套凭证畅行多个应用”的核心特性,极大简化了用户的登录操作。不过,SSO 在提升便捷性的同时,也将关键系统的访问入口集中化,因此必须落实一系列最佳实践,才能切实守护用户凭证与敏感数据的安全。
239 0
|
12月前
|
机器学习/深度学习 人工智能 自然语言处理
AI 驱动:如何用AI直接生成矢量 Logo? 技术研究与工具选择
AI 技术革新品牌标志设计,通过深度学习分析数据,精准把握市场趋势,智能生成高辨识度 Logo。矢量格式(SVG)确保清晰不失真,适配各类展示场景。AI 工具高效便捷,支持个性化定制,助力品牌快速打造专业视觉形象,成为市场竞争中的有力武器。
680 0
|
机器学习/深度学习 人工智能 算法
《当K12遇上朴素贝叶斯:趣味编程开启AI教育新旅程》
在数字化时代,K12教育迎来新机遇与挑战。编程教育作为培养逻辑思维和创新能力的关键,逐渐融入K12课程。朴素贝叶斯算法以其简单高效的特点,成为理想的入门算法。通过趣味编程如Scratch,结合生活实例、可视化工具和项目实践,激发学生兴趣,降低学习难度,提升其对机器学习的理解和应用能力。这不仅为学生打开人工智能的大门,也为未来科技发展奠定基础。
473 23
|
缓存 算法 C语言
【C++ 标准查找算法 】C++标准库查找算法深入解析(In-depth Analysis of C++ Standard Library Search Algorithms)
【C++ 标准查找算法 】C++标准库查找算法深入解析(In-depth Analysis of C++ Standard Library Search Algorithms)
443 0

热门文章

最新文章