记一次阿里云日志导致的服务宕机

导航

  • 引言
  • 火线告警,访问502
  • 猜测: I/O频繁惹的祸
  • 真相:FullGC突发高频导致程序崩溃
  • 移除阿里云日志,稳了
  • 结语
  • 最后
  • 参考

引言

技术人应该具备系统分析,并快速定位问题的能力。

资深技术人需要具备的核心竞争力有哪些?

  • 系统分析,并快速定位问题的能力
  • 快速地理解需求,转化为流程,架构,并文档输出的能力
  • 有一定的产品设计能力,关键时刻可以纠正不良产品设计
  • 快速组织人干事的能力

这里的每一项能力都很关键,但是最重要的还是拥有第一项能力。

毕竟,解决问题才是关键。

继上次《记一次加锁导致ECS服务器CPU飙高分析》之后,后面又陆陆续续地遇到并解决了一些新的问题。一直想着记录一下,但是终究因为各种原因没能下笔。

今天给大家分享一下阿里云日志引发的服务宕机问题的解决过程。

火线告警,访问502

项目背景介绍

今年Q2我接管了一个Java项目,接口服务是基于SpringBoot技术框架实现的,部署在阿里云的sae上(SAE是一款 Serverless理念的微服务应用框架)。

配置如下:

  • 实例规格: 2Core, 2GiB, 系统盘磁盘空间20GiB
  • 运行实例数: 当前2个实例

监控扩容策略:

  • 应用扩缩触发值:满足 cpu > 66%
  • 应用最小实例数: 2
  • 应用最大实例数: 10

该服务是是TOB业务,服务于2000家小微企业。

这里以2023.9.15日监控数据来看,在工作时段(09:30~18:00),单个实例总TCP连接数平均值约为4K左右。

问题描述

自从进入8月中旬以来,几乎每天都会在报警群里面,收到502告警通知。
这种通常是SAE已经出现自动扩/缩容,导致释放实例出现告警。

每天都会有2~3次报警,可能发生在上午或者下午或者两者都有,让人不厌其烦。

从用户第一的角度,这个老是自动扩容和释放肯定是不友好的。
而B端用户也容易拿这个说事儿,把问题放大。

从技术保障的角度看,这个服务的稳定性是值得商榷的,更不要谈4个9的指标了。

所以,解决服务稳定性是头等大事。

猜测: I/O频繁惹的祸

我连续跟踪了sae的监控日志,并对连续几次扩容时间点的各项指标进行了对比。
初步发现可一个规律: 即每一次触发扩容的cpu飙升,都是伴随着IOPS飙升的。

上图是总体指标,实际上单实例的指标在此之上。

初步断定,程序中可能有功能涉及到磁盘的大量读写,比如文件上传,可能触发了IOPS飙升。

阿里云存储云盘IOPS

IOPS即Input/Output Operations per Second,阿里云服务器存储系统盘IOPS指每秒能处理的I/O个数,IOPS表示块存储处理读写(输出/输入)的能力,单位为次。

部署事务密集型应用,如数据库类应用等典型场景,需要关注IOPS性能,只有挂载到I/O优化的实例时,SSD云盘才能获得期望的IOPS性能。IOPS指标说明:

指标

描述

数据访问方式

总IOPS

每秒执行的I/O操作总次数

对硬盘存储位置的不连续访问和连续访问

随机读IOPS

每秒执行的随机读I/O操作的平均次数

对硬盘存储位置的不连续访问

随机写IOPS

每秒执行的随机写I/O操作的平均次数

顺序读IOPS

每秒执行的顺序读I/O操作的平均次数

对硬盘存储位置的连续访问

顺序写IOPS

每秒执行的顺序写I/O操作的平均次数

于是查看阿里云日志,发现还真有个文件上传接口存在性能问题

有图有真相,这更加让我坚信是这个接口导致的问题。

于是连夜做了性能优化,快速上线。

真相:FullGC突发高频导致程序崩溃

道路是曲折的,前途是光明的。

如果仅仅是优化了上面这个接口就能解决,那这个问题也不值得我为此专门写一篇文章了。

实际情况是,第二天,可恶的502问题又出现了。

一筹莫展之际,同组的有个伙伴,这个项目在我接管之前,他是参与时间最长的开发。
他说可能是FullGC频率太高导致。

JVM监控功能用于监控重要的JVM指标,包括堆内存指标、非堆内存指标、直接缓冲区指标、内存映射缓冲区指标、GC(Garbage Collection)累计详情和JVM线程数等。
详细请查看《JVM监控》

于是我们一起看了监控中jvm的指标,下面我整理的9.11当天的FullGC和YoungGC指标。

经过观察,发现FullGC的频率确实偏高,每分钟大概在2~6次。
可以很明确的判断高频的FullGC是服务自动重启的罪魁祸首。

移除阿里云日志,稳了

在断定是FullGC高频这个根本原因之后,我们也做过一种方案,那就是修改JVM调参。

当然,尝试过几次之后,效果不理想,依然每天都出现502。关于JVM调参这个有兴趣的同学可以自己研究。

Log4j

在抛出我的解决方案之前,请允许我介绍一下Log4j。

Log4j是Apache的一个开放源代码项目,通过Log4j可以控制日志的优先级、输出目的地和输出格式。日志级别从高到低为ERROR、WARN、INFO、DEBUG,日志的输出目的地指定了将日志打印到控制台还是文件中,输出格式控制了输出的日志内容格式。

例如某电商公司,希望通过分析用户行为习惯数据(例如用户登录方式、上线的时间点及时长、浏览页面、页面停留时间、平均下单时间、消费水平等)、平台稳定性、系统报错、数据安全性等信息获取平台的最佳运营方案。

阿里云日志服务提供一站式数据采集与分析功能,帮助客户存储并分析日志。

所以,我们的大部分java项目也使用的log4j这个日志库。

而我的解决方案正好与log4j接入阿里云日志接口相关。

移除阿里云日志

程序中接入阿里云日志,本省就是通过sdk调用接口的过程,即便性能再好的接口,在每分钟3000+次时调用的情况下,也是会暴露出性能的问题。即便阿里云接口抗住了,恐怕我们自己的服务也处理响应不过来。

为啥我会怀疑是阿里云日志的调用问题呢?

恰好我在6月份处理过一个nodeJs项目cpu高的问题。

这个nodeJs项目也是部署在sae上的,是一个群聊的聊天服务器,正常情况下cpu使用率在20%左右,但是在socket连接数大于3k之后,群发消息cpu会急剧飙升。

这个也是我经过差不多一周时间的跟踪,并且在服务器上做了压测复现了的。

而他的最终解决方案就是将程序中阿里云日志服务上报,改成输出到控制台,再由sae再推送给阿里云logstore。

所以,整合了sae 基础监控、JVM指标、阿里云日志网关调用记录,我猜测他们可能本质上属于一类问题。

不管如何,我决定尝试一下。

说干就干,我将Java项目中阿里云日志接口移除,只保留控制台输出。
另外,补充说明一下,只要是输出到控制台日志,sae可以配置logstore,然后转存到指定的阿里云logstore。

令人欣喜的是,第二天,线上没有再报502,连续五天去了,依然稳健。
阿里云日志去除是9.11晚上线的,9.12~9.13两天的jvm监控如下:

从图中可以看到,FullGC的频率始钟控制在1次/min,同时我也统计了单日YongGC的总次数下降了一半。

至此,502的问题总算得以根治。

结语

程序是是有生命的,只要被使用就一定会随着业务的增长,带来新的问题。

解决这些问题的方式很多,一种是升级配置,一种是优化代码。

而很多时候,为了降本增效,我们不得不优化代码。

而这些优化的方式你可以从前辈们的分享中获取,但是很多问题可能是还得自己去摸索。

学习-实践-分享-萃取,周而复始,让知识和经验薪火相传,这也是博客的价值。

希望我的分享能够给你带来帮助,哪怕只是帮你节省了一点点喝咖啡的时间。

最后

这里再啰嗦两句,我们将业务日接入阿里云日志服务,主要是方便后续的日志查询。这个和我们使用ELK搭建日志服务异曲同工。

本文中遇到的问题不是阿里云日志的问题,只是我们的项目接入阿里云日志的方式不太适合当下的场景。我们选择将直接记录改成了异步方式记录,这个有利于降低业务服务器的压力(考虑到我们购买的服务器实例配置太低了,仅有2核2G)。

码字不易,欢迎各位老铁点赞、转发。

参考

posted @ 2023-09-17 21:55  智客工坊  阅读(746)  评论(0编辑  收藏  举报