一般处理线上问题的三板斧是重启-回滚-扩容
,可以快速有效的解决问题,可是根据我多年的线上经验,这三个操做略微有些简单粗暴,解决问题的几率也很是随机,并不老是有效。这边总结下一般我处理应用中遇到的故障的解决方案。mysql
处理故障的时候必须遵循的一些原则redis
提前发现问题,避免故障扩散
故障的出现链路通常以下图所示
每一层都有可能出现问题,越底层出现问题,影响面越大。因此每个层次都须要有相应的问题监控机制,这样越早发现问题,越能尽早解决故障,避免问题的扩散。好比服务依赖的一个数据库主库有问题了,若是等到用户报过来,这时候可能服务已经挂了几分钟了。再等你分析问题,解决问题,切换主备什么的,可能几分钟又过去了。影响访问比较大了。若是在数据库出问题时,就已经收到警报,迅速解决,可能没等用户报过来,问题解决了。sql
迅速广播
当收到一个P0警报,判断应用出现问题了,第一时间在组内广播。所有人员进入一级战斗状态,发现可能和其余依赖的服务/中间件/运维/云厂商有关,当即通知相关责任人,要求进入协同做战。数据库
快速恢复
保留现场很重要,有助于发现root cause。可是发生故障了,必需要争分夺秒,不能为了保留现场浪费几分钟的时间去干什么dump内存,jstack线程状态的事。必须第一时间内先恢复服务,以后再根据当时监控数据,去找root cause架构
持续观察
为了解决问题,可能须要在线上进行了重启/回滚/mock/限流等操做,必定要查看是否达到了预期效果。
须要持续观察一段时间,服务是否真的正常。 有时候可能只是短暂下去了,还会反扑。运维
处理手段无非是重启、扩容、回滚、限流、降级、hotfixjvm
如下是我通常处理线上问题的流程
主要分为四大块性能
和形成大部分车祸的缘由是因为变化致使同样,线上故障一般也是因为变化致使的。外部的变化很难感知到,可是服务自身的变化很容易感知,当有服务发布、配置变动等变化时。那么首先判断是否可回滚,可回滚的立马回滚。线程
如今通常是集群部署,服务高可用。若是只是一台机器有问题,在服务可摘除的状况下当即摘除。不可当即摘除的,先扩容再摘除。日志
整个服务集群都出问题了,问题就相对比较复杂一些了,须要分为单个API与多个API错误。
当即找到相关团队,一块儿看问题。若是是自身服务不正常的请求引发的,再作相应的fix。若是是正常操做引发的,那须要紧急扩容,升级配置。
从上述操做能够看出,故障发生时须要作的判断仍是不少的,若是经验不够丰富,处理不得当,很容易引起故障升级、资产损失。
因此须要提早预防。
像哲学家剖析本身同样去了解你的服务。通常包含如下内容
须要包含如下模块,
系统是如何部署的,部署在什么环境。如何登录、扩容、升配。
哪些模块是核心的,哪些模块是没那么重要的,能够降级的。
当前系统可以支持的单机QPS是多少,可能存在的性能瓶颈是什么,须要经过压测来得出来。
当前应用的API读写比是多少,对应到各个存储层面的比例是多少。当应用QPS上升,哪一个依赖最早挂掉。redis/mysql 仍是依赖的服务,仍是应用自己。
不管是用户反馈故障,仍是监控警报,基本都晚了,由于这时候已经累积了必定错误量的调用了。因此须要再抢先一步,按期盘点应用。衡量的指标通常围绕使用率、饱和度、吞吐量以及响应时间
盘点的内容包括全部的依赖。
应用层面
磁盘cpu,内存,load数,jvm gc状况
系统层面
qps
依赖的存储
磁盘,cpu, IOPS, qps。
消息队列
消费速度是否正常
另外系统日志是第一手的故障信息来源,应用owner须要按期对错误日志进行查询,可以有效的将潜在问题扼杀在摇篮里。
监控警报有助于提前发现故障,因此确保监控项完备,警报可以有效报出来。
如下是经常使用的一些监控项
类型 | 监控项 |
---|---|
主机状态 | 磁盘使用率>85 |
主机状态 | 5分钟load > 核数*1.5 |
主机状态 | 5分钟内存使用率 > 80 |
主机状态 | 5分钟CPU > 50 |
API | 5分钟API错误率>0.1 |
SQL | 慢查询 耗时>100ms |
日志 | 1分钟错误数>10 |
日志 | 5分钟错误数>50 |