遇到线上问题,第一要务永远不是盲目重启、不是猜原因、不是急着改代码,而是查看日志,定位报错信息。
日志是线上问题的 "黑匣子",包含了问题发生的时间、调用链路、异常堆栈、关键入参出参、数据库执行语句等关键信息。脱离日志的排查基本都是 "盲猜",效率极低且容易误判。
1.1 日志查看的常规路径
- 应用日志:业务异常、NPE、SQL 错误、第三方调用失败
- 网关 /nginx 日志:请求流量、4xx/5xx 状态码、超时记录
- 数据库日志:慢查询、死锁、连接数耗尽、执行失败
- 系统日志:OOM、文件句柄不足、网络异常
1.2 日志排查步骤
- 确定问题发生时间范围,缩小日志检索区间
- 根据报错接口 / 服务名,过滤对应日志
- 定位异常堆栈,找到抛出异常的代码行
- 结合入参、调用链路,复现问题场景
- 判断是代码 Bug、配置错误、依赖故障还是资源瓶颈
只有明确报错类型、触发条件、影响范围后,才能进行下一步处理或优化。
二、接口性能优化:从瓶颈到提速的常用手段
线上最常见的问题之一就是接口响应慢、吞吐量低、高并发下雪崩,这类问题大多与资源使用不合理、逻辑冗余有关。通用优化思路如下:
2.1 增加缓存,减少数据库访问
缓存是提升接口性能最直接、成本最低的手段之一,尤其适用于读多写少的场景。
- 本地缓存:Caffeine、Guava Cache,适用于单机、数据量小、一致性要求不高的场景
- 分布式缓存:Redis,支持高可用、分布式、过期策略、高并发读取
- 缓存思路:热点数据、配置数据、字典数据、用户基础信息提前缓存,避免频繁查询 DB
2.2 添加索引,优化 SQL 执行效率
绝大多数接口慢都源于慢 SQL,而慢 SQL 大多是缺少索引或索引失效导致。
- 为查询条件字段建立合理索引(where、group by、order by 字段)
- 避免左模糊、函数运算、类型隐式转换导致索引失效
- 使用执行计划
explain分析 SQL 执行效率,定位全表扫描 - 大表分页优化:延迟关联、主键分页
2.3 使用多线程池处理 IO 密集型任务
IO 密集型场景(调用第三方接口、文件读写、消息发送、多 DB 查询)适合线程池异步化处理。
- 使用
ThreadPoolExecutor自定义线程池,避免滥用 Executors - 异步并行执行无依赖的多个 IO 操作,显著降低 RT
- 配合 Future/CompletableFuture 实现结果聚合
- 注意线程池参数、拒绝策略、上下文传递、事务一致性
三、常见线上问题深度排查
线上问题类型繁多,其中 CPU 飙升、死锁 是高频且危害较大的场景,下面详细说明定位与解决方法。
3.1 CPU 飙升问题排查
CPU 飙升表现为服务器 CPU 使用率持续 100%,服务响应极慢甚至假死,常见原因:死循环、频繁 GC、复杂计算、大量线程阻塞与争抢。
排查步骤
- 定位高 CPU 进程使用 top 命令找到 CPU 占用最高的进程 PID:
bash
top
- 定位高耗 CPU 线程
bash
top -H -p 进程PID
找到占用 CPU 最高的线程 ID,并转换为 16 进制(用于 jstack 匹配)。
- 导出线程栈
bash
jstack 进程PID > stack.log
在日志中搜索 16 进制线程 ID,定位具体代码行。
- 分析原因
- 死循环:代码逻辑错误,无限循环执行
- 频繁 GC:内存不足、对象创建过多、FullGC 频繁
- 复杂计算:大量正则、递归、加密解密、数据解析
- 锁竞争:大量线程等待锁,导致频繁上下文切换
解决方案
- 修复死循环、优化复杂计算逻辑
- 调整 JVM 参数,优化内存使用
- 优化锁设计,减少锁竞争
- 异步化、限流、削峰,降低瞬时压力
3.2 死锁问题排查
死锁是指两个或多个线程互相持有对方需要的资源,并且互不释放,导致线程永久阻塞,服务无法响应。
死锁典型表现
- 接口持续阻塞不返回
- 数据库层面出现锁等待
- 线程栈中显示
BLOCKED状态并循环等待
快速解决方式
-
紧急恢复:重启服务 在业务影响较大时,重启服务可以快速打破死锁,恢复可用,属于应急止血手段。但重启只能临时解决,无法根除问题。
-
根因解决:开发者调整资源分配从代码层面彻底避免死锁:
- 统一资源获取顺序,避免循环等待
- 避免在事务中嵌套远程调用、长耗时操作
- 使用定时锁(tryLock),避免无限等待
- 减少锁粒度,使用分段锁、无锁编程
- 数据库层面避免长事务,合理设置事务超时
- 通过
jstack或jconsole分析死锁线程,定位代码位置
排查工具
- jstack:直接搜索
deadlock关键字 - jconsole /jvisualvm:可视化检测死锁
- MySQL
show engine innodb status:数据库死锁分析
四、总结
线上问题排查没有银弹,但有固定章法:
- 先看日志,定位异常,这是所有排查的起点;
- 性能问题优先从缓存、索引、异步线程池切入优化;
- CPU 飙升用系统命令 + 线程栈定位代码;
- 死锁优先重启止血,再从资源申请顺序与锁设计根治。
保持冷静、按步骤排查、先恢复再优化,既能最大程度降低业务影响,也能逐步形成自己的线上问题处理体系。