线上常见问题案例和排查工具分析

线上常见问题案例和排查工具分析
玦尘你必须非常努力,才能看起来毫不费劲。
前⾔
这篇⽂章可以作为参考,⽤来准备⾯试中类似下⾯的提问:
你在做这个项⽬的时候遇到了什么问题?(OOM 问题、GC 问题等等)
你⽤过哪些分析定位 Java 故障/性能的⼯具?(JDK ⾃带⼯具、MAT、Arthas 等等)
如果项⽬遇到了 OOM 问题,你会如何排查?(常⽤ MAT)
有什么办法可以监控到 JVM 的实时运⾏状态?(Arthas)
⽣产环境有⼀个接⼝很慢,如何排查?(Arthas)
CPU100%,你是怎么处理的?(jstack 或者 Arthas)
你是如何定位线上问题的?(说说⾃⼰了解的⼯具,然后根据⾯试官提示继续深⼊聊即可)
项⽬中遇到了哪些线上故障,你是如何解决的?
……
面试高频,一步一步解决OOM、GC调优:
Java
常⽤⼯具
Arthas
Arthas 官⽅⽂档(中⽂,很详细。⽕焰图这块⾯试常问,)
如果⾯试中聊到 Arthas 的话,⾯试官很可能会继续追问你 Arthas 的底层实现原理。
MAT
JDK⾃带⼯具
基础
不规范的枚举类代码引发的⼀场事故 - 阿⾥云开发者 - 2023
现象:对象的状态属性(枚举类型)在插⼊数据库后丢失,变成了空⽩字符串。
分析:通过 Arthas watch 命令发现 PayRequest 对象在转换过程中 status 属性丢失。
原因:直接原因:枚举类 Status 提供了 setter ⽅法,违反了枚举使⽤规范。根本原因:第三⽅库 podam 在解析枚举类时,错误地通过反射调⽤了 setter ⽅法。
建议:⾸要的是写代码还是要注意规范,最好本地装⼀些扫描⼯具,例如 sonar,发现⻛险⼀定要尽快按照建议修复。
⼀⾏ MD5 居然让⼩伙伴都回不了家! - 京东云开发者 - 2023
现象:测试环境中,⾸次请求超时,后续请求迅速返回。
分析:使⽤ Arthas trace 命令查看⽅法耗时。
原因:Hutool ⾃带的 MD5 算法使⽤存在问题(第⼀次加载很慢),使⽤ Google 提供的MD5 算法成功解决问题。
建议:使⽤第三⽅包的时候要⼩⼼,尤其是没有⼤公司背书的第三⽅包。
多线程
- ⼀次棘⼿的线程池使⽤不当导致的⽣产问题 - why 技术 - 2022(分析问题的思路超赞):拒绝策略使⽤不当,由严选技术的⼀个线程池拒绝策略引发的⾎案这篇⽂章引申⽽来。
- 线程池运⽤不当的⼀次线上事故 - IT ⼈的职场进阶 - 2021:⽗任务和⼦任务共⽤⼀个线程池导致的死锁问题。
- 记⼀次因@Async 引发的程序 bug - Linyb 极客之路 - 2022:
Controller
加了@Async
异步就失效了,不会被 MVC 进⾏映射处理,这样就导致了 404 的问题。推荐的解决⽅法是将@Async
逻辑抽离出Controller
,新建⼀个 Service 类进⾏处理。
- 详解⼀次由读写锁引起的内存泄漏 - Coder 的技术之路 -2021:为了实现 LRU 功能,通过重写
LinkedHashMap
的get()
⽅法,在 get 之后,将当前节点移动到链表最后。因此,即使是 get 操作,其实际依然是⼀个写操作。所以,不应该使⽤读写锁,⽽应该使⽤互斥锁。还是更推荐的还是使⽤分布式缓存或者 Guava 缓存、Caffeine 这些⽐较完善的本地缓存的实现。
常⻅⽣产问题
CPU使⽤率⾼(重要)
相关⾯试题:
- CPU100%,你是怎么处理的?
- 线上服务 CPU100% 问题,如何快速定位?
- CPU 占⽤情况如何分析?
解决 CPU 使⽤率⾼的常⽤⼯具:
jvm ⾃带的⼯具 jstack:使⽤
top
命令定位⾼ CPU 占⽤线程,再使⽤jstack
命令查看线程栈信息。阿⾥开源的全能的故障诊断⼯具 Arthas(更推荐):
dashboard
命令查看 TOP N 线程,thread
命令查看堆栈信息。内部集成的⽕焰图⼯具 async-profiler
利⽤ jstack 解决线上服务 CPU 100% - HeapDump - 2021
现象:钉钉告警:CPU 超过告警阈值,达 100%;客户反馈:系统登录失败,报 504 错误。
分析:使⽤
top -Hp <进程ID>
定位⾼ CPU 占⽤线程,再使⽤jstack <进程ID> > jstack.txt
查看线程栈信息建议:对于此类耗资源的操作,⼀定要做好相应的限制。⽐如可以限制请求量,控制最⼤分⻚⼤⼩,同时可以限制访问频率,⽐如同⼀⽤户⼀分钟内最多请求多少次。
⽤ Arthas 解决线上正则表达式导致 CPU100%的问题 - 掘⾦ - 2023
现象:⼀个服务出现了 cpu 达到 100%的问题。
分析:使⽤ arthas 查看线程信息,输⼊
thread -n 10
,列出 10 个占⽤ cpu 最⾼的线程堆栈信息。
不经意的两⾏代码把 CPU 使⽤率⼲到了 90%+ - HeapDump - 2023
现象:应⽤使⽤ schedulerx 执⾏定时任务,每⼩时执⾏⼀次,每次约 5 分钟,执⾏任务期间 CPU 使⽤率 90%+。
分析:Arthas 内部集成的⽕焰图⼯具 async-profiler ⽐较适⽤ CPU 使⽤率持续较⾼的场景。通过对热点⽕焰图的分析, NoSuchMethodException
异常相关代码占⽤了很多 CPU时间。为了更准确的定位相关业务代码,我们需要知道抛出 NoSuchMethodException
的线程栈,可以使⽤ Arthas stack,从线程栈我们可以知道在【哪个类哪个⽅法哪⾏】发出的调⽤。
OOM/内存泄露(重要)
相关⾯试题:
- 如果项⽬遇到了 OOM 问题,你会如何排查?
- 你遇到过 OOM 问题吗?最后怎么解决的?
解决 OOM/内存泄露的常⽤⼯具:
JDK ⾃带的 VisualVM:使⽤
jmap
命令⽣成堆转储快照也就是 dump ⽂件,然后通过VisualVM 分析 dump ⽂件。MAT (Memory Analyzer Tool):MAT 也可以分析 dump ⽂件。
阿⾥云开发者发表过⼀篇三万字⻓⽂:JVM内存问题排查Cookbook - 2024,堪称应⽤内存问题排查保姆级指南。不过,这篇写的过于详细,实际⾯试中是需要介绍这么详细的,直接针对⾃⼰项⽬遇到的问题去介绍即可。
现象:线上某个服务有接⼝⾮常慢,通过监控链路查看发现,中间的 GAP 时间⾮常⼤,实际接⼝并没有消耗很多时间,并且在那段时间⾥有很多这样的请求。
分析:使⽤ JDK ⾃带的
jvisualvm
分析 dump ⽂件。建议:对于 SQL 语句,如果监测到没有
where
条件的全表查询应该默认增加⼀个合适的limit
作为限制,防⽌这种问题拖垮整个系统资料:实战案例:记⼀次 dump ⽂件分析历程转载 - HeapDump - 2022。
⽣产事故-记⼀次特殊的 OOM 排查 - 程语有云 - 2023
现象:⽹络没有问题的情况下,系统某开放接⼝从 2023 年 3 ⽉ 10 ⽇ 14 时许开始⽆法访问和使⽤。
临时解决办法:紧急回滚⾄上⼀稳定版本。
分析:使⽤ MAT (Memory Analyzer Tool)⼯具分析 dump ⽂件。
建议:正常情况下,
-Xmn
参数(控制 Young 区的⼤⼩)总是应当⼩于-Xmx
参数(控制堆内存的最⼤⼤⼩),否则就会触发 OOM 错误。
⼀次⼤量 JVM Native 内存泄露的排查分析(64M 问题) - 掘⾦ - 2022
现象:线上项⽬刚启动完使⽤ top 命令查看 RES 占⽤了超过 1.5G。
分析:整个分析流程⽤到了较多⼯作,可以跟着作者思路⼀步⼀步来,值得学习借鉴。
建议:远离 Hibernate。
GC问题
记⼀次 CMS GC 耗时 46.6 秒的 排查与解决过程 - 掘⾦ - 2023
现象:HTTP 接⼝请求延时过⾼。
分析:使⽤ MAT (Memory Analyzer Tool) ⼯具分析 dump ⽂件(⽼套路了)。
建议:监控⼯具⾮常重要,SQL 语句的编写需要谨慎。
YGC 问题排查,⼜让我涨姿势了! - IT ⼈的职场进阶 - 2021
现象:⼴告服务在新版本上线后,收到了⼤量的服务超时告警。
分析:使⽤ MAT (Memory Analyzer Tool) ⼯具分析 dump ⽂件。
建议:学会 YGC(Young GC) 问题的排查思路,掌握 YGC 的相关知识点。
听说 JVM 性能优化很难?今天我⼩试了⼀把! - 陈树义 - 2021
通过观察 GC 频率和停顿时间,来进⾏ JVM 内存空间调整,使其达到最合理的状态。调整过程记得⼩步快跑,避免内存剧烈波动影响线上服务。 这其实是最为简单的⼀种 JVM 性能调优⽅式了,可以算是粗调吧。
你们要的线上 GC 问题案例来啦 - 编了个程 - 2021
案例 1:使⽤ guava cache 的时候,没有设置最⼤缓存数量和弱引⽤,导致频繁触发Young GC
案例 2: 对于⼀个查询和排序分⻚的 SQL,同时这个 SQL 需要 join 多张表,在分库分表下,直接调⽤ SQL 性能很差。于是,查单表,再在内存排序分⻚,⽤了⼀个 List 来保存数据,⽽有些数据量⼤,造成了这个现象。
Java 中 9 种常⻅的 CMS GC 问题分析与解决 - 美团技术团 - 2020
这篇⽂章共 2w+ 字,详细介绍了 GC 基础,总结了 CMS GC 的⼀些常⻅问题分析与解决办法。
数据库
MySQL
死锁问题(重要)
⼿把⼿教你分析解决 MySQL 死锁问题 - 后端元宇宙 - 2024
⽣产环境中,MySQL 死锁还是挺常⻅的,⾯试被提问的概率也较⼤。这篇⽂章详细介绍了
MySQL 死锁问题该如何排查和解决。
解决 MySQL 死锁问题的思路:
- 使⽤
show engine innodb status;
查看死锁⽇志,然后分析死锁⽇志。 - 如果第⼀种⽅式⽆法解决死锁问题,可以通过 binlog ⽇志获取锁事务所执⾏的全部SQL。有了具体 SQL 语句,就能进⾏具体的锁冲突分析了。
类似的⽂章:
时区问题
⼀个诡异的 MySQL 查询超时问题,居然隐藏着存在了两年的 BUG - CoderW 喜欢写博客 -2021
时区没对上 :SQL ⽇志记录⾥⾯的时区都是标准时区,任务执⾏的时候是北京时间,标准时区和北京时区是差了 8 个⼩时。
底层在取时间区间时,调了⼀个 RPC 接⼝,这个接⼝预期返回的时间区间只有⼏天,结果返回了七个⽉的时间区间。查询的⽇期区间从 2020 年 9 ⽉到 2021 年 4 ⽉,时间跨度7 个⽉。MySQL 成本计算的时候认为区间太⼤,⾛索引还不如直接扫描全表,最终没有⾛索引扫描了 1800W 条数据。
慢查询
慢查询引发的⻋祸现场,案例分析! - ⽉伴⻜⻥ - 2021
分享了⼏个导致慢查询的案例。
隐式转换
⼀个 MySQL 隐式转换的坑,差点把服务器整崩溃了 - 古时的⻛筝 - 2022
我们在平时的开发过程中,尽量要避免隐式转换,因为⼀旦发⽣隐式转换除了会降低性能
外, 还有很⼤可能会出现不期望的结果。
事务隔离级别错误
MySQL 可重复读,差点就让我背上了⼀个 P0 事故! - 楼下⼩⿊哥 - 2020
真实事件,交易系统,p0 事故:余额多扣!
Redis
Redis 主从切换导致的数据丢失与集群陷⼊只读状态故障。事故最后的原因很简单,运⾏配置和静态配置不⼀致导致的。修改配置时,切记分析清楚,到底是要永久性的,还是⼀次性的。
Redis——由分布式锁造成的重⼤事故 - 浪漫先⽣ - 2020
分布式锁使⽤不当导致超卖。
消息队列
Kafka
⼀次 Kafka 消息堆积问题排查 - 张乘辉 - 2020
项⽬中某 Kafka 消息组消费特别慢,有时候在 kafka-manager 控制台看到有些消费者已被踢出消费组。该消费组在短时间内重平衡了 600 多次。
RabbitMQ
RabbitMQ 消息延迟和堆积实战 - 菜农⽈ - 2021
消息延迟 :TTL + 死信队列(⽐较麻烦)、RabbitMQ 延迟队列插件(更简单,相关阅读:[RabbitMQ 延迟插件的使⽤](https://mp.weixin.qq.com/s/rFN_MkEIyeUbmttwdN-YGw)
消息堆积解决:增加消费者、多线程、扩⼤队列的容量、惰性队列(更灵活但消息的时效性降低,接收到消息后直接存⼊磁盘⽽⾮内存,⽀持百万级消息的存储)
⽹络
万字⻓⽂让你掌握⽹络问题排查技巧! - 安琪拉的博客 - 2021
⽹络问题很考验⼯程师解决问题的功⼒,这类问题需要对 TCP 的原理,抓包⼯具有⽐较深⼊的理解和运⽤,这篇⽂章以实战⻆度为你讲述了⽹络问题的排查思路,⾮常值得⼀看!