背景
美团外卖业务在互联网行业独具特色。其流程较为复杂,包含用户下单、商家接单以及配送员接单和交付等环节。压力与流量在午、晚高峰时段高度集中。此外,外卖业务增长迅猛,从 2013 年 11 月上线至最近峰值突破 1600 万,时间还不到 4 年。在这种情形下,一旦发生事故,仅依靠人工排查来解决问题,会存在较多的局限性。本文会详细地对问题发现、根因分析以及问题解决等自动化运维体系的建设历程和相关设计原则进行解析。
外卖业务特点
从业务本身所具备的一些特点来阐述自动化业务运维的必要性。
业务流程复杂
图1 用户角度的美团外卖技术体系
美团外卖的定位为“以在线商品交易与及时送达为核心的 O2O 电商交易平台”。图 1 为用户在使用美团外卖 App 时所涉及的技术模块。此过程历经用户下单,接着系统将订单发给商家,商家准备外卖,然后进行配送,直至最后用户收到商品,像热乎乎的盒饭等。整个过程的时间需控制在半小时以内。在这背后,整个产品线上会涉及众多方面的交互,包括数据分析、统计、结算、合同等各个端。所以,对一致性的要求较高,并且并发量也很大。
每日流量陡增明显
图2 美团外卖常规业务监控图
外卖业务在每天的特定时刻,流量会明显陡增。有时会与第三方开展一些活动,这会导致系统流量瞬间达到午高峰的 2 至 3 倍,如图 2 所呈现的那样。
业务增长迅猛
图3 美团外卖重要成长里程碑
就会导致比较大的损失
开发人员需要快速解决问题。
需要解决的问题
图4 开发人员日常监控痛点
我们在日常的业务运维工作里时常会遇到一些让开发人员感到困扰的问题,就像图 4 所展示的那样,主要存在着四个大的痛点:
各种事件通知和报警事件充斥着开发人员的即时通讯工具(IM)。我们需要投入大量精力去配置和优化报警阈值以及报警等级,这样才不会出现大量的误报。我们期望能够将各种服务的报警指标和阈值进行标准化和自动化处理,然后自动收集这些事件并进行统计。可以帮助开发人员提前发现潜在的问题风险,同时能为找出问题的根本原因提供有力的数据支持。
公司拥有多套监控系统,每套系统都有其特定的职责定位。然而,这些系统之间相互没有关联。正因如此,开发人员在排查问题时,不得不带着参数在不同的系统之间进行切换。这种情况降低了定位问题的效率。
我们的代码中存在大量的降级限流开关,在服务出现异常时会进行相应的保护操作。这些开关随着产品的快速迭代,我们无法确定它们是否依然有效。同时,我们需要较为准确地进行容量规划,以应对业务量的快速增长。这些都需要通过全链路压测来不断地验证,从而发现性能瓶颈,有效地评估服务容量。
开发人员收到各种报警后,通常依据自身经验排查问题。这些排查经验是可以标准化的,例如对于某个服务的 TP99 异常,所需的排查操作是固定的。将问题排查流程标准化后,便可通过计算机实现自动化。要提高诊断的准确度,就需使这个流程更智能化,减少人为参与。
核心目标
我们期望借助一些自动化的举措来提高运维的效率,这样就能让开发人员从日常的业务运维事务中解脱出来。接下来先来看一个用户所处的使用场景:
如图5所示,触发服务保护有两条路径。
当用户前期接收到我们的诊断报警后,会被直接引导进入该报警可能影响到的业务大盘。此时我们需查看业务图表,若影响到业务,就引导用户进入该业务图表对应的核心链路,以定位出问题的根本原因,然后再判断是否要触发该核心链路上对应的服务保护开关或预案。
图5 自动化业务运维系统核心建设目标
用户可以直接通过诊断报警进入对应的核心链路,进而查看最终引发异常的根本原因,以此来引导用户判断是否需要触发相应的服务保护预案。
发现问题,这一步需要不断提升准确度,具体数据可通过全链路压测获得;诊断问题,此步同样需不断提升准确度,相关数据能借全链路压测知晓;解决问题,这一过程的每一步都离不开准确度的提升,全链路压测能给出具体数据。当某些场景的准确度极高时,便可转化为自动化方案。
因此,我们的核心目标在于,当整个方案能够实现自动化推进之后,对于用户而言,其使用场景便转变为:首先收到异常报警,接着收到业务服务恢复通知。随着自动化方案日益完备,开发人员能够将更多精力放在业务逻辑的开发上。
重点系统体系建设
我们确定了核心目标后,便开始着手开发产品。接下来,我们将介绍建设这套系统的核心产品以及各个产品模块之间的关联。对于其它设计细节以及我们碰到的坑,本文暂不进行着重描述,之后会有更具针对性的文章分享出来。
体系架构
如图 6 所示,在自动化业务运维系统里,业务大盘和核心链路是用户使用的入口。若用户查看业务指标时出现问题,我们就得快速找到该业务指标异常的根本原因。我们通过分析核心链路上的服务状态,协助开发人员定位最终的问题节点,并且建议开发人员触发哪些服务保护预案。业务大盘的预测报警可以帮助开发人员提前发现服务可能潜在问题,相当于提前做健康检查;核心链路的红盘诊断报警也能起到这样的作用;已经收集到各个维度的报警事件,若对其做进一步统计分析,同样可以帮助开发人员从宏观角度提前发现服务可能潜在问题,相当于提前对服务做健康检查。我们需要定期进行全链路压测,以此不断验证问题诊断和服务保护是否有效。在压测过程中,能够看到各个场景下的服务健康状态,并且可以对服务节点进行有效的容量规划。
图6 业务监控运维体系架构 业务大盘
外卖业务有很多业务指标会被监控,这些业务指标与系统指标、服务指标不一样,需要业务方按照不同业务自行上报监控数据。业务大盘是业务运维系统的使用入口,它能让开发人员迅速查看自己所关心的业务指标的实时状态以及最近几天的走势情况。
图7 业务监控大盘及拓展能力
如图 7 所呈现的那样,业务大盘不但得展示业务监控指标,同时还得具备很强的对外扩展能力,具体而言,例如:
当业务指标出现异常时,通过对后台监控数据的分析,能够手动或者自动进行事件标记,将引起业务指标波动的原因告知开发人员,以实现用户信息量的快速同步。
可以利用时间戳和类型,迅速引导开发人员进入其他监控系统,从而提升开发人员排查问题的效率。
我们会定时对生产系统开展全链路压测。并且,为了避免压测数据对真实的业务数据造成污染,会将压测流量监控进行隔离。
外卖业务场景下,我们的大多数业务监控数据都具有很强的周期性。对于业务数据,我们能够利用历史数据,通过 Holt 等模型来进行业务数据的预测。当实际值与预测值不在置信区间内时,就会直接进行告警。
由于该运维系统更偏向于业务,所以我们针对那些敏感的业务指标实施了相应的权限管理。
为了使系统使用场景得以增加,我们有必要支持移动端。这样一来,用户能够在任何地点,借助手机来查看自身所关心的监控大盘,同时还可以触发服务保护预案。
核心链路
核心链路是系统主要的使用入口,用户能够通过它快速确定是哪一个调用链出现了问题。如图 8 所呈现的那样,这里包含两个步骤:
我们要给核心链路上的服务节点进行健康评分,依据评分模型去界定问题严重的链路。在此过程中,我们会依据服务的各个指标来描绘服务的问题画像,问题画像中的指标有权重划分。例如,当服务出现失败率报警、TP99 报警,且有大量异常日志时,就会进行高权重的加分。
当确认某条链路出现问题后,链路上靠后的节点可能是引发问题的根节点。我们会实时获取该节点的更多相关监控指标进行分析诊断,此过程会融合开发人员日常排查问题的标准操作程序(SOP),最终有可能定位到是这个服务节点中某些服务器的磁盘或 CPU 等方面的问题。
图8 核心链路产品建设路径
我们最终会发出问题诊断结果。发出这个结果之后,需要收集用户的反馈,以此来判断诊断结果是否准确。这样做能为我们后续优化评分定位模型与诊断模型提供有力的数据支持。在核心链路建设的前期阶段,我们会建议开发人员去制定并触发相应的服务保护预案。当我们的诊断结果达到足够准确的程度后,就能够针对固定的问题场景自动触发服务保护预案,这样做的目的是为了缩短解决问题所需要的时间。
服务保护&故障演练
图9 服务保护&故障演练模块的核心功能
服务保护与故障演练模块是使我们的业务运维体系形成闭环的重要组成部分。该模块所需具备的核心功能如图 9 所呈现。针对各种不同的保护需求,我们拥有不同类型的服务保护开关,主要有以下几种:
业务快速发展,导致代码中存在成百上千的降级开关。当业务出现异常时,需要手动进行降级操作。
限流开关:某些特定业务场景需要具备相应的限流保护措施。其一,针对单机限流,主要是对自身服务器的资源进行保护;其二,针对集群限流,主要是对底层的 DB 或其他存储资源进行资源保护;此外,还有一些其他限流需求,都期望在系统出现流量异常时能有效地进行保护。
自动熔断:能够借助对异常数、线程数等这些简单指标的监控,迅速起到保护作用,使我们的服务健康状态不会快速且急剧地恶化。
根据运维经验,生产事故发生时可能会涉及多个开关的切换。所以需要针对不同故障场景预先设置服务保护预案,以便在出现问题时能通过一键操作对多个服务保护开关进行预设状态的变更。既然有了应对不同故障场景的服务保护预案,就需要时常验证这些预案是否能起到预期效果。
生产对应的事故并非经常发生,当然不能仅仅寄希望于生产真的出现问题才去验证预案,还得针对不同的故障进行模拟。当我们的生产服务出现问题时,无论是由于网络原因还是硬件故障,在服务方面大多表现为服务超时或者变慢、抛出异常。我们前期主要针对这几点进行工作,能够对核心链路上的任一服务节点进行故障演练。在生产过程中,故障可能会同时在多个节点出现。因此,这里就需要我们的故障演练具备支持预案管理的能力。
服务保护属于业务运维的终端措施。我们要在软件层面让用户能够便捷地直达相应的服务保护。这样我们就能轻易地将服务保护与业务大盘以及核心链路整合起来。当开发人员发现问题时,能够方便地进入对应的服务保护预案。有了这些保护措施和故障演练功能,由于它们与核心链路存在关系,所以能够在自动化建设方面与故障诊断以及全链路压测相结合。
整合全链路压测
我们现在会定期组织外卖全链路压测。每次压测都需要很多人配合。如果能针对单一压测场景进行压测,就会大大降低我们组织压测的成本。如图 10 所示,我们现在在全链路压测时,会针对压测流量进行不同场景的故障演练。在制造故障的同时,验证服务保护预案能否按预期启动保护服务。后面会讲一下我们针对全链路压测自动化建设思路。
图10 提升全链路压测给我们带来的收益 自动化路程
前面主要介绍了基于业务的运维系统所需的各个核心功能。下面重点介绍,在整个系统建设过程中,自动化方面的建设主要集中于哪些地方。
异常点自动检测
图11 异常点自动检测
我们在进行核心链路建设时,需要去收集各个服务节点的报警事件。这些报警事件包含服务调用时端到端的监控指标,同时也包含服务自身 SLA 的监控指标。在与开发人员沟通时得知,他们平时配置这些监控指标耗费了大量人力。每个指标的报警阈值都需反复调整,才能达到理想状态。基于这些监控痛点,我们希望能通过分析历史数据,自动检测出异常点,自动计算出应有的报警阈值并进行设置。如图 11 所示,我们依据不同监控指标的特点,挑选了不同的基线算法,并且算出了其置信区间,以此来协助我们更精准地检测异常点。例如,我们的业务周期性较为强烈,多数监控指标在历史同期呈现出正态分布,在这种情况下,可以将真实值与均值进行对比,若其差值在 N 倍标准差之外,就认为该真实值是异常点。
自动触发服务保护
图12 异常检测与服务保护联动
我们的服务保护措施一部分是通过实施自动熔断来实现的,还有一部分是依靠我们已有的上千个降级、限流开关。这些开关通常需要开发人员依据自身的运维经验进行手动触发。我们如果能够依据各种监控指标,准确地诊断出异常点。并且事先把已经确定的异常场景和我们的服务保护预案关联起来。这样就能够自动化地触发服务保护预案,如图 12 所示。
压测计划自动化
图13 压测计划自动化
我们会定期进行外卖全链路压测,需要召集相关业务方来进行准备和跟进。在这当中,数据构造部分会与很多业务方的改造、验证、准备工作相关联。如图 13 所呈现的那样,我们要通过压测计划把整个准备、验证过程串联起来,要让尽量少的人为活动参与到整个过程中。在这期间,我们需要为以下工作做准备:
在整个压测计划的自动化进程里,系统运行中人为参与的部分会逐渐减少,全链路压测效率会逐步提升。我们期望,用户只需点击一个开关就能开始压测计划。
,然后等待压测结果就可以了。
结语
图14 自动化建设后期发力点
在整个业务运维系统的建设过程中,只有精准地定位问题的根节点,将问题的根本原因诊断出来,才能够逐步地去进行一些自动化的运维动作。比如可以触发降级开关,也可以对集群进行扩容等。如图 14 所展示的那样,我们会在这些环节的精细化建设方面持续投入资金。我们希望能够检测到任意维度的异常点,进而向上推测出可能会对哪些业务指标产生影响,以及会对哪些用户体验造成影响。同时,向下依托于全链路压测,就可以非常准确地进行容量规划,从而节省资源。
作者简介
刘宏伟于 2016 年加入美团点评。他主要承担外卖业务架构方面的工作。目前他正在针对业务进行监控运维体系的建设。
名词解释
工作时间:8:00-18:00
电子邮件
扫码二维码
获取最新动态