生产问题排查深度话题
CPU 飙高 · OOM · 接口慢 · 死锁 · 前端白屏 · 限流熔断降级
🎬 怎么引出
「线上问题我处理过几个。印象深的是接口 CPU 突然 100%,用 top 找进程 → top -H 找线程 → jstack 看堆栈,定位是一个正则表达式恶意回溯(用户输入特殊字符触发 catastrophic backtracking)。还有前端白屏,Sentry 收到 JS 错误,90% 是某个依赖 CDN 加载失败,加 fallback CDN 解决。生产排查能力是高级工程师的核心竞争力,有故事面试官最爱听。」
1
CPU 飙高排查(经典三连)
📋 三步定位法
# 1. top 找占用 CPU 最高的 Java 进程
top -c
# 假设找到 PID = 12345
# 2. top -H 找该进程里占用最高的线程
top -Hp 12345
# 假设找到线程 TID = 12378
# 3. 线程 ID 转十六进制(jstack 里是十六进制)
printf "%x\n" 12378
# 输出 306a
# 4. jstack dump,搜索这个 nid
jstack 12345 | grep "nid=0x306a" -A 30
# 看这个线程在执行什么代码 → 定位问题
常见原因: ① 死循环/死递归;② 正则回溯爆炸(恶意输入);③ 频繁 Full GC(jstat 看 GC 频率);④ 大计算(加密/序列化);⑤ 锁竞争激烈(线程都在等锁,自旋耗 CPU)。排查就是 jstack 看线程在干嘛。
⚠️ 正则回溯爆炸
真实案例: 用户输入特殊字符串(如一长串重复字符),正则 (a+)+ 这类嵌套量词会触发指数级回溯,单次匹配耗 CPU 100%。解法: ① 避免危险正则(嵌套量词);② 用 RE2 引擎(线性时间,不支持回溯引用);③ 限制输入长度;④ 超时机制。
2
OOM 排查(见专题 16)
流程: ① 配
-XX:+HeapDumpOnOutOfMemoryError 自动 dump;② jmap -dump(MAT 分析);③ 看 Dominator Tree 找大对象;④ 判断是泄漏(修代码)还是溢出(加限流/分页/流式)。详见专题 16。
3
接口慢 / 超时排查
📋 排查思路
- APM 看链路: SkyWalking/Pinpoint 看接口耗时花在哪(网关→服务→DB→下游)
- 慢 SQL: MySQL 慢查询日志,EXPLAIN 看执行计划(是否全表扫/没索引)
- 下游服务慢: 调的第三方/其他服务超时(看 RT)
- GC 停顿: jstat 看 Full GC 频率和 STW 时间
- 网络: ping/telnet/mtr 看网络延迟和丢包
- 连接池: DB/Redis 连接池满,请求排队
常见根因: ① 没索引/索引失效(慢 SQL 最常见);② N+1 查询(循环里查 DB);③ 大表全量查(没分页);④ 下游超时拖垮(级联失败);⑤ GC STW;⑥ 锁等待。
4
死锁排查
📋 Java 死锁
# jstack 会自动检测死锁,看 "Found one Java-level deadlock"
jstack <PID> | grep -A 20 "deadlock"
# 输出会显示:
# "Thread-1" waiting to lock 0x... held by "Thread-2"
# "Thread-2" waiting to lock 0x... held by "Thread-1"
MySQL 死锁:
SHOW ENGINE INNODB STATUS 看 LATEST DETECTED DEADLOCK。预防: 统一加锁顺序、缩短事务、降隔离级别。详见专题 17。
5
前端白屏排查
📋 白屏原因
- JS 报错: 关键 JS 抛异常,Vue/React 挂载失败 → 白屏(看控制台 + Sentry)
- 资源加载失败: CDN 挂了/被墙,JS/CSS 404(看 Network)
- 跨域: 接口 CORS 被拦,数据没拿到(看控制台 CORS 错误)
- 路由配置错: 动态路由没注册,匹配到空白页
- 打包问题: 缓存了旧 HTML + 新 JS(chunk hash 变了找不到)
⚠️ 生产必加:Sentry
线上用户白屏你不会知道(用户不会截图发你)。Sentry 自动捕获 JS 异常,带堆栈和用户环境,90% 白屏能定位。还要配资源加载失败监听(window.onerror + error 事件)。没有监控等于裸奔。
预防: ① ErrorBoundary(React)/ errorCaptured(Vue)兜底渲染;② 资源多 CDN fallback;③ HTML 不缓存(
Cache-Control: no-cache),JS/CSS 长缓存(文件名带 hash)。
6
限流 / 熔断 / 降级(高可用三板斧)
| 手段 | 目的 | 实现 |
|---|---|---|
| 限流 | 控制请求速率,保护系统不被打挂 | 令牌桶(Guava RateLimiter)、Sentinel、Nginx limit_req |
| 熔断 | 下游故障时快速失败,不拖垮自己 | Sentinel/Hystrix,错误率/慢调用阈值触发 |
| 降级 | 核心保住,非核心返回兜底 | 推荐列表失败返回默认推荐、详情失败返回缓存 |
核心思想: 故障隔离,防止级联失败。一个服务挂了,不该把整个系统拖死。限流挡住外部洪峰,熔断快速失败不等待,降级保证核心可用。秒杀/大促必备。
7
高频追问
1线上 CPU 100% 怎么排查? 必问
三步: top 找进程 → top -Hp 找线程 → 线程 id 转十六进制 → jstack 搜 nid 看堆栈。常见原因:死循环、正则回溯爆炸、频繁 Full GC、大计算、锁自旋。看堆栈就知道线程在执行什么代码。
💬 这题答出"三步定位",说明真排过。
2接口突然变慢怎么排查? 高频
① APM 看链路(SkyWalking)定位耗时在哪;② 慢 SQL 日志 + EXPLAIN 看是否全表扫/索引失效;③ jstat 看 GC(Full GC 频繁 STW);④ 下游服务 RT;⑤ 网络延迟;⑥ 连接池满。常见根因:没索引、N+1 查询、大表没分页、下游超时。
3限流熔断降级区别? 高频
限流: 控制请求速率(令牌桶),挡外部洪峰。熔断: 下游故障快速失败(错误率阈值),防级联拖垮。降级: 非核心返回兜底,保核心可用。目的都是高可用 + 故障隔离。实现:Sentinel(阿里,推荐)、Hystrix(停更)、Resilience4j。
4前端线上白屏怎么排查? 中等
① Sentry 看错误(90% 是 JS 异常);② 看 Network 有没有资源 404(CDN 挂);③ 看控制台 CORS;④ 路由配置错。生产必加 Sentry + ErrorBoundary。预防:资源多 CDN fallback、HTML 不缓存 JS 长缓存(文件名带 hash)。
5令牌桶和漏桶区别? 中等
令牌桶: 固定速率产生令牌,请求拿令牌才能过。允许突发(桶里攒的令牌可瞬时用)。漏桶: 请求进桶,固定速率漏出。平滑输出,不允许突发。限流多用令牌桶(Guava RateLimiter、Sentinel)。
6你怎么预防生产事故? 加分
① 监控告警(Prometheus + Grafana + Sentry,提前发现);② 灰度发布(小流量验证再全量);③ 限流熔断(保护系统);④ 压测(上线前发现瓶颈);⑤ 回滚预案(出问题秒回滚);⑥ 复盘(每次事故写 postmortem,沉淀)。不是等出事再排查,是预防。
💬 这题体现工程思维,加分。
8
30 秒陈述
🎤 30 秒版
「线上问题我处理过几次。CPU 100% 用三步定位 — top 找进程、top -H 找线程、jstack 看堆栈,定位过正则回溯爆炸(恶意输入触发)。接口慢用 APM 看链路 + EXPLAIN 看慢 SQL,常见是没索引或 N+1 查询。前端白屏靠 Sentry 自动捕获,加 ErrorBoundary 和 CDN fallback。预防上我主张监控告警 + 灰度发布 + 限流熔断,不是等出事排查而是提前预防。高可用三板斧:限流(令牌桶)挡洪峰、熔断防级联、降级保核心。」