1. 稳定性总览
图片过大,有压缩,可能不是特别清晰,图片可能不是最新,请直接查看 思维导图链接。
备注:由于本人目前做 IoT 业务,所以会以设备为例。
1.1 定义
当系统收到输入后,能输出正确的、符合预期的响应,此时系统称为稳定。
1.2 核心
- 减少系统不稳定的可能性
- 减少系统恢复稳定的时间
2. 思维导图部分说明
- 关于边缘业务:边缘业务往往是遗漏点,但是也容易引发故障。我遇到过边缘业务消费阻塞,导致整个 kafka 消费集群疯狂 rebalance,影响核心业务;同样也遇到过边缘业务触发某个坑,拉取上万个设备,把依赖应用接口打挂的情况。
- 关于发布:这里的发布不仅是代码部署上线、流程变更、配置变更均属于发布范畴。
- 关于监控:发布阶段和故障监控告警均依靠监控,不同之处在于发布阶段着重关注各项指标是否有明显变动,而告警更关注阈值。假如发布时 CPU 利用率涨了百分之十,可能不会触发告警,但依然需要评估该增长是否合理。
- 关于 RT:不要使用平均等待时长作为衡量服务负载的指标,应该核查应用的“尾部”值。使用 50%、90%、95%、99% 的平均等待时长作为服务响应的指标。一个很常见的场景,用户反馈某页面响应很慢,但是查看接口平均 RT 却很正常,但如果查看 P95、P99 指标可能会发现确实有少量请求耗时极大。
- 关于接口 RT 差值巨大:如果某个大接口在不同数据请求时, RT 差异巨大,建议对接口进行拆分,方便设置合理的超时时间,同时也方便统计和监控。举个例子:在物联网场景下,控制一个智能灯的开关是很快的,但是在 APP 上拉流显示摄像头的视频是极慢的,此时可以将拉流的操作单独拆分出接口,避免公用一个接口时因为拉流耗时大而将整个接口的超时时间设置过大。
- 关于发布监控期间的依赖应用:这个时常被忽略,发布变更往往会影响到上下游依赖,比如你提供出去的 dubbo 接口改动后性能变差、影响到调用方;或者你对依赖应用的 dubbo 调用量翻了好几倍,导致依赖应用系统水位增长很多。明显影响上下游的变更需要及时同步相关责任方。
- 关于日志:在高并发场景下,注意 info 日志的量,我遇到过增加一行日志发布后,CPU 涨了 25%。warn 日志和 error 日志要严格区分,我遇到过请求第三方 Http 接口报 SocketTimeoutException 被捕获后不打 error 日志、不计失败 Trace 而导致成功率统计有误的。
- 关于使用 AOP 打日志:我个人的观点是严禁使用 AOP 打日志,这会养成不思考、随意打日志的习惯,并且可能会引入安全合规问题,比如把账号密码通过 AOP 打印下来。
- 关于上下游依赖:研发必须熟悉自身业务的上下游,对上三层、下三层有把控。这样不仅可以提升平时研发协同的效率,而且可以在系统变更或者出故障时做出更精准的判断。之前出现过对上下游不熟悉而导致的故障,调用链:我的应用 —> 应用 A —> 应用 B,应用 A 的接口对外提供给客户,为了保证安全性,应用 B 对应用 A 按照客户的指定流量进行限流,但是评估的过程中完全没有考虑到我的应用,导致高峰期我的应用被限流,业务有损。
- 关于隔离:环境隔离、数据隔离、应用隔离、接口隔离都要考虑。我经历过在跨区业务中由于隔离没做好导致欧洲区故障拉跨美国区的。
- 关于定期巡检监控:我个人养成了双周周一上班先看业务监控的习惯,一是看业务流量情况,二是看系统水位、各监控指标等。各指标的小小异常,将来都有可能造成故障,需要提前分析和处理。
- 大型故障和局部故障的区别:局部故障的第一优先级是及时止血,虽然暂时不知道产生问题的原因,但是可以通过回滚、重启/摘流、扩容等措施解决,此时如果花精力定位反而浪费时间;大型故障的第一优先级是定位根本原因,因为此时大面积的故障,各个应用都出现故障,如果不找出根本原因,各应用没法通过常规措施进行恢复。局部故障一般是小团队故障,大型故障一般是大团队甚至集团故障(例如:整个机房网络故障、整个k8s 集群崩溃、多个Redis实例宕机、ZK 脑裂、链路雪崩等)。
- 关于回滚:回滚时要注意不要出现二次故障,之前遇到过发布时修改了 Apollo 配置中心配置,然后在回滚的时候因为配置问题导致了二次故障。
- 关于故障复盘:亚马逊有 Ask 5 Whys 方法,针对这次故障至少反问 5 个为什么,并针对提出的反问制定对应的 Actions,可以是技术层面,可以是流程层面,可以是个人能力层面。
脑图中的每一个单项,都可以开一篇文章细讲,网上资料也很多,这里不再赘述。