分享

五年磨一剑:滴滴顺风车服务端之稳定性规范

 airen89 2020-06-15

桔妹导读:本文给出其中稳定性相关的规范,这些规范都是顺风车成立五年来,对大量真实线上故障复盘、总结得到的,希望对大家服务的稳定性提升有所帮助。

本文转自:滴滴技术

服务端作为顺风车技术部内最大的工程团队,随着人员的扩张和迭代,流程规范在其中扮演着原来越重要的角色。一方面规范化可以提高我们的交付质量、交付效率,另一方面,我们也希望在一次次的实战中不断的总结,探索出适用于我们团队的最佳实践。

基于此,我们制定并推广了一套适用于服务端开发的可执行、最小限制的工程规范,包括研发流程、稳定性、性能成本等多个方面。

本文给出其中稳定性相关的规范,这些规范都是顺风车成立五年来,对大量真实线上故障复盘、总结得到的,希望对大家服务的稳定性提升有所帮助。

1

名词解释

下文的描述中,会用到很多的技术名词,为更容易的理解,在这里对这些名词做下简要说明:

  • 服务分级: 

    根据业务需要,一般的我们需要针对最小系统划分为一级服务,一旦出问题需要第一优先级跟进。我们将影响业务核心指标(比如发单量、成单量等)的服务定义为一级服务,其他为二级服务。

  • 预览集群: 和线上生产环境的部署完全一致的一套环境,只是无线上流量,可以内部访问,集群内流量闭环。

  • 小流量集群: 和线上生产环境的部署完全一致的一套环境,通过流量控制,只有个别城市的流量会落到此集群,集群内流量闭环。

  • 灰度发布: 将发布过程分为预览集群、灰度城市集群、10%流量、50%流量、100%流量的发布机制,确保安全上线过程。

  • 全链路压测: 在不影响线上服务的前提下,对生产环境进行压力测试的解决方案。用以摸清生产环境的容量、瓶颈点等。

  • 机房多活: 通过多机房部署,当一个机房出现故障时,可以快速将流量切到其他机房,以减少损失。涉及流量路由、流量闭环、数据同步、数据一致性、灾难应对等诸多环节的整套解决方案。




2. 

稳定性规范

部署和运维
  1. 【强制】严禁在临时脚本中未通过接口或封装方法,直接操作线上数据,如有需要,必须经过QA测试;

  2. 【强制】服务上线必须通过上线平台,并接入质量平台(功能包括自动化case、核心曲线图及其他上线checklist),强制停留观察’

  3. 【强制】一级服务需要包含预览集群、小流量集群(除部分特殊服务)并且双机房部署;

  4. 【建议】非一级线上服务建议包含预览集群;

  5. 【建议】新服务上线建议进行容量规划,建议通过接口压测或全流量压测验证模块容量。

监控告警

  1. 【强制】线上服务机器必须有基础监控报警,包含CPU、IO、内存、磁盘、coredump、端口;

  2. 【强制】线上服务必须有基础的服务监控,包括接口qps、fatal数量、耗时;
  3. 【建议】核心业务指标(发单量、抢单量、支付量等)必须有监控和报警;
  4. 【建议】需要有服务整体大盘,能够涵盖该方向核心模块监控,方便快速定位服务问题。

预案管理

  1. 【强制】必须有多活切流预案,且需要保障有效性,必须定期组织演练,建议1月1次;
  2. 【强制】全链路压测通道需要保证有效性,定期组织压测;
  3. 【强制】一键限流预案需要保障有效性,定期review和演练;
  4. 【强制】强依赖降级预案需要保障有效性,定期演练。

3.1.容灾和容错设计

反模式3.1.1 

过度的节点熔断策略

【实例】

为了提高请求成功率,在下游故障时对下游节点采取熔断措施,比如1分钟内连续出现5次访问出错,则将该节点熔断,不再调用(过一段时间后再恢复),某天网络抖动,下游服务4个实例中的3个均进入熔断模式,导致访问下游的所有流量均落到剩余的这个实例上,压力过大,将该实例压垮。下游服务雪崩,整个系统不可用。

【解决方案】

熔断模式下,还需要有熔断保护措施,避免过度熔断带来的稳定性问题。

反模式3.1.2 
固定的重试序列

【实例】

每次重试序列都为“下一台”。

【后果】
一个是雪崩:假设某一类 query 的重试序列为A B,当 A 出现故障时,B 要承受两倍的压力,如果 B 扛不住,那么 B 的下一个也会被压垮;一个是上线损失流量:假设重试次数是2,上线时如果 A 和 B 同时重启,那么重试序列为 A B的 query 必然无结果。

【解决方案】
评估新的重试算法,比如随机重试。不过相对于固定的重试序列,随机重试序列也可能给系统带来风险,例如可能会降低下游模块的cache命中率,降低系统性能。

反模式3.1.3 
不合理的超时设置

【实例】

上游服务超时时间设置不合理,下游出现问题时,直接把上游服务拖垮。

【解决方案】
应该根据链路的99分位耗时来设置超时时间,同时定期对链路的通信相关配置进行review。

反模式3.1.4 
未考虑同一请求中多次调用下游的影响

【实例】
服务调用下游时超时时间设置没有问题,但同一请求中会串行多次调用某个下游服务,下游服务故障时,也会把上游服务直接拖垮。

【解决方案】
除了考虑对下游服务的单次超时,还需要考虑对下游服务的总体超时。

反模式3.1.5 
不合理的重试逻辑

【实例】
整条链路多个地方有重试,下游服务故障时,重试被放大,导致服务雪崩。

【解决方案】
评估重试机制,梳理请求处理的整个链路,保证重试收敛在一个地方。

反模式3.1.6 
没有考虑到业务毛刺的影响
【实例】
某业务形态有个特点,在半点和整点时刻有请求尖刺,某次受节假日影响,访问下游的流量瞬间暴增,导致下游服务雪崩。

【解决方案】
对业务尖刺进行平衡处理,减少对下游服务的峰值流量冲击。

反模式3.1.7 
没有对异常输入进行容错处理

【实例】
业务没有对异常输入进行容错处理,仍然按照正常逻辑处理,导致数据混乱。

【解决方案】
业务特别是业务入口,必须对不合理的异常输入进行容错处理,保证整个系统的健壮性。

反模式3.1.8 
接口不支持幂等性设计
【实例】
接口不支持幂等性,网络故障时引发大量的重试,导致核心数据大量出错。

【解决方案】
接口设计的时候就需要考虑幂等性的需求。

反模式3.1.9 
没有对非核心流程弱依赖化

【实例】
没有对流程进行弱依赖化,导致系统整体上比较脆弱,每个依赖单元故障都会导致整个业务瘫痪。

【解决方案】
定期对系统的流程进行梳理,最小系统化,非必须流程尽量弱依赖化。

反模式3.1.10 
没有考虑ID溢出的影响

【实例】
某ID使用int32,超出后ID溢出,导出服务异常。

【解决方案】
增加资源相关的ID字段时要考虑ID的范围,是否有溢出风险
定期对资源相关的ID字段进行review,提前预防,最大限度防止故障的发生

3.4.变更管理

反模式3.4.1 
代码搭车上线

【实例】
由于缺乏有效的代码修改管理机制,某产品线由于代码搭车上线,出现过多次线上故障
并且由于变更时涉及的修改比较多,导致问题定位和追查时非常困难

【解决方案】
建立严格的代码管理机制,严禁代码搭车上线,保证任何时刻主干没有未上线验证的代码

反模式3.4.2 
服务回滚时遗漏回滚代码

【实例】
上线出现问题,服务回滚后没有第一时间把代码回滚掉。第二天其他同学上线时将未回滚的问题代码再次带上线,上线时导致连续两天出现系统故障

【解决方案】
服务回滚的时候同时第一时间回滚代码

反模式3.4.3 
过高的并发部署设置

【实例】
部署配置的并发个数太高,导致同一时刻只有少数机器可用,引发集群雪崩

【解决方案】
服务部署配置的并发个数,要保证剩余机器能够承载业务全部流量

反模式3.4.4 
服务启动或回滚时间过长

【实例】
服务上线异常,回滚时单个服务回滚时间太长,导致未能短时间内快速止损

【解决方案】
定期检查服务的启动和回滚时间,保证出现故障时可以第一时间完成回滚操作

反模式3.4.5 
配置文件缺少有效的校验机制

【实例】
配置文件由模型产出,数据配送系统实时配送到线上服务,模型产生的配置文件有问题,引发线上故障

【解决方案】
针对配置文件,尤其是模型产出的配置文件,建立严格的检查和校验机制

反模式3.4.6 
配置变更没有灰度

【实例】
配置相关修改,稳定性意识上重视度不够,没有进行足够的观察和灰度,导致故障

【解决方案】
所有变更,包括服务变更、配置变更、数据变更以及环境变更,都需要进行严格的观察和灰度,保证变更的质量

反模式3.4.7 
变更没有经过严格的测试

【实例】
变更较小,感觉没有必要进行测试,结果出现低级错误,导致故障

【解决方案】
任何变更都要测试、double check,修改一行代码,也可能导致线上的稳定性故障

反模式3.4.8 
变更时没有严格按照变更规范执行

【实例】
上线时,小流量和A机房均严格按照规范检查,服务和各种曲线没有问题,上线B机房时没有进行检查。结果B机房出现故障。
经排查是因为B机房配置缺失

【解决方案】
任何变更都要严格按照变更规范严格检查,上线的每个阶段都要检查服务的各种曲线和指标

反模式3.4.9 
离线直接通过sql更新db数据

【实例】
直接通过sql进行离线更新数据库,没有做好限流保护,导致db压力大,线上服务访问时出现大量超时

【解决方案】
  • 除非特殊情况,严禁直接通过sql操作db数据,修改需通过接口修改,方便通过曲线观察,也可降低直接改库的风险;

  • 批量修改db数据需要通报dba,经过review,确认没有问题时才可以进行操作;

  • 批量增改、增加数据务必做好限流措施。


3.7.稳定性原则和意识

反模式3.7.1 
对稳定性缺乏敬畏之心

【实例】
以为服务出故障是正常的,对稳定性不以为然

【解决方案】
技术同学需要对代码、线上稳定性保持敬畏之心,不能有任何侥幸心理
一行代码的bug,就可能导致整个业务瘫痪掉

反模式3.7.2 
故障时没有第一时间止损

【实例】
服务出现故障时,相关同学第一时间在定位故障原因,没有第一时间进行止损

【解决方案】
出现故障必须第一优先级处理,第一时间止损

反模式3.7.3 
使用未充分验证过的技术和方案

【实例】
某服务使用了mq的广播特性,该特性在公司还没有在线上被使用过,上线后触发mq广播消费代码中的一个bug,导致mq集群不可用的故障

【解决方案】
尽量避免使用未充分验证过的技术和方案
如果因为某些原因必须使用,一定要有相应的兜底措施,同时控制好接入的节奏
在非关键服务上验证充分后,才能应用到核心链路上

反模式3.7.4 
使用新技术时未控制好接入节奏

【实例】
某服务使用了mq的广播特性,在非核心服务验证时间不够的情况下,将此特性引入核心服务,核心服务的流量比较大,触发mq广播消费代码中的一个bug,导致mq集群不可用的故障

【解决方案】
引入新技术时一定要控制好接入的节奏
在非关键服务上验证充分后,才能应用到核心链路上

反模式3.7.5 
稳定性改进方案未及时落实

【实例】
某服务出现故障,复盘时制定了相应的改进措施,但是未及时有效落实;后该问题再次爆发,又一次服务故障。

【解决方案】
建立改进措施落实的有效跟踪机制,保证改进措施的有效落实。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多