平稳运行半年的系统宕机了,记录一次排错调优的全过程!

简介: 最近发生了一件很让人头疼的事情,已经上线半年且平稳运行半年系统在年后早高峰的使用时发生了濒临宕机的情况。访问速度特别慢,后台查到大量time_wait的连接,从代码层面到架构层面到网络层面排查了几天几夜,总算是有了结果。

听说微信搜索《Java鱼仔》会变更强哦!


本文收录于JavaStarter ,里面有我完整的Java系列文章,学习或面试都可以看看哦


(一)前言


最近发生了一件很让人头疼的事情,已经上线半年且平稳运行半年系统在年后早高峰的使用时发生了濒临宕机的情况。访问速度特别慢,后台查到大量time_wait的连接,从代码层面到架构层面到网络层面排查了几天几夜,总算是有了结果。


(二)架构、问题描述


先简单描述一下这个系统的架构,公网域名对应的公网IP连接着华为云的ELB弹性负载均衡服务,ELB下是两台Nginx服务器多活,Nginx下连接着四台内网应用集群服务器(通过专线),Mysql服务器读写分离、Redis服务器主从配置。


发生宕机问题时,四台集群服务器的Load Average飙到了200,要知道8核的服务器Load average超过40就需要注意了。同时Nginx的tcp连接数也异常,有大量的TIME_WAIT连接。


网络异常,图片无法展示
|


(三)问题排查


这个问题主要原因还是系统挡不住突然间的高并发,根据上面的这些报错数据,首先是想办法把load average降下去。请求大于当前的处理能力,会出现等待,引起load average升高。因此主要从下面几个方面进行了排查:


3.1 检查Nginx配置


首先是运维人员检查Nginx配置,看看是否是配置不对造成大量time_wait连接,检查结果是没有问题。


3.2 抓网络请求


运维人员帮忙抓取了应用服务器在高并发时的网络包,最后分析下来有一个接口的请求次数是所有请求的40%。这是一个疑问点,这个请求为什么会被调用如此多的次数。


3.3 检查线程堆栈信息


因为请求数量如此多,因此需要检查占用CPU最高的线程堆栈信息,最后发现垃圾回收线程竟然占用了30%+资源,说明垃圾回收应该是存在一些问题的。


网络异常,图片无法展示
|


3.4 检查数据库连接池


检查数据库连接池是否正常,看看有无死锁或者资源耗尽等问题,查出来是一切正常的。


3.5 检查垃圾回收情况


通过jstat -gcutil 命令抓取垃圾回收情况,发现YGC很频繁,大概一秒一次,下图是高峰期过了之后的垃圾回收情况,YGC大概在一分钟8次左右。因此也是怀疑业务代码存在问题。


网络异常,图片无法展示
|


(四)定位业务代码


通过上面的信息,我们初步怀疑那个被频繁调用的接口存在问题。查到代码后,发现每次刷新页面的时候,都会调用这个接口7次,这种调用太频繁了。同时代码中发现了大量JSON转换、序列化的情况,查了一些资料后发现这种行为确实会导致YGC频繁操作。


于是优化代码逻辑,刷新页面的时候调用一次接口就行,数据一次性传给前端,而不是多次调用。同时将没有必要的JSON转换代码优化掉。按理说现在的性能应该可以提升不少。打包、上传、重新观察。


(五)问题还是存在


平稳了4天,在周五早晨高峰的时候,运行缓慢、负载高的情况又发生了。这下傻眼了,难道是有其他地方没有检查到吗。


这时想到一个问题,明明一直没有动这些服务器,为什么平稳运行了半年后突然出现问题,于是往其他方面去想,怀疑是从公网IP进来到应用服务器中的某条链路存在问题。于是尝试着断掉公网链路,去压测放在内网的这些应用,竟然不会出现之前的问题。


于是检查公网到内网的专线网络请求情况,发现出口带宽最高就只能到200M,就是早高峰的时候,而当时买的专线带宽是可以到500M的。因此怀疑是带宽满了导致请求进不来堵塞在公网的Nginx服务器上,而用户发现运行缓慢后频繁去刷新,导致大量的Tcp连接time_wait。于是赶紧联系相关服务商对网络带宽情况进行检测,果然500M的带宽直接打了折扣,联系相关人员处理这方面的问题。


同时一些静态资源放在私有云的服务器上也会导致网络流量大,将这些静态资源分离到公有云的Nginx服务器上,来降低这条专线的网络压力。


(六)后续措施


后续观察来看,问题应该是解决了,当时发生宕机时,是用户反馈上来的,这一点很不合理,后续需要做好服务的监控等各项措施。同时在整体的排查问题时,也解决了一些虽然不是问题根源,但也需要优化的地方。


我是鱼仔,我们下期再见!



相关文章
|
28天前
|
SQL 存储 监控
实用技巧:排查数据异常/数据波动问题,该如何下手?
在我做开发的这些年,让我很头痛的一类问题,不是线上故障,而是数据异常,不知道有没有程序员跟我感同身受。大多数的服务故障都有较为直观的异常日志,再结合产品表象,相对排查起来还有迹可循,但数据异常的原因就太多了,很多时候连报错日志都没有,排查起来简直无从下手。
实用技巧:排查数据异常/数据波动问题,该如何下手?
|
SQL 监控 网络协议
线上故障如何快速排查?来看这套技巧大全
有哪些常见的线上故障?如何快速定位问题?本文详细总结工作中的经验,从服务器、Java应用、数据库、Redis、网络和业务六个层面分享线上故障排查的思路和技巧。较长,同学们可收藏后再看。
线上故障如何快速排查?来看这套技巧大全
|
1月前
|
监控 数据安全/隐私保护 iOS开发
服务器监控新利器:ServerBee带你看透服务器运行状态
服务器监控新利器:ServerBee带你看透服务器运行状态
41 0
|
缓存 JSON 运维
如何避免大规模线上故障
如何避免大规模线上故障
116 0
|
SQL Java 数据库连接
线上运行的项目突然变得很卡如何排查?
线上运行的项目突然变得很卡如何排查?
|
SQL 固态存储 关系型数据库
经典案例:磁盘I/O巨高排查全过程(1)
经典案例:磁盘I/O巨高排查全过程
261 0
经典案例:磁盘I/O巨高排查全过程(1)
|
缓存 IDE Java
在被线上大量日志输出导致性能瓶颈毒打了很多次之后总结出的经验(上)
在被线上大量日志输出导致性能瓶颈毒打了很多次之后总结出的经验(上)
在被线上大量日志输出导致性能瓶颈毒打了很多次之后总结出的经验(上)
|
存储 监控 Java
在被线上大量日志输出导致性能瓶颈毒打了很多次之后总结出的经验(中)
在被线上大量日志输出导致性能瓶颈毒打了很多次之后总结出的经验(中)
在被线上大量日志输出导致性能瓶颈毒打了很多次之后总结出的经验(中)
|
存储 Prometheus 监控
在被线上大量日志输出导致性能瓶颈毒打了很多次之后总结出的经验(下)
在被线上大量日志输出导致性能瓶颈毒打了很多次之后总结出的经验(下)
在被线上大量日志输出导致性能瓶颈毒打了很多次之后总结出的经验(下)
|
负载均衡 Java 微服务
从JVM角度思考--如何预估线上环境机器资源大小
如何给JVM虚拟机巧妙地设计参数对大部分开发来说一直是个随缘的事情,可能是去网上拷贝一套参数,可能是沿用公司其他应用的参数。但是这个随缘的操作可能就会给未来留下隐患。给JVM分配的内存过大倒是没什么问题,无非浪费点资源,但是如果分配的内存过小,就有可能导致频繁的Full GC,给人一种系统一直很卡的感觉。这篇文章就通过一个实例分析一下如何结合场景设置JVM虚拟机参数。 当然,本文更重要的是希望能通过预估参数的这个过程,让你更加了解虚拟机内部的一些东西,要想最准确的参数设置,用一些工具记录下JVM各个区域的变化会更有效。