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