开篇之前,先来讨论一个问题,当谈到服务治理的时候,说的其实是什么呢?
我们认为,服务治理的关键要素在于两点,人和系统,我们在系统层面希望服务能够按照业务愿景和架构师的理念进行运行和持续演进。而在人的层面,我们希望在这些系统之上工作的工程师能够取的最大的舒适感。
听起来有点像废话,但确实是很容易在一些高大上的名词中忽视掉的点。在《微服务设计》一书中,其实也提到了类似的论点。猫眼的服务治理体系在几年的演进过程中,其实也碰到了一些问题。
猫眼作为国内互联网在线票务的领头羊,也在全娱乐领域在做持续深耕,目前有数千万的DAU,每日百亿级的调用和百万级的QPS。
在这个领域,猫眼目前面临的主要难点有如下几个:
以上难点都在过往的几年中困扰着猫眼,也一定程度上阻碍了猫眼业务的发展。
举两个典型的例子:在稳定性这方面,2017年春节档Redis千兆网卡打满带来的严重影响,我们常规时候的流量曲线会有两个规律的早晚高峰,而大家可以看到,在故障当天,因为网卡打满导致了非常长时间的服务不可用。这也是猫眼经历过的一个非常重大的事故。
而在人效方面,目前猫眼有1000+的服务,中间件的升级动辄半年以上的版本升级周期,这个其实对于业务方或者底层架构团队来说都是非常不友好的一个体验。所以基于这些问题,猫眼开始开展服务治理的演进之路。
不难发现,猫眼主要面临的场景是大流量下的概率性故障。基于这样一个前提,需要展开了故障前、中、后全生命周期的分享优化。基于这样的一些背景,得出高可用治理在猫眼的落地理论架构是:面向故障全生命周期进行治理,悲观与乐观并济。
怎么理解这句话呢,从乐观角度上来说,通过各种测试和评估,系统应该可以避免所有的问题。但是从悲观角度来看,基于墨菲定律,我们知道可能发生的就一定会发生,所以必须来看假定问题发生,我们能做什么。以及问题真的发生,又能做什么。
而高可用在猫眼落地,需要面临实际生产中的诸多难点与挑战,比如前面有提到的,如何应对永无止境的爬虫和恶意流量的攻击,如何应对大档期洪峰或者秒杀场景,另外,基于墨菲定律我们知道,故障是无法避免的。所以如何应对随时随地可能出现的各种上下游的故障,如何避免快速故障恢复可能带来的服务雪崩。这些都是做高可用中需要去应对的挑战,也是猫眼几年历程中真实出现的问题。
另外,高可用领域中,流控的常规解决方案是用富SDK来做的,而富SDK是否能满足业务快速滚动以及流控自身敏捷迭代升级的诉求呢?而如果将流控功能都剥离到Server端,我们知道分布式环境中会带来最大麻烦的就是网络,全部剥离到Server端的话如何保障实时性和可靠性?也就是所谓的 Client Side 或 Server Side,我们应该如何抉择?
再者,有了限流、熔断、混沌工程等等的工具后,很容易就出现有工具但实际上用不好的情况,更有甚者,因为分布式网状拓扑下的这些限流熔断工具的滥用,反而可能将你的系统推向不可控的深渊。如何避免有术而无道的局面呢?
基于这样的一些考虑,我们开展了专项的治理行动,自研了猫眼高可用治理中心,代号大禹。旨在提供自动化的限流、熔断、降级、隔离、演练、监控报警的一站式可用性保障方案。由于篇幅限制,下面主要介绍系统的整体架构以及一些产品上的特点。更加具体的架构实现会在后续大会上去做逐步的披露。
首先,这个是高可用治理中心的一个分层架构。做一个简单的介绍:
接下来,简要介绍一下前面一直提到的语法引擎。可以看到,在建模过程中,抽象出四个维度,比如对于下单请求进行限流策略控制。那么APP就是订单服务、Pipeline就是下单功能、Stage就是限流策略,这都是一对多的关系。最后策略会由很多最原子的策略组件Component所构成。
实际上,我们可以定义很多策略组件,比如特征维度、过滤器、动作、条件判断、恢复策略等等。而这些策略你可以定义实际组件和视图组件,来让你的语义尽可能地友好。所以你可以看到,有很多组件,他们在视图层和控制层其实是分离的,他们可以是一对一、多对一、一对多的关系。这样就可以让你的视图层尽可能友好的情况下,实现控制层最大程度的精简。
整个语法引擎的核心表达式即如标题右侧所示。如何解析由 Component 自己定义说了算。这样就实现了组件与组件之间的松耦合和自己内部的高内聚,用轻量级的原子解析,来避免将语法解析器做成一个难以维护的巨无霸产品。
右下方是一些简单的示例。可以看到,无论你是简单的频率限制、或者稍微复杂一点的反爬策略,再或者是状态机熔断这类规则,都可以通过表达式轻松搞定。
最小固化约束下的松散解析,加上VC的分离,这就是猫眼高可用治理语法引擎的核心理念。
这是大禹的系统架构。系统架构上,我们目前分成了几大平台,包括流量控制平台、演练平台、健康度量平台、决策中心和租户隔离,其中右侧置灰的系统目前正在设计开发中。左侧的系统都已经大规模落地并经历了几年线上流量的考验。
下方有个演练平台,即用来进行压测模拟、故障模拟、预案验证。这边不做过多介绍。
上面流量控制平台主要负责进行对流量的限流、熔断、降级和实时监控,是流量的安全保护罩。业务流量会调用远端的流控服务进行实施的决策。
大家如果了解 Service Mesh 的可能会有点熟悉,这种远端实时控制的方式,是不是有点类似于 Istio 的 Mier 服务?是的,在我们16年启动的时候,也是经历了控制平面如何切割,Server还是Client为重的苦苦思索和探索,后来确定了猫眼的流控路线是Server Side为主的方式进行。这个路线也为后续猫眼的发展带来了非常大的便利。仅这个架构选型几年内节省了数百人天以上的投入。大家可能会有疑问,Mixer在 Service Mesh 中被认为是一个相对没那么成功的实现,那猫眼是如何规避的呢?
流控的核心如图所示,包含两大服务——断言服务和分析服务。断言服务主要用以快速判断流量是否符合预期,而分析服务用以进行流量的准实时分析,并将结果传递给断言服务。
这个流控核心里面有几个大的特色:
前面说到猫眼面临的一些场景,比如最开始猫眼面临的锯齿状的恶意流量,如果攻击者或者爬虫做得好的话,一些场景下连这个锯齿都看不到。以及随时业务的快速发展,大档期来临时候的脉冲流量的冲击。再之后随着热门演唱会业务、以及银行活动等等业务的蓬勃发展,逐渐碰到了越来越高流量的秒杀场景。从最开始的一些核心系统QPS突增1k,到后来的突增近100w QPS。这给猫眼其实带来了非常高的技术挑战。而大禹中心是如何在限流上去做出反应的呢?
在2016年及以前,猫眼面临了非常多的恶意流量、爬虫流量,在尝试对猫眼进行一些攻击和商业敏感数据的抓取,针对这个问题,因此研制了策略引擎,并基于此搭建了流控平台,在此基础上,在策略上,我们提供了一些精细化的行为探测,黑白名单,以及基于请求内容特征的决策策略。
实现的关键点主要有四个:
在这个阶段,业务特性要求我们的攻防处理时候,准确性的重要性要大于实时。经过第一阶段的处理,也有了不错的效果,比较明显的是一些系统负载下来了,核心数据的反爬率到达了70%以上,且保持误伤率在百万分之三以下。
到了下一个阶段的攻防,主要就是流量过载的防御,2017年大年初一的服务雪崩给业务带来了较大影响。大档期洪峰来临后,这个阶段要求实时性要进一步提升,而本来的这种异步分析的方式是无法满足我们需求的,研发了持续洪峰限流策略,基于去噪预测算法基于过去的历史数据来预测当前时刻的数据,准确率可以达到99.2%。这不到1%的一个 QPS 牺牲来换取0延时的效果,是可以接受的。同时我们采用多级缓存、批量缓冲以及自然窗口计数的方式,进一步降低对 Redis 的依赖,彻底实现了 Redis 无热点情况下的集群持续洪峰限流策略。
除此之外,我们也提供了其他的能力。比如客户端限流,众所周知,限流越靠前效果越好,所以我们也将限流前置到了客户端层面。以及降级预案,选择了非核心交易链路的功能,进行紧急情况下的部分流量降级和全部降级。
通过第二阶段的攻防,对于实时性有了更高的要求,准确性可以有接受小的牺牲。第二阶段完成后,接入的系统能够承载数百倍过载流量压力而不被压垮。
从2018年下半年开始,不断衍生出银行活动和演出秒杀的场景。这类秒级别激增的流量,用预测算法已经无法很好支持,因为这种瞬时激增的脉冲流量是无法被预测的,更甚可能会因为去噪预测算法会将其标识为噪点数据而导致误差的进一步放大。
所以基于这样一个背景,经过权衡之后,这个阶段在流控层面的优化主要在于入口层面单机限流+内部基础服务持续洪峰限流。 主要有两点考虑:
从全局上考虑,我们和业务方协作,进行了“一控四化”的权衡,即:
随着业务的蓬勃发展,2019年演出迎来了百万级别的 QPS 秒杀场景,我们发现后续步骤用持续洪峰限流也已经无法满足要求,即使经过前面几个步骤的打散,后续步骤的一些系统 QPS 仍然会有激增到很高的情况,用户、订单服务都遭受到类似的问题冲击影响了系统的稳定性甚至导致关联业务受损。
所以这时候对于这类的场景,进行了如下几点的处理:
刚刚提到的是限流,现在说一下熔断。我们的高可用治理中心的熔断能力相比于业内的一些实现,也有自己的一些特别的地方。
我们能够支持精细化的过滤和错误判断标准的自定义。
同时为了避免快速恢复导致服务雪崩,因而采用了阶梯式的熔断策略。有点类似于开手动挡的车,可以跨档降速,但不能跨档提速。通过这种方式,我们提供了这种快速熔断-阶梯恢复的策略。 目前基于猫眼业务主要提供的是基于错误率的判断,当流量较低的时候,按照错误率来判断很容易造成误伤,而流量很低的时候,进行熔断的现实意义也不是很大,所以设置了当前熔断策略启动的流量阈值。
提完了限流、熔断。之后不得不说到目前业内提到的一个越来越流行的做法,即基于类似 BBR 的 TCP 拥塞控制算法的方式来进行自动化的处理,来避免各种参数配置带来的不可控的成本和影响。这是一个非常好的思路。
但是这种类 BBR 的算法的启动阈值判断是需要多维考虑的,而不能就仅仅基于业内目前提供的这种基于 CPU load 的方式来做。这样对于低load的场景无法适用,我们认为应该有一些更智能更全面的评估方式来评估系统的健康度,当系统因为流量原因马上要出问题的时候,再启动对应的 BBR 策略。不能将系统健康直接粗暴地等同于 CPU 使用率或者load高这样的单一判断。比如基于 QPS、基于load、基于错误率、基于容量评估、基于链路判断等等。
这其实给我们提供了很大的想象空间的同时也能解放人力,是未来猫眼希望去深耕的一个方向。
除此之外,还提供了演练的能力,进行了混沌工程的落地实践。演练产品进行了全链路压测和故障演练的打通,可以通过调度压测的流量来进行演练,对应的预案能够在演练过程中不影响线上真实流量。
同时,为了尽量降低风险,一般的演练都会放到晚上高峰期之后再进行。所以针对这种情况,我们也实现了在灰度链路上进行演练,以此来大幅削减演练的成本。两年以来,累计进行十余次大型演练,发现了超百个问题,包含数十个致命级别的问题。这说明演练事实上发挥了非常关键的作用。
介绍一下大禹的精细化运营。能够进行秒级别的流量探测(精确到1s),同时提供了多维度的图表来便于日常使用者和运维方的使用,也提供了自动巡检的能力,来对接入的业务方进行几个维度的巡检来简单判断他的健康状态。
同时,我们也提供了“流量预观察”的能力。因为一条策略上线是否可靠,是否会阈值设置有问题带来一些不可控的影响,上线之前基本业务方心里是没有底的。这个时候我们提供了这种预观察的能力,能够模拟策略生效,让你实时观察实际的影响。从而给你提供了“反悔”的机会。这种能力在我们的限流熔断足够智能化无参化之前,是一个极其重要的能力。
当然,稳定性保障仅靠高可用治理中心是不够的,业务层面,也进行了大量的持续优化。来看下在猫眼2018年稳定性保障持续深耕之后的整体非功能性的故障趋势:
可以看到,P2及以上故障下降了46%,无P1级别故障。和前面几年形成了鲜明的反差。这也侧面体现了猫眼在稳定性保障这个领域的努力,以及高可用治理中心的价值。
这是猫眼服务治理几年发展以来,在稳定性保障方面基于业务痛点去做出的一些工作。本文主要做一些产品特性和功能上的介绍。更深度的剖析和落地的指导原则,会在后续持续披露。下一章节,将介绍猫眼服务治理之下一代微服务架构演进。
领取专属 10元无门槛券
私享最新 技术干货