线上问题定位与排查实战:从日志到优化的完整思路

遇到线上问题,第一要务永远不是盲目重启、不是猜原因、不是急着改代码,而是查看日志,定位报错信息

日志是线上问题的 "黑匣子",包含了问题发生的时间、调用链路、异常堆栈、关键入参出参、数据库执行语句等关键信息。脱离日志的排查基本都是 "盲猜",效率极低且容易误判。

1.1 日志查看的常规路径

  • 应用日志:业务异常、NPE、SQL 错误、第三方调用失败
  • 网关 /nginx 日志:请求流量、4xx/5xx 状态码、超时记录
  • 数据库日志:慢查询、死锁、连接数耗尽、执行失败
  • 系统日志:OOM、文件句柄不足、网络异常

1.2 日志排查步骤

  1. 确定问题发生时间范围,缩小日志检索区间
  2. 根据报错接口 / 服务名,过滤对应日志
  3. 定位异常堆栈,找到抛出异常的代码行
  4. 结合入参、调用链路,复现问题场景
  5. 判断是代码 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、复杂计算、大量线程阻塞与争抢。

排查步骤
  1. 定位高 CPU 进程使用 top 命令找到 CPU 占用最高的进程 PID:
bash 复制代码
top
  1. 定位高耗 CPU 线程
bash 复制代码
top -H -p 进程PID

找到占用 CPU 最高的线程 ID,并转换为 16 进制(用于 jstack 匹配)。

  1. 导出线程栈
bash 复制代码
jstack 进程PID > stack.log

在日志中搜索 16 进制线程 ID,定位具体代码行。

  1. 分析原因
  • 死循环:代码逻辑错误,无限循环执行
  • 频繁 GC:内存不足、对象创建过多、FullGC 频繁
  • 复杂计算:大量正则、递归、加密解密、数据解析
  • 锁竞争:大量线程等待锁,导致频繁上下文切换
解决方案
  • 修复死循环、优化复杂计算逻辑
  • 调整 JVM 参数,优化内存使用
  • 优化锁设计,减少锁竞争
  • 异步化、限流、削峰,降低瞬时压力

3.2 死锁问题排查

死锁是指两个或多个线程互相持有对方需要的资源,并且互不释放,导致线程永久阻塞,服务无法响应。

死锁典型表现
  • 接口持续阻塞不返回
  • 数据库层面出现锁等待
  • 线程栈中显示 BLOCKED 状态并循环等待
快速解决方式
  1. 紧急恢复:重启服务 在业务影响较大时,重启服务可以快速打破死锁,恢复可用,属于应急止血手段。但重启只能临时解决,无法根除问题。

  2. 根因解决:开发者调整资源分配从代码层面彻底避免死锁:

  • 统一资源获取顺序,避免循环等待
  • 避免在事务中嵌套远程调用、长耗时操作
  • 使用定时锁(tryLock),避免无限等待
  • 减少锁粒度,使用分段锁、无锁编程
  • 数据库层面避免长事务,合理设置事务超时
  • 通过 jstackjconsole 分析死锁线程,定位代码位置
排查工具
  • jstack:直接搜索 deadlock 关键字
  • jconsole /jvisualvm:可视化检测死锁
  • MySQL show engine innodb status:数据库死锁分析

四、总结

线上问题排查没有银弹,但有固定章法:

  1. 先看日志,定位异常,这是所有排查的起点;
  2. 性能问题优先从缓存、索引、异步线程池切入优化;
  3. CPU 飙升用系统命令 + 线程栈定位代码;
  4. 死锁优先重启止血,再从资源申请顺序与锁设计根治。

保持冷静、按步骤排查、先恢复再优化,既能最大程度降低业务影响,也能逐步形成自己的线上问题处理体系。

相关推荐
OxYGC18 分钟前
[AI工程] Spring AI 第十四篇:Agent 五种模式在 2.0 里怎么写
java·spring·ai·ai编程
code2cat19 分钟前
【随笔】从聊天到调用工具:理解MCP在AI应用中的位置
java·人工智能
2501_9339232527 分钟前
Spring Bean作用域揭秘:单例、原型、请求与会话的区别
java·后端·spring·java-ee
学编程就要猛1 小时前
基于Spring AI 的智能聊天机器人
java·spring ai·chat robot
修炼室1 小时前
Java开发工程师笔试经验贴【高频知识】
java
木井巳1 小时前
【记忆化搜索】最长递增子序列
java·算法·leetcode·深度优先·剪枝·推荐算法
杨杨杨大侠1 小时前
知识库已经有了,Java 程序员还要做什么?Spring AI RAG 实战
java·openai·ai编程
伊信1 小时前
Spring AI 基础学习与应用
java·后端
夜郎king1 小时前
基于 Java + Playwright 实现网站自动访问与数据采集(以腾讯云开发者社区为例)
java·playwright·网页数据获取
Anastasiozzzz1 小时前
重新定义 Agent 基建:Redis 在现代 AI 与智能体系统中的工程实践
java·人工智能·redis·ai