一次线上 cpu 过高问题
> 最近新项目刚上线,所以一直比较留心观察服务器各相关的性能问题
### 项目第一天上线
- 问题描述
- 遇到服务器响应过慢
- 前端频繁的提示超时
- java.lang.OutOfMemoryError: Java heap space
- 解决分析思路
- 调整-Xmx1024m -Xms128m
- 看下日志输出,发现正在狂输出日志,不到半天日志文件竟然达到 10G,优化不必要的日志输出,毕竟是小公司没有专门的运维 elk 等支撑
- 根据前端调用返回耗时地方接口,重点分析之后,发现频繁的内部循环调用,采用必要的前端缓存和服务端 redis 缓存来减少压力
- 再者基于上面接口耗时长的地方,重点分析发现 sql 执行了多表关联,没有走到索引耗时很长,优化 sql 同时增加必要的索引
- 效果
- 上面情况,稍微有所成效了,终于冲以前的耗时 3s 到 30ms 到几百 ms 的耗时
### 过了几天观察,发现服务器 cpu 和 mysql 实例 cpu 过高
- 问题描述
- 开始没有考虑过多,mysql 性能配置阿里云为 2 核 4G,redis 是 2G,服务器是通过阿里云 slb 负载 10M 带宽,内部服务器是两台 8 核 16G 配置
- 虽然是 8 核 16G 配置,但是上面部署了接近 10 个 java 实例应用
- 解决分析思路
- 扩展服务器,将 pc 端和 app 端,从入口切分出不同的服务器,减少过于集中访问的压力问题
- 由于采用读写分离,开始想着快速上线使用,采用异步 xxl-job 任务,出现问题就是集中访问读给 mysql 带来压力,后面调整为异步结合 rabbitMQ,带来效果就是分散,削峰
- 继续优化 sql 语句,调整过度依赖 mybatis plus 查询方式,改由 mybatis.xml 原始 sql 语句模式
- 扩展 mysql 配置为 4 核 8G
- 效果
- 服务器整体明细平稳
- 读写的中间时效性,也同步解决了,之间由于是任务,中间需要等待几分钟,怕任务频繁带来更多压力
- ![avatar](https://kcnf-open.gitee.io/wiki/20201228/20201228170515.png)
- ![avatar](https://kcnf-open.gitee.io/wiki/20201228/20201228170529.png)
### 发现 pc 端的两台服务器突然 cpu 居高不下
- 问题描述
- 前端调用接口耗时,超过 1s
- ![avatar](https://kcnf-open.gitee.io/wiki/20201228/20201228170157.png)
- ![avatar](https://kcnf-open.gitee.io/wiki/20201228/20201228170323.png)
- ![avatar](https://kcnf-open.gitee.io/wiki/20201228/20201228170252.png)
- 解决分析思路
- 开始怀疑是新版本问题,最近都一直比较平稳,看了下新功能数据时间,并没有这个时间内操作
- 根据接口日志分析,怀疑是不是其他应用再调用 mysql 和 mongdb,造成压力,结果表现都很平稳
- 最终都指向是这两台服务器居高不行,采用 top,发现其中一个 java 实例 cpu 一直过高
- 百度一把接着一阵命令输入分析
- top 看具体那个进程 cpu 过高
- top -H -p pid 查看
- /usr/local/jdk1.8.0_241/bin/jstack 20342 > /usr/local/dd.txt 下载具体的 dump 日志
- 最后发现几个过高的 cpu 线程,都指向是 GC 线程 啊,盲区,但是根据 dump 大概能联想区域了
- 后面再仔细根据时间点分析发现和 error 日志文件提示请求超时,接口指向其中一个功能,分析入参和代码结果非空未做拦截,居然全表查询 10w 以上的数据循环计算,啊,眩晕,单单一次调用就输出 40M 的日志,神了
- 赶紧的重启应用,抓紧补丁上去,完美解决
版权声明: 本文为 InfoQ 作者【kcnf】的原创文章。
原文链接:【http://xie.infoq.cn/article/4f7f6f249b3aa41f20cdbb730】。文章转载请联系作者。
评论