
产生背景
场景:研发团队在重构消息服务,上线需要新消息服务替换老消息服务上线西班牙试点,上线2天之后,发现CPU飙升,系统告警
时间:2025年4月8日,CPU异常再次发生后的会议室
角色:
老张(运维): “李总,小李,今天早上8点,西班牙的msg服务CPU又飙到94%了,和上周的情况一模一样。我重启了服务,暂时恢复正常了。但这已经是第二次了,我们必须找到根本原因,不能每次都靠重启解决问题。”
李总(业务方): “老张,这个问题很严重啊!我们西班牙的试点项目是公司业务扩张的关键,如果CPU问题不解决,上线后可能会影响整个欧洲市场的拓展。小李,你这边有什么进展吗?”
小李(程序员): “李总,老张,我上周排查了日志,发现有几个慢SQL,以为是SQL引起的,已经优化了这些SQL语句。但今天又出现了CPU飙升,看来问题没那么简单。”
老张(运维): “小李,你确定只是SQL的问题吗?我看了监控,CPU飙升的时候,数据库的负载并不高。而且,重启后SQL还在执行,但CPU却恢复正常了。这不太像是SQL引起的。”
小李(程序员): “老张,你说得对,SQL可能不是根本原因。我需要更详细的数据来分析。你能提供CPU飙升时的线程堆栈信息吗?我想看看是不是有死循环或者资源泄漏。”
李总(业务方): “小李,老张,你们别互相推诿了!我们现在时间很紧,业务正在野蛮生长,西班牙试点必须尽快上线。老张,你这边能不能提供更多的监控数据?小李,你需要什么数据直接跟老张说,别浪费时间。”
老张(运维): “李总,我已经把当时的监控数据导出来了,包括CPU、内存、线程堆栈和网络IO。小李,你可以先看看这些数据。另外,我建议我们启用更详细的日志记录,方便下次排查。”
小李(程序员): “好的,老张,我马上分析这些数据。另外,我怀疑是消息服务在处理某些特定消息时出现了问题。李总,你能提供一些最近的消息样本吗?我想模拟一下当时的场景。”
李总(业务方): “小李,消息样本我可以让业务团队提供,但你们必须尽快找到问题。我们不能再拖了,西班牙试点是公司业务扩张的重点,不能因为技术问题延迟上线。”
小李(程序员): “李总,我理解你的担忧。我会尽快分析数据,找到根本原因。老张,我们还需要在测试环境复现这个问题,你能帮忙搭建一个和生产环境一致的测试环境吗?”
分析过程
下面是分析过程,整套分析过程下来,思维清晰,

通过aws发邮件,每次创建client链接,client.sendEmail()方法内未做close操作,用完未关闭,导致内存泄漏GC无法回收,慢慢把内存打满,频繁发生FullGC抢占CPU资源,最终导致CPU异常升高。第一次西班牙重启后,因为西班牙的业务量没有那么大,所以经过几天才打满,CPU第二次异常。虽然美国业务量大很多,由于配置高又是双机,所以坚持了2天才爆出问题。
解决方案
经验总结
相关技术分享
部分SDK使用分享
1.aws发送邮件send()后没有主动做close操作,需要使用者自己手动调client.close()关闭
2.阿里的smtp发送SDK里面有做关闭链接操作
3.WhatsApp发送send()里面有做close操作
4.腾讯云发送send()里面有做close操作