美团扫码付的前端可用性保障实践

开篇

2017年,美团金融前端遇到了很多通用性问题,特别是在保障前端可用性的过程中,我们团队也踩了不少“坑”,在梳理完这些问题以后,我们还专门做了第31期线下沙龙给大家进行了分享。不管是在面试过程中与候选人讨论,还是在团队内的和我们前端小伙伴讨论,都能发现很多同学有一个共同点,对所做的工作缺乏判断,包括如何评判工作交付的质量,如何评判产品与客户之间的触达率等等,这些问题其实比“埋头敲代码”重要很多。

今天抛砖引玉,分享一下我们团队的思考,希望能帮助更多的同学对前端可用性的保障工作,有一个更全面的认识,后续还会分享很多美团前端相关的内容。我们会做成一个系列,对前端感兴趣的同学,可以关注我们美团技术团队(meituantech)的公众号,也欢迎大家跟我们一起交流、讨论。

业务介绍

近几年,随着移动支付的普及,衍生出来聚合支付产品逐渐成为了大家进行移动支付第一选择。而对美团金融平台而言,支付这件事的意义和挑战就完全不一样,我们把它定义为“搭载火箭的冰山式服务”。之所以称之为“火箭”,是因为我们在过去一年中,迅速成为公司又一个日订单千万级的业务,整个业务是火箭式的发展速度。为什么叫“冰山式的服务”?这是因为,通过我们平台的一个二维码、一个页面就可以实现扫码支付,虽然操作比较简单,但是其背后却涉及很多商家系统、供应链系统,而且还需要很多平台系统的支撑,对技术和系统稳定性的要求非常之高。但对用户来说,他们只是看到了“冰山一角”。

前期,我们在做服务设计的时候,我们以为这个产品就是一个很简单的服务,按照传统前端的定义,我们只是把前端的多个界面完成就可以了,后端服务以及很多第三方的接口我们不需要花太多精力去关注。但是真正接触到项目后,我们发现金融服务跟传统的服务完全不一样,甚至还需要做政府方面的一些工作,比如金融最大的问题要合规,这就导致很多业务设计上,必须强制做很多功能节点,随着业务发展过程中节点越来越多,这必然导致服务的可用性越来越差,可能实际情况比下面这张图更复杂。

当我们把产品串起来之后,发现有很多端,每个端同时又有很多的逻辑线互相交叉,这就造成了整个产品和前端服务在快速发展过程中缺乏设计性,同时也缺乏可靠性、稳定性的保证。

很多同学天真的认为,前端服务应该像奥尼尔一样稳定、强壮。但是实际情况,更可能像下了班后“葛优躺”的那种状态。今天我们讲的目标就是:

如何提高自己对所负责业务服务的信心?

之所以提这个目标,是因为有次在休假的过程中,老大问能不能保证你负责的服务不会出问题。相信很多同学都会遇到这种情况,在出去度假或者看电影时,突然接到老大的电话,对于大家来说,这种事情出现直接会影响到生活质量。所以,保障服务的可用性,其实也是提高大家生活质量的重要因素。本文将会从四个方面进行分享:

第一,如何定义的前端可用性。

第二,影响前端可用性的关键因素是什么。

第三,解决这些关键问题的处理方式,或者说端到端监控与降级处理的方案。

第四,总结一下标准的前端保障的工作流程,希望能对大家有所启发,最好能应用到自己的工作之中。

扫码付前端可用性定义

大家对于“系统可用性”这个概念都不陌生,其定义也比较简单,比较好理解,业界通用的计算公式是:

%availability=(Total Elapsed Time-Sum of Inoperative Times)/ Total Elapsed Time

也就是 平均无故障时间/(平均无故障时间+平均故障修复时间) 的百分比。

但是,前端和后端对这个可用性的认知并不一样。因为对于后端服务的可用性来说,执行环境较为可控,基本上不会存在中间的状态。而前端服务却大为不同,前端会面临各式各样不确定的用户使用场景。比如,我们使用iPhone访问没有问题,测试的同学使用小米6也没有问题,但是老板用的华为P10就有问题了。

所以,前端服务的可用性无法像后端一样,可以有准确的数字指标,或者精确的定义公式。当然,这也是前端可用性提升面临的问题,因为我们无法将最终的工作归结在一个衡量指标上。

这里给大家留一个思考题:如果你负责的业务提高了万分之一的可用性,对整个业务能够产生多大大价值?

在美团金融,我们团队粗略算过,如果业务的可用性提高万分之一,对业务部门的价值提升,至少在五位数以上。可以说,不积跬步,无以至千里。可以说,在前端领域,任何一点微小的进步或者提升,都值得我们付出百分之一百的努力。

影响可用性的关键因素

我们把2017年前端发生的故障分为四种类型:

  1. 客户端升级兼容性问题:在做前端开发时,很多组件依赖于容器。比如美团App升级,但是在升级时可能并不会通知所有的业务方,而升级难免会造成兼容性问题,这种情况会造成业务不可用,甚至带来其他相关的问题。这个问题没有办法完全避免。
  2. 代码优化、服务迁移后遗症:代码优化和改造,这点也不可避免。因为技术在更新代码的过程中,很难兼顾到所有的细节问题,容易造成线上事故。
  3. 外部依赖服务故障:这是比较典型的问题,对于前端来说,最常见的就是接口服务或者依赖的基础服务组件出现故障,这些都会导致前端业务的不可用;
  4. 研发流程执行不彻底:其实代码优化层面的问题,可以通过流程或者标准化的动作进行规避。但实际过程中,很多问题是因为投入的精力有限,或者着急上线等因素,导致研发执行的不彻底或者不规范。

虽然看起来很复杂,但是归根结底可以概括成两大类:

第一类问题,就是我们自身的问题,可以比喻成“我撞在猪身上了”;第二类问题就是别人的问题,可以理解成“猪撞我身上了”,我们经常说这样一句话,“不怕神一样的对手,就怕猪一样的队友”,在前端开发问题上,这个道理一样适用。

内部节点可用性

第一点就是如何把自己的事情做好。相信很多同学都看过网上很多文章,也听过线下很多大牛的分享,都非常有经验了。这里还有几个需要强调的地方:

  1. 流程规范:很多的前端事故的主要原因就是流程不规范,所以建议整个研发流程要用SOP来规避一些问题。比如上线的准入标准,服务必须达到一定的标准才能上线,在没有明确之前不准上线等等。
  2. 方案合理:需要根据不同的业务场景,来完成合理的方案设计,之前总结过一篇文章《前端常见开发模式及相关技术介绍》,这篇文章里讲到了三种不同的业务场景,以及他们适合什么样的技术方案。如果大家不知道选择什么样的技术方案,那么我们给的建议就是,尽量选择简单。这样的目的是,当真正发生问题的时候,能够快速解决问题,很多前端开发同学属于“热闹驱动式”选型,但在优化时却无从下手,这点并不可取。
  3. 代码规范:一般而言,很少有前端代码写的不规范,但是可以在流程和制度层面进行额外的要求。很多时候,前端的语法要求不是特别严格,但是服务可用性有额外的要求,代码规范,可以帮助规避简单的问题。

除了上述三点之外,还有一点建议提升测试的效率,虽然整个行业都在做,但是也不是特别理想。之所以提倡单元化测试和自动化测试,主要是因为可以帮助我们减少工作流程中重复的工作,将更多时间投入到业务开发层面。目前,已经实现了Android容器上的自动化测试,同时我们也在使用一些标准规避容器和外部依赖造成的故障。

外部链路的可用性

对技术同学来说,在做任何一个服务的时候,我们经常喊的口号都是“简单可依赖”。但是在现实中,“简单可依赖”几乎是不存在的,没有任何一个人敢说自己负责的服务能够达到简单可依赖,这只是愿景而不是现实。

我们使用外部服务的时,怎么保证它的可用性呢?对于前端开发者来说,外部服务主要分为资源的可用性和接口的可用性,接下来我们依次进行分析:

静态资源的可用性

对于前端工程师来说,静态资源的不可用,主要分以下三种情况:

  1. 资源加载问题:在一个临时的弱网环境下,文件加载失败,比如说电梯间或者一个封闭的过道。
  2. 网络劫持问题:代码篡改的问题,静态资源在经过一些网络运营商时,被进行篡改或者注入广告。
  3. 代码执行问题:可能是兼容性问题,也可能是代码语法或者逻辑出现问题。

针对第一个问题,因为静态资源主要分为CSS文件和JS文件,CSS文件与我们的核心业务无依赖关系,所以加载失败的时候进行重试,保障页面样式可还原。

而JS文件涉及一些依赖的文件,所以我们采用一个比较稳妥的方案:在判断核心的JS文件加载失败时,降级为一个MVP的版本,来保障交易的正常进行。如右图所示,在没有做静态资源降级之前,这个门店是正常的会员门店,会有促销的活动和信息。在CDN出现问题时,它会出现白屏问题。而在经过降级处理之后,我们可以把整个页面回退成普通的门店,就不包含营销或者促销信息了。

整个方案有一个核心点,就是在CDN不可用时进行降级或者重试的过程中,还会遇到不可用的情况,我们最终要把资源回到源服务,至少保障在源服务上可以提供一个静态的页面提供给用户。这里也存在一个风险点,如果资源挂掉的话,源服务能不能承受CDN回源产生的额外流量?这个大家需要打一个问号,也需要特别注意。如果采用这样的方法,一定要评估好服务能不能承受这么大的压力。

第二个问题,大家都比较头疼。因为运营商是以省为单位运营的,所以在跨省的资源请求上会造成额外的流量,基于这个问题,每一个省级运营商都会想办法节省流量,对于流量大的资源有可能会进行劫持甚至篡改。

首先是要预防,一个简单的方案:全部把域名全部升级为HTTPS,让劫持篡改失去了价值,这样可以降低一些风险。如果还支持HTTP访问,依然还会存在被劫持的风险。

其次,在发现劫持问题后,要快速帮助用户修复。美团运维有统一的120模式,这个模式会帮助我们收集一些用户的环境信息,包括网络信息、手机版本号等等,从而快速定位这个问题,全力保障用户体验。

最后是监控,流量劫持都是以省级为单位的,所以在资源监控上,我们要求至少要做到省级,最好能够做到市级,如果发现某一个市、某一个省静态资源发生问题,就第一时间启动修复。

还有一个隐性问题,就是在CDN回源的时,资源请求是不是应该使用HTTPS?在这个问题上,因为考虑到性能,回源请求会使用HTTP。所以普遍来讲,CDN文件的请求会使用HTTPS,意味着我们使用HTTPS来保证CDN不会被劫持,但是CDN回源会造成风险,相当于HTTPS预防这种方式,在理论上不能完全解决这个问题。

最后,还有一个代码执行层面的问题。我们会把报错信息,及时上报到平台上进行分析和处理,目前美团使用统一监控方案CAT,现在已经开源了。

接口服务的可用性

很多前端开发同学有一个很大的误区,接口不可用并不是前端的问题。很多同学会先定位这个问题属于自己还是别人,如果是后端的问题,自己的心态就是“烧高香”。

但实际情况是,系统可用性需要前端和后端共同努力,如果后端不可用,前端怎么提升都是没有效果的,所以我们需要改变自己的认识。如果发现接口有问题,第一时间帮助后端解决或者帮助定位,减少故障影响的时间,这也能提高前端的服务效率。美团对技术团队的要求是,提高监控和反馈的敏锐度。接下来,就涉及到端到端监控和降级的方案了。

端到端监控与降级

监控、报警的目的是为了快速的发现问题。如果定位到问题,第一时间不能靠人力进行解决,那么应该马上进行故障自动处理或者降级。

可控的一些降级的方案在上文中已经提到。对于前端的监控,我们使用了美团开源的CAT。CAT可以定义每个页面覆盖资源的情况,可以细分到省、系统、网络、运营商等维度,从而帮更快的发现劫持和篡改的情况,然后及时进行修复。

故障演练的必要性

在实际工作中,我们很多时候都缺少执行力。比如上文提到的故障处理的方法和方案,在实际工作中有没有效果,或者能不能为业务做出价值和贡献,都需要要打个问号。当然,如果这些事情都没有实践,也相当于“纸上谈兵”。所以,为了最终要达到目的,提高系统的可用性,就需要提高系统的检验标准,接下来就是要做故障演练。

比如,我们可以人为的让后端接口挂掉,看前端服务的表现;让静态资源挂掉,检查对服务有没有影响。现在,美团的静态资源托管服务上运行着近千个项目,如果挂掉的话,会造成无法想象的后果。在这种情况下,托管CDN之后并不意味着会带来一些很好的效果,实际上它也会带来很多无法想象、无法预知的问题。所以为了系统的稳定性保障,最终落地点就是故障演练。

保障动作标准流程

最后总结几点,帮助大家做系统可用性的Review,主要分为事前、事中、事后:

  1. 事前依赖流程与规范,包括代码规范、分支规范、测试规范、上线规范等。如果没有百分百的把握,不要上线。上线标准一定明确的,模棱两可的上线,大概率会出现问题。
  2. 事中依赖监控与降级,可以设计一些监控和降级的方案。对于不可降级的要做好事前的预案,同时也依赖于演练的频率。演练的次数多了,就可以通过熟练的操作,降低服务受影响的时间,间接提高服务的可用性。
  3. 事后依赖执行力,要做可落地的Case Study。很多同学都是在事后复盘的时,说这次没有做好,代码写错了,没有太注意,这是别人的问题等等,草草就结束了。但是对下次事故来说,并没有预防的动作和可落地的执行方案。这就要求执行力,也看解决问题的决心。

总结

最后总结,影响前端服务可用性,其实就是两件事:

  1. 流程规范的执行力
  2. 工程化完整程度

很多前端的同学并没有关注监控和报警的情况,大部分精力还是放在业务开发和功能覆盖上。但是,制定流程规范是工程师通用的能力,希望大家在自己所负责的业务系统中,可以设定更多的流程制度,帮助保障前端服务的可用性和稳定性。

除此之外,我们要多思考。比如认真思考一下,之前的工作存在什么潜在的问题。思考的频率如何,思考之后的结果和落地的执行力如何,这些都非常重要。

我们发现很多前端同学都把时间花在业务开发和功能覆盖上,对于自己的系统缺少完整性的认知。所以建议大家可以先做一个通用的解决方案,覆盖从前端到后台,从研发、测试、上线的全流程。目前,美团金融前端团队已经开始尝试构建一个符合公司前端标准研发体系的解决方案,还有一个线上协作研发平台,将集团的服务进行集成,同时把很多平常不注意的事情集中进行解决,减少重复性的工作,帮助大家把精力更多地投入在核心业务层面。

如果大家对我们所做的事情也有兴趣,想要和我们一起共建大前端团队的话,欢迎发送简历至 tianyang02@meituan.com 。

作者简介

田泱,2015年校招入职美团,先后参与过美团平台移动版多项垂直品类的前端研发工作,从0到1参与了智能支付应用层的前端建设工作,现负责美团金融服务平台前端基础服务研发团队。

下一章:Flutter的原理及美团的实践

总第272篇 2018年 第64篇 导读 Flutter是Google开发的一套全新的跨平台、开源UI框架,支持iOS、Android系统开发,并且是未来新操作系统Fuchsia的默认开发套件。自从20 ...