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

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

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

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. 死锁优先重启止血,再从资源申请顺序与锁设计根治。

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

相关推荐
无巧不成书02182 小时前
Java核心技术全景解析:从白皮书到实战踩坑
java·开发语言
Roy_Sashulin2 小时前
基于AI的Java编程平台
java·开发语言·人工智能·sashulin·deepseek
大傻^2 小时前
Spring AI Alibaba 企业级实战:从0到1构建智能客服系统
java·人工智能·后端·spring·springaialibaba
贼爱学习的小黄2 小时前
NC BIP增加按钮
java
短剑重铸之日2 小时前
《ShardingSphere解读》11 解析引擎:SQL 解析流程应该包括哪些核心阶段?(上)
java·后端·spring·shardingsphere·分库分表
Javatutouhouduan2 小时前
Netty进阶指南:基础+中级+高级+架构行业运用+源码分析
java·netty·java面试·网络io·后端开发·java程序员·互联网大厂
编码忘我2 小时前
java开发模式之静态代理、动态代理、CGLIB代理
java
冬夜戏雪2 小时前
实习面经摘录(八)
java
拾年2752 小时前
别再让 NullPointerException 搞崩你的代码了!Optional + Stream 组合拳详解
java