先来看张表;
很直观的可以看出,饿了么的业务的快速增粘情况,2013年和2014年的时候发生了比较大的飞跃,饿了么也是在这个时间段订单量开始猛增。
对于系统的认知;
第一,订单是整个交易链路的核心,围绕了一些相关服务,比如金额计算服务、催单服务、售中异常服务等,我们希望这些服务之间有明确的区别。
第二,订单实时处理是整个链路的中心,我们将这个过程定义得尽量简洁。一笔交易中,订单被推进得越复杂,说明系统设计得越复杂,出问题的概率也会越高。所以我们希望订单核心流程非常简单、轻薄,把复杂的东西剥离出来,把简单和复杂明确成两个部分。
第三,考虑到交易的时效性和异常场景越来越复杂,将交易分成正向交易流程和逆向交易流程两个部分。正向交易流程,99%的订单会根据这个流程走完生命周期;逆向交易流程,比如说退单要求时效性比较低,处理会牵扯多方业务可能很复杂,所以通过一个逆向的交易流程来解决。
第四,能够在功能和业务上独立的部分,尽可能抽象为单独的模块或服务。简单来说,比如催单的服务,它其实对交易链路无法起到推进作用,它只是一个动作或者附带服务,我们把它单独抽象出来,为后面的发展做出铺垫。
对于监控和告警的峰值非常明显,午间和晚间两个高峰,其他时间流量相对平缓。下面主要讲三个部分。
第一,对于订单而言,吞吐量是最需要重点关注的指标。一开始对业务指标的感知并不是特别清晰,就在某一个接口耗费了很多时间。后来发现一些很小BD的问题不太容易从小接口感知到,但是从业务方面感知就比较明显,所以就更多关注业务指标的控制。
第二,通常我们重视系统指标,而容易忽视业务指标,其实业务指标更能反映出隐晦的问题。
第三,目前我们致力于基于监控和数据学习的过载保护和业务自动降级。虽然现在还没有完全做好,但是已经能感觉到一些效果。如果商户长时间不接单,用户会自动取消订单,自动取消功能的开关目前是人工控制的,我们更希望是系统来控制。
订单系统而言主要有以下四个内容。第一是消息广播补偿,第二是主流程补偿,第三是灾备,第四是随机故障测试系统。在部署方面,把提供补偿功能的服务和主服务分开部署,依赖的服务也需要使用独立实例,以保证高可用性。在效果方面,用户支付成功前的所有信息都应该尽量入库,可以对支付、待接单、接单等一系列环节都可以做补偿。
饿了么的系统参考了Netflix的猴子家族,研发了自己的Kennel系统。猴子家族主要是针对节点的攻击,我们的Kennel主要是对网络、内存等做了调整,还结合自己的服务,对应用和接口也做了一些攻击。攻击分两部分。
第一部分是物理层面的,我们可以对指定节点IO做攻击,或者把CPU打到很高;对于服务和接口而言,可以把某个接口固定增加500毫秒或者更要的响应延迟,这样做的目的是什么?在整个链路中,我们希望架构设计或者节点都是高可用的,高可用就需要被测试,通过大量的测试人为攻击节点或者服务,来看预先设计好的那些措施或者补偿的能力是不是真的有用。
整个Kennel的设计是,首先会有一个控制中心来做总的调度,配置模块可以配置各种计划,可以控制CPU或者网络丢包等,可以设置在每周六8-10am的某个时间点攻击系统十五分钟。它还有一些操作模块,比如执行计划模块、任务执行模块、节点管理模块、执行记录模块等。
Kennel有四个主要的作用。
首先,帮助我们发现链路中隐蔽的缺陷,将小概率事件放大。比如说缓存不一致的问题,之前极少出现,一旦出现之后,处理手段比较缺乏,那就可以通过Kennel来模拟。网络的抖动是很随机的,那么Kennel可以在某个时间段专门进行模拟,把小概率事件放大。如果怀疑某个地方出了问题,可以通过它来测试是不是真的能查出问题。
第二,重大功能可以在发布之前通过其进行测试,迫使你更深入地设计和编码。通过模拟流量或者线上流量回放,来检验系统运行是否如你设计那样工作,比如监控的曲线或者告警以及相关服务之间的依赖等。
第三,我们做了很多失败的准备和设计,要看到底会不会起作用、起多大作用。可以通过Kennel进行校验,在某个时间通过随机手段攻击相关服务,服务方不知道具体的攻击内容,这时原本设定的监控告警,降级熔断等措施有没有及时起作用就是一个很好的校验。同时还可以检验之前准备的容错或者补偿措施是否能按照预期工作。
第四,需要验证FailOver的设计,只有验证通过才可以依靠。所有的设计都是经历了一次一次的失败,一些设计原以为有用,但是真实问题发生时并没有起到作用。真正有意义的FailOver设计一定是经过验证的。
文中部分截图、总结摘自原文的专业术语总结,如有不适请联系15227013954