记一次线上故障处理

前言

下面信息裁剪了一些,有的不确定了就拍脑袋定了,大体情况还是和实际相似。

整体过程

最开始接到告警

一个周六的 9:00 接到钉钉告警A应用线上 499 数量大量增加,

A应用的背景介绍

先说下A应用的背景,我们A应用每天上亿次访问,主要是给别的厂商买接口的,按照各个厂商的调用量收钱,A 应用的实例数有几十个,接入的 nginx 也有 10 个以上,分布在 3 个机房,平均RT时间 15 ms,一般 499 数量多是某个tomcat或者某个机房的资源有问题导致的,这种问题登录我们收集了 nginx 日志的 ELK 平台查看 499 在各个 nginx 还有各个 tomcat 的分布一般就能看出来。
A应用依赖 3 个 RPC(其中一个rpc非常重要),3 个 redis,日志是A应用自己异步打到 kafka。4 个月前A应用做过一个比较大的改动,A应用的日志之前是自己写磁盘,然后通过 filebeat 收集到 kafka ,后来为了简化运维的复杂度,让A应用自己打到 kafka。当时还做了测试:把A应用的一个线上实例连接 kafka 的 hosts 改成一个根本通不了的,A应用起来以后观察了1周,RT 时间和正常的应用实例是基本一致的,所以判断日志打 kafka 是异步而且 kafka 宕机与否不会影响A应用。

初步诊断

这次问题从这两处都没啥明显异常,499 在各个 nginx 还有各个 tomcat 的分布很均匀,没发现异常。因为突然多出来的 499 一般是由于A应用 RT 时间增长导致的,所以问题就变成了为什么A应用 RT 时间会变长,查看平台发现A应用在周四上午 11:00 就增加了,但是当时增加的不明显,RT时间一直再 20ms 以下,周六上午发现的时候 RT 时间已经超过了 50ms,而且还在增长。
然后检查这周的变更记录,这周由于是要放假,所以变更是就有几个,A 应用是周一发了灰度大约10%,周二发了全量。周二周三观察了两天也没有什么异常。还有一些创建 kafka topic 的变更,还有其他一些和A应用没有关系的发版。

从现有信息分析不出结果,联系开发

9:30 从现在的信息分析不出原因在哪里,所以找到负责这个应用的开发,让开发看看 RT 时间为什么这么长,开发反馈是S服务(那个重要的 RPC)调用时间过长,有好多超过 2s 的,A应用正常的平均RT时间就在 15ms 左右,所以我们一起查看S服务是否正常,决定重启一个机房的所有 S 服务实例,但是重启了之后,RT 时间没有改善。

再仔细分析问题

10:30 然后想起了开发说超过 2s 的有很多请求,判断开发说S服务RT时间长的根据是在所有超过 2s 的请求中,A调用S服务 RT 时间最长的,但是如果超过2s 请求的只占总请求的 1%,或者不到 1%,那么说 S 服务的问题,这个逻辑就是有问题的。所以联系开发询问情况,一问才知道他果然只查看了超过 2s 的请求,其他维度的数据(比如所有RT时间的平均耗时,各个机房的 RT 等等)他就没查过,我觉得这次问题是总的RT时间长,我们并不是要查个别请求 RT 时间长的问题,而是为什么总平均 RT 时间超过平时的5倍。
要推翻是否是 S 服务器 RT 时间长导致A应用 RT 时间的假设,我们查看了这周S服务超过1s请求的个数的曲线图,发现这周超过S服务RT时间超过1s的请求个数曲线没有明显变化。所以排除 S 服务的嫌疑。
之后仔细问了开发 A 应用收到 ELK 日志里面调用各个服务的标识,比如 TT 是总耗时,st 是调用S服务,yt 是调用y服务,我们一一查看了所有A应用依赖的各个服务的RT时间在这周的曲线变化,没有发现哪个服务的 RT 时间是周四开始,周六变的很高的,这个过程还发现了一个比较大的问题就是A应用里记录的总RT时间在这周的曲线图变化不明显,总的 RT 时间这周都是不到 20ms,但是 nginx 记录的RT时间此时已经超过100ms了。
11:30 到此为止,发现应用的日志 RT 时间居然和 nginx 记录的RT时间不一致, nginx 的 upstream_response_time 和 request_time 的变化曲线是一致的,所以肯定是应用的 RT 时间变长了,但是为什么应用记录的RT时间是正常的呢?仔细和开发聊了一下他记录的耗时的计算方法,开发表示这个日志都收了一年多了,日志也一直这么打,这么分析,没有出过什么问题,如果不是开发记录日志的问题,那么还能是 nginx 记录日志的问题。。。

问题影响进一步扩大

13:00 查问题已经查了好几个小时,很多三方合作的厂商都打过电话问具体的请求,现在线上影响正在逐步扩大,RT时间还在增长,这时有人反馈最近这几天 kafka 连接超时,问我们 kafka 是不是有问题,我们 nginx 日志有个监控,如果5分钟内一条 nginx 日志都没有就会有告警,所以我们肯定 kafka 是没有问题的。而且经过之前的测试就算 kafka 挂掉A应用的RT时间也不会收影响。

进一步分析问题

13:30 这时候问题就比较难排查,但是如果说 nginx 记录的RT时间还有应用记录的RT时间都没有问题的话,那么问题还能出在哪里呢?机房网络?三个机房不可能同时出问题吧,而且就算出问题,不可能出问题的就只有A应用,不过还是仔细查了一下,结果还是没有什么发现。nginx 本身的问题?nginx 配置文件检查了这周都没有变动过,nginx 接了很多应用,就应用A有问题,而且所有应用在 nginx 的配置基本一致。

领导介入,A应用回版到4个月前的版本

最开始我们尝试了回版,就回了最近一两次的版本,一般回版就回一个机房的,但是没有效果。领导说要回到A应用不直接打到 kafka 的版本,那个版本是 4 个月前的版本了。不过我觉得用途不大,毕竟当时做个测试,A应用就算连不上 kafka 也不会影响 RT 时间。不过只能先回版看看了,回了一台以后,发现这个tomcat 的 RT 时间回到了 15ms 的水平。然后就把一个机房的A应用都回到了这个版本。观察了 10 分钟后,这个机房A应用的RT时间回到了正常水平。然后就接着把剩下的应用实例都回到了 4 个月前的版本,这时候已经 14:30 了。实在想不出来为什么回到 4 个月前的版本能解决问题。

周日 ELK 告警

周日早上 5:00 起来看手机的时候发现有 ELK 的告警,5 分钟内没有一条日志进入 elasticsearch,赶紧起床解决问题。这个过程持续了 3,4 个小时,最终查出原因是 kafka 一共有 5 个实例,有 3 个实例内存耗尽了,swap 都用了好多,解决方法就是把整个 kafka 集群重启了(因为 3 个实例出了问题,所以一个个重启解决不了问题,还会有 kafka topic partition 的 reassign)。

kafka 问题分析

kafka 的内存也是周四上午 11:00 开始下降的,而周六A应用RT时间过长的问题也是通过应用不直接连 kafka 解决的。所以 kafka 服务器的内存问题是引起A应用RT时间长的根本原因。

kafka 服务器内存泄漏 bug 简述

kafka 服务器的内存问题之所以只有3个实例又内存问题,这个又是一个故事了,简单的说就是光纤网卡驱动的bug导致的内存泄漏,当时这 5 台都有这个 bug,都是 centos 7.3 网卡绑定 mode 4,当时出于对问题的好奇就采取了两种不同的解决方法,有3台是通过解绑 linux 网卡绑定解决的,2台是通过把 centos 7.3 升级到 7.4 解决的。之所以说解决是因为当时观察了一两个月内存使用一直平稳,所以认定是解决了。

kafka 服务器内存泄漏 bug 因何而再次出现?

距离这次事件发生已经一年半多了,之所以周四上午这个 bug 会被触发,初步分析是因为某个应用使用的 kafka 方式改了,虽然要查是哪个具体应用引起的这个问题不难(因为故障的时间点很明确),但是我没有查下去,因为就算查出来是哪个应用,我们也不能做什么,所以这个问题就到此为止了。

事后分析

这个事情过去了两三个月,再问开发为什么应用记录的 RT 时间会和实际有那么大的出入,他们也不知道为什么。不过后来又出现几次这种 java 应用自己记录的 RT 时间和实际的不一致的问题,这个问题的共性就是出问题的时候 java 的 GC 会比较频繁。我分析当时A应用连接 kafka 肯定是耗时比平常多很多,所以同一时间内连接 kafka 的资源消耗肯定比平时多,这样 java 的 GC 可能会比平时多,可能就会引起应用自己记录的RT时间和实际的不一致的问题。但是这个只是猜测,具体对不对只能在今后的遇到的问题中仔细分析了。

整体回顾

本文的整体回顾就以谷歌 SRE 处理问题的几个原则来分析:

初学者心态

当时领导要把A应用回版到4个月之前,自己内心其实是十分反对的,因为觉得没道理,不过现在觉得,所以的问题我们都应该用事实说话,不能觉得自己真正了解整个系统了,有时候问题是复杂的,很多东西我们只有遇到了才会知道自己其实有很多不清楚的。

信任但要验证

当周六有人报 kafka 的问题的时候,我就直接说 kafka 没有问题,并没有去验证 kafka 是否有问题,只是觉得自己的检测脚本没有告警就没有问题。试想如果当时自己登陆 kafka 服务器简单查看了下,当时也不用那么多人花了大半天的解决问题。其实自己的检测脚本也有些问题,事后改良了一下,和这个问题关系不大就不细说了。

原文地址:https://www.cnblogs.com/WisWang/p/12079233.html

时间: 2024-11-09 02:52:50

记一次线上故障处理的相关文章

系统上线那点事 - 记一次线上系统故障

该项目是一个微信转盘游戏抽奖营销项目.因为运营营销时间要求紧迫.开发測试部署上线用了10天不到,有些准备工作并没有到位,如: 1.因为总体开发在上线前2天才完毕,測试了解这个项目需求是在开发的第二周,并没有充足的时间进行完好的功能,UI机型适配,系统压力測试. 2.技术上因为合作方的公众号密钥并不适合直接给出,所以由对方封装微信接口获取所需功能,对方封装的微信接口给出比較迟,在预定開始时间前三天: 微信的网页接口授权回调域名仅仅有一个.这个回调域名还有其它应用在使用,不能直接简单的改为我们部署应

线上故障处理原则

墨菲定律 任何事情都没有表面看起来那么简单 所有事情的发展都会比你预计的时间长 会出错的事情总会出错 如果担心某个事情发生,那么它更有可能发生 墨菲定律暗示我们,如果担心某种情况会发生,那么它更有可能发生,久而久之就一定会发生.这警示我们,在互联网公司,对生成环境发生的任何怪异现象和问题都不要轻视,对其背后的原因一定要调查清楚.同样,海恩法则也强调任何严重的事故背后都是很多次小问题的积累,当到一定量级后会导致质变,严重的问题就会浮出水面.那么,我们需要对线上服务产生任何现象,哪怕是小问题,都要刨

记一次线上gc调优的过程

近期公司运营同学经常表示线上我们一个后台管理系统运行特别慢,而且经常出现504超时的情况.对于这种情况我们本能的认为可能是代码有性能问题,可能有死循环或者是数据库调用次数过多导致接口运行过慢.应领导要求,我们将主站中进行性能测试的框架代码(见我前面一篇博文记录一次通过性能日志处理线上性能问题的过程)添加到了该后台管理系统中.上线运行一段时间后,查看相关日志可以看到如下分析日志: 通过该日志可以发现,dao方法一直获取不到数据库链接池,但是根据实际情况考虑应该不大可能,原因有两点: 主站和后台管理

记一次线上MySQL数据库死锁问题

最近线上项目报了一个MySQL死锁(DealLock)错误,虽说对业务上是没有什么影响的,由于自己对数据库锁这块了解不是很多,之前也没怎么的在线上碰到过.这次刚好遇到了,便在此记录一下. 出现死锁问题背景 项目层面:报错的项目做的是一个批量下单的动作,会同时写入多条订单数据,代码之前写的是一个事务中一个循环一条一条insert到数据库(至于为啥没用批量插入就不追究了,历史原因了). 数据库层面:一张test表(非线上真实表),比较重要的是有一个 type 和 name的唯一索引. 事务隔离级别:

记一次线上mysql主从架构异常的恢复经历

前提:之前一位同事负责的一位客户,因后期转到devops小组.所以将此用户交接给我,在后期发现有一套数据库主从环境,从库已经无法正常使用.查看slave 状态为: 其中:Master_Log_File:#此处显示的bin-log已经在master上找不见了Read_Master_Log_Pos:#显示的行数也就存在没有意义了Slave_IO_Running:NO #salve io进程显示为no,无法从master同步数据因此判定从库已经无法使用,需要及时修复.保证主从架构正常使用. 以下是恢复

记一次线上环境 ES 主分片为分配故障

故障前提 ElasticSearch 版本:5.2集群节点数:5索引主分片数:5索引分片副本数:1 线上环境ES存储的数据量很大,当天由于存储故障,导致一时间 5个节点的 ES 集群,同时有两个节点离线,一个节点磁盘只读(机房小哥不会处理,无奈只有清空数据重新安装系统),一个节点重启后,ES集群报个别索引分片分配异常,ES索引出于保证数据一致性的考虑,并没有把重启节点上的副本分片提升为主分片,所以该索引处于 不可写入 状态(索引分片 red). 处理方案 在网上找了找类似的处理方案,分为以下几个

记一次线上服务器处理后门程序

现象:当日下午,通过监控报警得知,该台服务器的CPU使用率非常高,已接近100%,见下图: 处理过程: 1.立刻登录服务器,用top命令查看是什么原因导致CPU使用率飙升,见下图: 2.发现.chinaz{1461058进程占据了97%的CPU,确定该进程是可疑进程 3.在系统上使用 find / -name ".chianz"命令找到和此命令相关的文件,发现在/etc/rc.d/init.d/目录下存在可疑文件,删除该文件并重启系统,系统恢复正常 4.通过安全事件得知,该文件是被人利

记一次线上Java程序导致服务器CPU占用率过高的问题排除过程

https://blog.csdn.net/u013991521/article/details/52781423 1.故障现象 客服同事反馈平台系统运行缓慢,网页卡顿严重,多次重启系统后问题依然存在,使用top命令查看服务器情况,发现CPU占用率过高. 2.CPU占用过高问题定位 2.1.定位问题进程 使用top命令查看资源占用情况,发现pid为14063的进程占用了大量的CPU资源,CPU占用率高达776.1%,内存占用率也达到了29.8% [ylp@ylp-web-01 ~]$ top t

记一次线上问题排查:C#可选参数的坑

线上报了大量异常,错误信息为:找不到XX方法实现 代码调用关系是: 查看代码历史记录,发现最近上线前对 GetUserDottedLineSuperiors 方法做过修改,增加了一个可选参数. 跟相关开发同学确认后,是Hotfix的方式上线了UserService.dll,没有整版发布(而在测试环境验证的时候是整版发布). 按说,改了哪里的代码,只需要更新该代码所在的dll即可,也就是只更新UserService.dll是没毛病的. But,这样是不对的. 我们分别看一下DataRule.dll