6.1 海恩法则和墨菲定律
海恩法则:
每一起严重事故的背后,必然有29次轻微事故和300起未遂先兆及1000起事故隐患。
1.事故的发生是量的积累的结果
2.再好的技术,再完美的规章,在实际操作层面也无法取代人自身的素质和责任心
在线上应急的过程中,不但要定位和解决问题,还要发现问题的根源,并找到事故之前的各种征兆,对征兆进行排查和分析,并做相应的报警处理。
完善,通用的平台都是为80%的通用需求服务的,对于20%的特殊需要和问题仍然需要专家来解决,因此,作为互联网架构师或者专家,我们需要对自己的
线上服务了如指掌。
墨菲定律:
如果有两种或者两种以上的方式去做某件事,而选择其中一种方式将导致灾难,则必定有人会做出这种选择。
墨菲定律强调以下几点:
1.任何事情都没有看起来那么简单
2.所有事情的发展都会比你预计的时间长
3.会出错的事情总会出错
4.如果你担心某种情况发生,那么它更有可能发生
对生产环境的任何怪异现象都不能忽视。
6.2 线上应急的目标、原则和方法
6.2.1 应急目标
在生产环境发生故障时快速恢复服务,避免或者减少故障造成的损失,避免或者减少故障对客户的影响。
6.2.2 应急原则
1.应第一时间恢复系统而不是彻底解决问题,快速止损
2.有明显的资金损失时,要在第一时间升级,快速止损
3.应急指挥要围绕目标,快速启动应急过程和快速决策止损方案
4.应急指挥负责人如果在短时间内不能解决问题,则必须进行升级处理
5.应急过程中在不影响用户体验的前提下,要保留部分现场和数据
6.2.3 线上应急的方法和流程
线上应急一般分为6个步骤:
1.发现问题
发现问题时常通过自动化的监控和报警系统来实现。
对系统层面的监控包括对系统的cpu利用率,系统负载,内存使用情况,网络IO负载,磁盘负载,IO等待,交换区的使用,线程数及打开的文件句柄等进行
监控,一旦超出阈值,就需要报警。
对应用层面的监控包括对服务接口的响应时间,吞吐量,调用频次,接口成功率及接口的波动率等进行监控。
对资源层的监控包括对数据库,缓存,消息队列进行监控。我们通常会对数据库的负载,慢sql,连接数等进行监控;对缓存的连接数,占用内存,吞吐量,
响应时间等进行监控;以及对消息队列的响应时间,吞吐量,负载,积压情况等进行监控。
2.定位问题
在分析过程中要先考虑系统最近发生了的变化,需要考虑如下问题:
1.问题系统最近是否进行了上线
2.依赖的基础平台和资源是否进行了上线或者升级
3.依赖的系统最近是否进行了上线
4.运营是否在系统里面做过运营的变更
5.网络是否有波动
6.最近的业务是否上量
7.服务的使用方是否有促销活动
3.解决问题
在发生严重问题时先使用止损策略,在恢复问题后再定位和解决问题。
4.消除影响
无论在哪种情况下都需要消除问题产生的影响:
1.技术人员在应急过程中对系统做的临时的改变,后证明是无效的,则要恢复到原来的状态
2.技术人员在应急过程中对系统进行的降级开关操作,在事后需要恢复
3.运营人员在应急过程中对系统做的特殊设置如某些流量路由的开关,需要恢复
4.对使用方或者用户造成的问题,尽量采取补偿的策略进行修复,在极端情况下需要一一核实。
5.对外由专门的客服团队整理话术统一对外宣布发生故障的原因并安抚用户,话术尽量贴近客观事实,并从用户的角度出发
5.回顾问题
消除问题后,需要应急团队与相关方回顾事故产生的原因,应急过程的合理性,对梳理出来的问题提出整改措施,主要聚焦于下面几个问题:
1.类似的问题还有没有没有想到的?
2.做了哪些事情,这个事故就不会发生?
3.做了哪些事情,这个事故即使发生了,也不会有损失?
4.做了哪些事情,这个事故即使发生了,也不会产生这么大的损失?
6.避免措施
根据回顾问题时提出的改进方案和避免措施,我们必须以正式的项目管理方式进行统一管理。
应急只有一个总的目标:尽快恢复问题,消除影响
6.3 技术攻关的方法论
技术攻关的目标是解决问题,因此首先要从问题发生的环境和背景入手,首先考虑下面几个问题:
1.最近是否有变更,升级和上线?
是 => 回滚。
否 => 之前是否遇到此类问题
2.之前是否遇到相同后者类似的问题?
是 => 历史经验
否 => 是否有相关领域的专家
3.是否有相关领域的专家?例如:安全,性能,数据库,大数据和业务等领域的专家
是 => 开启专家模式
否 => 最小化复现 => 找到原因 => 提出解决方案 => 验证解决方案 => 线上实施
对于第1个问题很重要,30%线上问题都是上线导致的,必须建立上线流程和上线评审机制,每一次上线都需要有快速回滚方案。
对于第2个问题,根据历史经验判断以前是否遇到相同或者类似的问题,如果有,用历史经验解决。
对于第3个问题,我们需要先判断这个问题是否是某个领域的深层次问题,比如被攻击,性能扛不住或者数据库频繁告警等,如果是这类问题,我们需要请教专家。
如果通过上面的思路还没有解决,那么一次真正的技术攻关就开始了。思考下面问题:
1.when: 什么时候出的问题?
2.what: 什么出了问题?
3.who: 谁在什么时间里发现了问题?问题影响了谁?
4.where: 哪里出现了问题?哪里有没有出现问题?
5.why: 为什么出现了问题?
最小化复现是指个人开发环境内通过模拟生产环境来重现生产问题。
首先方案要在开发环境和QA环境下进行验证,不但验证此方案是否解决问题,还要避免影响现有的功能,因此需要做回归验证。大型平台的回归验证都是自动化测试平台
实现的。方案通过后才能应用到线上环境中,可以通过灰度发布环境通过对一些对系统可用性不太敏感的用户流量来验证方案,成功后才能应用到生产环境。
6.4 环境搭建和示例服务启动
6.5 高效的服务化治理脚本
6.5.1 show-busiest-java-threads
6.5.2 find-in-jar
6.5.3 grep-in-jar
6.5.4 jar-conflict-detect
6.5.5 http-spy
6.5.6 show-mysql-qps
6.5.7 小结
6.6 JVM提供的监控命令
6.6.1 jad
jad 反编译工具可以将字节码的二进制类反编译为java源代码常常用于遇到问题但是无法在源代码中定位的场景,通过反编译字节码,
可以分析程序在实际执行流程,从而定位深层次的问题。
6.6.2 btrace
btrace 可以动态的跟踪java运行时程序,将定制化的跟踪字节码切面注入运行类中,对运行代码无入侵,对性能的影响也可以忽略。
6.6.3 jmap
生产中Java应用遇到 OutOfMemoryError 属于家常便饭,发生了内存不足时,我们需要找到原因,查出内存问题。jmap主要用来查看java内存
的使用情况。
6.6.4 jstat
jstat 利用jvm内建的指令对java应用程序的资源和性能进行实时的命令监控,包括对堆大小和垃圾回收情况的监控等。与jmap对比,jstat更倾向于
输出积累的信息与打印GC等的统计信息等。
6.6.5 jstack
jstack 命令用于打印给定的java进程的线程堆栈快照信息,从而可以看到java进程内线程的执行状况,正在执行的任务等,可以据此分析线程等待,死锁等。
6.6.6 jinfo
jinfo 可以输出并修改运行时的java 进程的环境变量和虚拟机参数。
6.6.7 其他命令
javah : 生成java类中本地方法的c头文件,一般用于开发JNI库
jps: 用于查找java进程,通常使用ps命令替代
jhat: 用于分析内存堆的快照文件
jdb: 远程调试,用于线上定位问题
jstatd: jstat 的服务器版本
Java 虚拟机的图形界面分析工具如下:
1.JConsole
2.JVisualVM
JMAT
JProfiler
6.7 重要的Linux基础命令
6.7.1 必不可少的基础命令和工具
6.7.2 查看活动进程的命令
6.7.3 窥探内存的命令
6.7.4 针对CPU使用情况的监控命令
6.7.5 监控磁盘I/O的命令
6.7.6 查看网络信息和网络监控命令
6.7.7 Linux系统的高级工具
6.7.8 /proc文件系统
6.7.9 摘要命令
6.7.10 小结
6.8 现实中的应急和攻关案例
6.8.1 一次OOM事故的分析和定位
6.8.2 一次CPU 100%的线上事故排查