美团外卖作为一个超级业务方,业务内又运营多个方向业务,如流量业务、交易业务、商家业务、商品业务、营销业务、广告业务等。
综上所述,可以发现美团外卖不仅仅自身业务比较复杂,而且对外的角色也很复杂。在美团内部,外卖不仅仅是美团平台的一个频道业务,而且自己本身也是一个平台业务,同时美团外卖还承担着新业务发展的平台角色。这意味着想要支持好美团外卖业务的发展是一件非常有挑战的事情。
1.3 美团外卖移动端历史架构概述
好的架构源于不停地衍变而非设计。美团外卖的架构,历史上也是经历了很多次迭代。由于外卖业务形态不断地发生变化,原有的设计也需要不断地跟随业务形态进行演进。在不断探索和实践过程中,我们经历了若干个大的架构变迁。从考虑如何高效地复用代码支持外卖App,逐渐地衍变成如何去解决多端代码复用问题,再从多端的代码复用到支持其他频道业务的平台架构上。在平台化架构建设完成后,我们又开始尝试利用动态化技术去支持业务快速上线的诉求。如今,我们面临着多端复用、平台能力、平台支撑、单页面多业务团队、业务动态诉求强等多个业务场景问题。下文我们针对美团外卖移动端架构的变迁史,做一些简单的概述,以便读者阅读本文时能有更好的延续性。
1.3.1 组件化架构
早期阶段,美团外卖作为公司的一个孵化业务,在2013年底完成了美团外卖App的1.0版本。随着外卖业务的验证成功和跑通,订单量也快速增长,在2014年底突破了日订单量100万。随后在2015年2月,外卖以Native的形式接入美团App,成为美团App的一个业务频道。在接入过程中,我们从美团外卖App拷贝了大量的代码到美团App的外卖频道,两个App上的外卖业务代码也分别由两个独立的团队维护。早期外卖业务变化快,App迭代频繁,写代码的方式也比较粗放,同时美团App也处在一个平台化转变的时期,代码的稳定性和质量都在变化和提升当中。这些因素导致了外卖代码内各子系统之间耦合严重,边界模糊,“你中有我,我中有你”的情况随处可见。这对代码质量、功能扩展以及开发效率都造成很大的影响。此时,我们架构重构的目的,就是希望将各个子系统划分为相对独立的组件,建设组件可以直接复用,架构如下图所示:
1.3.2 平台化架构
如上文所述,大家可以知道美团外卖和美团外卖频道是由不同的团队在维护发展。2015年,公司考虑到业务发展的一致性,将美团外卖频道团队正式归于美团外卖。从组织架构上来说,美团外卖和美团外卖频道,逐渐融合成一个团队,但是两端的差异性,导致我们不得不仍然阶段性地维持原有的两班人马,各自去维护独立外卖App和美团外卖频道。如何解决这个问题?两端代码复用看起来是唯一的途径。另外,随着业务的快速发展,外卖App所承载的业务模块越来越多,产品功能越来越复杂,团队规模也越来越大,如闪购、跑腿等业务想以独立的Native包的形态接入外卖App,还有外卖的异地研发团队的建立,都带来了挑战。这使得我们在2017年开始了第二次架构重构——平台化架构,目标是希望能够支持多端复用和支持不同团队的业务发展。通过抽象出平台能力层、业务解耦、建立壳容器,最终实现了平台化架构,架构如下图所示:
1.3.3 RN混合架构
在平台化架构之后,美团外卖功能持续增加,美团外卖客户端安装包的体积也在持续增加。回顾2017年和2018年,每年几乎都增长100%。如果没有一个有效的手段,安装包将变得越发臃肿。另外,由于原生应用需要依托于应用市场进行更新,每次产品的更新,必须依赖用户的主动更新,使得版本的迭代周期很长。业务上的这些痛点,不断地督促我们去反思到底有没有一种框架可以解决这些问题。
在2015年的时候,Facebook发布了非常具有颠覆性的React Native框架,简称RN。从名字上看,就可以清楚的明白,这是混合式开发模式,RN使用Native来渲染,JS来编码,从而实现了跨平台开发、快速编译、快速发布、高效渲染和布局。RN作为一种跨平台的移动应用开发框架,它的特性非常符合我们的诉求。美团也积极的探索RN技术。在RN的基础上,美团在脚手架、组件库、预加载、分包构建、发布运维等方面进行了全面的定制及优化,大幅提升RN的开发及发布运维效率,形成了MRN(Meituan React Native)技术体系。
从2018年开始,美团外卖客户端团队开始尝试使用MRN框架来解决业务上的问题。使用RN的另一方面的好处是,能逐渐的抹平Android和iOS开发技术栈带来的问题,使用一套代码,两个平台上线,理论上人效可以提升一倍,支持的业务需求也可以提升一倍,架构如下图所示:
2. 美团外卖容器化架构全景图
2.1 什么是容器化架构
上文说到,外卖业务已经发展到多App复用、单页面多业务团队开发的业务阶段。要满足这样的业务场景下,寻求一个可持续发展的业务架构是件不容易的事情。经过我们之前架构演进,我们获得了宝贵的经验:在平台化架构的时候,我们将App和业务进行解耦,将App做成壳容器,业务形成独立的业务库,集成到壳容器里面,从而屏蔽了多App的问题,提高了业务的复用度。在RN混合式架构里面,我们引入了RN容器,通过这个容器,使得业务屏蔽了Android和iOS的平台差异。借助这些成功的经验,我们进一步思考,如果我们尝试进一步的细分外卖的业务场景,将不同场景下的基础能力建设成壳容器,业务集成到容器内,是否可以更好的支撑我们多App复用、单页面多业务团队的当前现状呢?
容器化架构的愿景是:
希望将前端呈现业务的环境抽象出来,将能力进行标准化,形成统一的容器,通过容器去屏蔽平台和端的差异。容器提供上层标准统一的能力接口,使得业务开发人员专注于容器内的业务逻辑的实现,最大复用已有的能力,而不用关注现在的环境是Android还是iOS,现在的端是美团App还是大众点评App。
容器和远端达成呈现协议,使得端上的内容具备随时可变化的能力。容器化架构的实现是存在一定前提的,如果业务的发展本身处在一个探索阶段,还有较多可变的因素,是无法形成稳定的能力层的,这时候建设容器化架构反而使得架构偏向复杂。但对于外卖业务场景来说,经过多年的沉淀固定,外卖业务逐渐形成了一套稳定的业务形态,已经进入到场景细分和快速迭代业务模块的阶段。在这样的阶段下,容器化架构才有可实施的前提。
2.2 容器化架构的优势
当我们把承载外卖业务的环境进行了抽象和标准化后,就可以获得以下若干点好处。首先动态化属性提升,我们可以把原有必须在客户端上写的业务放到了远端,业务的动态性得到很大的提升,具备随时上线业务的可能。对于开发过程而言,编译部署的速度也得到了极大提升。如果涉及到客户端的代码改动,那客户端的编译打包,即使是增量的编译,也至少是秒级的编译速度。而容器化后,我们只打包必要的业务,把业务动态下发到容器呈现,客户端代码本身不会有变化,这样就可以从秒级的编译减少到毫秒级的编译。同样,业务动态下发,对减少客户端的包大小也有很大的帮助。
然后,容器位于应用之内,我们向应用中引入相同的容器SDK,容器屏蔽了应用之间的差异,对于Android和iOS平台,在设计上,通过容器这一层去尽可能屏蔽平台之间的差异,使业务开发人员只需要认识容器,不需要花费大量的精力去关注应用和平台之间的差异,从而使得开发效率得到了极大的提升。
其次,容器化后,容器对承载的内容是有接口协议要求的,承载的内容只有满足容器定义的协议才能得到容器带来的好处,这促使业务得到了更细粒度的细分,业务开发时候,对模块化的意识得到了保障。另外,容器这一层提供的接口在Android和iOS上是标准化的,业务的开发也因为依赖的标准化,而趋向标准化,双端的业务一致性得到了提升。这些潜在的架构好处,对未来的业务维护和扩展都打下了比较好的地基。
2.3 外卖容器化架构全景图
整个外卖容器化架构可以按照从下到上,从左到右的视角进行解读:
最底层是系统服务,因为我们采用了H5和RN这样跨端的技术栈,使得iOS系统和Android系统成为了最底层。
系统服务之上是集团基于Native建设的基建,全公司通用,覆盖了研发工程中方方面面的基础服务。
在基建之上是我们定义的容器层。我们尝试用单一技术栈解决所有问题。但经过我们的探索,觉得不太可能实现。好的架构要匹配业务形态,业务的诉求决定了我们不能选择唯一的技术栈去解决所有问题,细分外卖的业务场景可得到以下3个方向的页面分类:
高PV主流程页面,例如首页、金刚页、商家页等,这类页面的PV远高于其他页面。这类页面的特点是,交互强、曝光度高、多团队参与建设和维护。针对这类页面,为了给用户提供极致的体验,是无法采用H5或RN实现的,即使性能上能够满足,但是这些页面是多团队共同参与建设,如果用H5或RN实现,那么单一团队改动,都会造成全页面受到无法预料的影响,其他未改动的业务方肯定是无法接受的。所以这类页面,我们采用的是局部动态化+页面模块化的方案,我们针对页面进行容器化改造,将页面变成容器,容器承载模块。每个模块归不同的业务方进行维护,从模块的维度进行解耦,每个模块都可以动态配置和下发。
低PV辅助页面,例如帮助、足迹、收藏等,这类页面的PV低,但胜在数量多,都用原生实现成本比较高,如果都用H5来实现,不少页面和原生的关联还是比较近,不是非常适合。针对这类页面,我们采用集团提供的MRN基建去承载,MRN作为跨端的技术栈,我们已经在之前的RN混合架构的时候,建设了较为丰富的组件,针对自定义的MRN容器做了比较丰富的建设。同时,MRN具备动态下发的能力,满足业务的诉求。
向外投放的运营活动页面,例如圣诞节活动,时效性比较强。这类页面由H5技术栈去完成,一方面可以满足时效性,另一方面H5的动态下发能力也是最强的,这样的特性能够充分的满足业务的诉求。我们使用集团提供的Titans基建,通过建设业务自定义的Titans容器,支撑业务的发展。
再往上,就是垂直的业务,外卖目前有流量业务、交易业务、商家业务、商品业务、广告业务、营销业务、闪购业务等。业务都是垂直向下依赖,直接可见容器,可见基建,能够很好地获取到各种已经建设的能力去完成业务的需求。
最上面是承载的App端,目前有四端,包括外卖、点评、美团、闪购等等。
右侧是测试发布和线上监控,相对于常规的移动端App架构而言,容器化架构的测试发布和监控是更为精细化的。不仅仅要关注端本身的可用性,还需要关注容器、容器承载的模块、模块展示的模板,模板里面的样式这些的可用性。
2.4 容器化的挑战
容器化架构相对常规的移动端架构而言,它从管理移动端的代码转变成管理移动端的容器建设代码和业务远端开发代码,多出了容器和业务远端下发。这不仅仅是对技术上的挑战,对长期做客户端开发同学,也需要一个思维转变的跳转。
一致性的挑战:容器需要在多个宿主应用之中运行,宿主应用的环境一致性直接影响了容器的一致性。我们的策略是两手准备,一方面利用外卖业务的优势推动宿主应用的环境对齐;另一方面将容器建设成SDK,通过SDK将长期保持容器的一致性,也通过SDK内部的设计屏蔽应用之间的差异;对于Android和iOS平台,我们通过分层的设计,尽可能屏蔽平台的差异。综上所述,一致性的挑战在于(1)容器运行的宿主应用的环境一致性;(2)不同应用不同版本容器的一致性;(3)Android和iOS平台容器的对业务的一致性。
动态发布的挑战:长期以来,客户端同学的开发概念里面只有App版本的概念,而当我们逐渐把业务代码做成远端下发时,将会新增一个线上动态发版的概念。当我们在发布业务的时候,相对以往的工作,多出需要去考虑这个业务的版本,可以运行的容器对应的App上下界版本。另外,发版的周期也会新增业务的发版周期,不仅仅是App的发版周期。这两者在一起将会产生新的火花,业务的版本和App的版本如何适配的问题,业务动态发版的周期和App的发版周期如何适配的问题。外卖这边的解决方式是建设主版本迭代+周迭代的模型。
监控运维的挑战:以往的移动端架构,我们更加关注的是端本身的可用性,然而当我们演进到容器化架构的时候,仅仅关注端的可用性已经远远不能确定业务是可用的了。我们需要从端的可用性延伸出下载链路、加载链路,使用链路上的可用性,针对每个重要的环境,都做好监控运维。
3. 外卖跨端容器建设
3.1 MRN容器
3.1.1 MRN容器简介
React Native框架本身只是一个运行时环境中的渲染引擎,可以将同一套JS代码分别在Android和iOS系统上最终以Native的方式渲染页面,从而为App提供了基础的跨端能力。但从工程化的角度来看,如果想在App中大规模地应用RN技术,除了RN框架本身外,还需要在开发、构建、测试、部署、运维等诸多方面的配合。MRN(Meituan React Native)是美团基于React Native框架改造并完善而成的一套动态化方案,在RN的基础上提供了容器化能力、动态化能力、多端复用能力和工程化保障。MRN在开发效率、稳定性、性能体验、动态化和监控运维等多方面进行了能力升级和扩展,满足了美团RN开发工程化的需要。目前,MRN已接入美团40多个App,核心框架及生态工具有超过100位内部代码贡献者,总PV超过4亿。
3.1.2 Roo组件库
下面再介绍一下外卖建设的两个UI相关的技术项目,Roo组件库和组件样式动态配置。
Roo组件库:外卖在RN及MRN框架提供的UI组件基础之上,又扩展了适用于外卖业务的标准化UI组件库。UI组件库一方面统一了我们的设计规范和开发规范,提高了UI一致性;另一方面,组件封装也提升了RN页面的开发效率和质量。
组件样式动态配置:有了标准的Roo组件,我们进一步给标准组件的动态添加了样式动态配置能力。在使用组件时,很多样式是支持动态下发的,例如字体、圆角、背景色等,方便我们进行UI的适配和改版。
外卖在2018年底开始试验MRN容器在外卖业务上的应用,并在2019年上半年进行了大面积的页面落地。目前,外卖已有近60个RN页面上线,占外卖页面比例超80%,其中包括Tab页面“我的”、提单选择红包页、订单评价页等高PV页面。MRN容器的接入,给外卖App的容器化、动态化、人效提升、包大小瘦身等方面都做出了不小的贡献。
3.2 Titans容器
3.2.1 Titans容器简介
Titans容器是美团系App统一的Web容器组件,基于苹果提供的WebView组件,将WebView容器化,统一了WebView的UI展示和交互方式,规范了桥协议的使用范式,同时预置了诸多基础能力和业务能力。Titans容器大大提高了Web页面的开发效率和用户体验上的一致性。
Web容器:Titans容器提供了统一的UI展示和自定义样式,例如导航栏样式、页面Loading状态、进度条样式等;还有统一的交互方式,例如页面跳转、Scheme协议的解析等。
KNB统一桥服务:Web容器虽然在动态化和Android、iOS双端复用上很好地弥补了Native的不足,但在很多地方体验上又难以达到Native的标准。因此,KNB桥应运而生,KNB定义了Native和JS通信的标准方式,方便开发时进行桥协议扩展,同时KNB也内置众多的Native基础能力,极大地提高了Titans容器的用户体验和开发效率。
Web业务增强能力:Titans容器中预置了丰富的基础业务页面,例如登录页面、分享弹窗等。
提供链路增强:提供了长连接、离线化等方式来提高网络请求的速度和成功率。
WebView预加载:在App启动之后,用户点击网页入口之前,提前加载好HTML主文档和基础库,这样当用户点击页面入口时,App直接使用已准备好的WebView,仅需加载少量的业务代码。从而达到白屏时间短、加载页面迅速的效果。
Titans容器在外卖业务中的使用场景非常丰富,其中最重要的使用场景是各种运营页和活动页,例如点击首页顶部Banner的广告落地页、为你优选、限时秒杀等活动运营页等;还有客服页、帮助反馈页、商家入驻页、美团公益页等功能性页面;作为一级入口页面的美团会员页面,也是一个基于Enlight的Titans容器。
4. 外卖页面容器建设
外卖容器化建设,首先需要要区分的是核心页面和非核心页面。外卖业务中对核心页面的定义是页面DAU>美团DAU的5%或者是下单关键路径。为什么要先按照是否为核心页面进行拆分呢?重点就在于改造的成本。核心页面的业务复杂度决定了它不容易做全页面的动态化,它比较适合做局部的动态化方案。核心页面的复杂度在于业务本身复杂,最重要的是核心页面往往会有多个垂直业务团队共同的开发维护,大家各自有重点关注的模块,做全页面的动态化,无法做到有效的物理隔离。
而对于非核心页面,业务功能和交互相对简单,组织关系也较为确定,更适合做标准的MRN和Titans容器化。所以我们的策略是核心页面做到支撑页面模块级别的业务动态和复用,非核心页面可以做到页面级别的动态化和复用。页面容器化的核心含义就是把一个页面划分为若干个模块,每个模块成为一个业务容器,每个容器的填充既可以用Native的方式实现,也可以用Mach实现(Mach是外卖自研的页面局部动态化技术),可以支持iOS/Android/小程序三端跨平台运行。页面本身则化身为容器的管理者,负责子容器的编排和布局,并支持其动态化。
4.1 页面容器化设计思路
页面容器化设计中主要分为三个阶段,模块有序化、模块编排化、渐进式业务落地。
模块有序化:将耦合的外卖业务代码按模块维度进行拆分,建立标准化的模块间组合和交互方案,降低模块内改动对其他模块的影响。这个阶段我们同时完成了Native原生模块和局部动态化模块的标准化改造。
模块编排化:页面容器化的一个特点是页面具备编排模块的能力,在这个阶段我们在客户端增加了对业务模块结构编排能力的支持,同时我们跟后端的同学共建了配置平台,通过配置化的方式打通了AB实验平台、统一数据服务等多个平台。在标准化的数据协议的支撑下,页面支持了AB实验动态上线,大大降低了客户端在AB实验方面的开发成本,做到了客户端零成本,后端低成本,高效地支撑了外卖首页六周年的大改版。
渐进式业务落地:页面容器化后最明显的收益是支持业务需求的动态上线,只有页面容器中的业务模块具备动态能力才能实现这个目标,这会涉及Native模块迁移为Mach模块的过程。在这个方面,我们的思路是跟随业务需求渐进式落地。在模块编排阶段,我们设计了Native模块向Mach模块迁移的能力,同时设计了覆盖模板维度和API接口维度的三重降级方案,来保障模块动态化迁移的稳定性。
4.2 业务构建模块标准化
从App页面开发的角度看,一个完整的页面可以按照不同的功能及不同业务属性划分出多个不同的模块。
业务构建泛指由多个业务模块组合拼装为一个业务页面的过程,涉及页面本身(UIViewController/Activity)以及各个业务模块的构造过程,前后端业务数据以及页面和业务模块之间的数据交互过程,业务模块内部的数据处理以及视图刷新流程。
模块标准化指的将业务构建涉及到的多个过程通过规范化的方式确定下来,形成唯一的标准。模块标准化一方面能够在解决业务共性问题的基础上提供业务难点专项解决方案,另一方面能够在框架基础上形成能力约束,减少重复建设、低质量建设的问题。
业务构建模块标准化中我们抽象了四层,下面将分别进行解读。
最底层是框架能力层,是外卖业务团队自研的符合外卖业务特点的双端模块化框架。框架解决了不同页面场景下的共性问题,对典型的业务痛点也进行了支持。它是一种页面框架设计在iOS、Android双端对齐的实现方案,这种双端对齐的能力为页面容器化设计的双端一致性提供了保障。
统一接口层是对框架能力层的标准化抽象,它可以保证任一模块调用的能力在各个业务场景下的实现都是一致的,有了这一层抽象任一模块都可以直接在各个场景下复用。
在往上就是App全局的模块复用层,标准化后的模块可以通过唯一标示向模块复用池注册模块,这种中心化的注册方式可以让业务模块在跨业务库的场景下可以灵活地复用。
最上层就是外卖的核心业务场景层,每一个场景都对应了一个标准化的页面容器,页面容器通过实现容器化接口来完成页面容器的构建。
通过业务构建模块标准化的建设,业务模块已经是标准化的了,可以在跨页面间自由组合,这为页面容器化打下了基础。
在页面容器化中最基础的能力有以下几点:页面中业务模块可编排能力,动态上线前端AB实验的能力,增量上线动态模块的能力。实现这些能力最重要的就是进行前后端数据协议标准化建设。客户端根据数据协议中的模块唯一标识匹配并构造业务模块,在完成模块数据的填充后会根据数据协议中的模块布局信息完成模块的布局。针对Mach动态模块,我们创建了基于模板ID的模块匹配和数据填充流程,可以支持Mach动态模板的增量上线。在数据协议中针对前端AB实验我们预留了AB实验和通参字段,在数据填充阶段通过容器化接口传入动态模块中,用于支持AB实验的动态上线。
在容器化上线的过程中属于接口的大版本升级,为了保证容器的高可用性,客户端从模块级别和API级别实现了两套降级容灾方案。
模块级别的降级方案主要针对Mach动态模块,与Native模块不同,Mach动态模块需要预先下载动态模板才能正常地完成模块的载入和渲染。为了保证动态模块的加载成功率,我们一方面在接口上线前利用Eva(美团内部系统)对Mach模板的下载进行预热。另一方面,我们设计了动态模块的主动降级方案,针对动态模块的动态上线使用Native模块进行兜底降级,对于跟版动态模块使用App内置模板的方案进行兜底降级。
API级别的容灾方案主要为了保障客户端在新接口不稳定的情况下可以自行降级到旧接口。针对这个问题,我们对线上老接口设计了数据结构映射方案,在客户端通过配置化的方式可以把老接口的数据结构映射为新接口的数据结构。这样在上层业务无感知的情况下,可以做到容灾方案的上下线。
4.3 小结
通过页面容器化,使得页面只需要关心页面级的构造方式,而无需关心某一模块内部如何实现动态化的。把页面与页面的模块分离,也符合目前外卖客户端的组织结构,有利于业务组间的协作。同时,页面容器化使得外卖核心页面具备了符合外卖业务场景下的动态能力,渐进式把Native静态模块过渡到具备动态能力的模块,从模块的维度使整个页面具备了动态能力。这种渐进式的迁移方案把容器迁移跟业务模块的迁移分隔开,大大降低了页面容器化改造的风险。
5. 外卖容器化架构的衡量指标
5.1 容器化架构衡量指标的特点
质量和性能指标是衡量我们App开发质量和用户体验的重要依据,是我们一直都非常关注的重点数据。在非容器化时代,我们大多数的指标都和App的使用环节紧密相关,因为在非容器化时代,逻辑链路相对简单,例如我们打开一个新页面时,我们首先创建页面实例,然后发起网络请求,同时页面会经历一系列生命周期方法,最后渲染。这时我们可能会关注网络请求的成功率和请求时间,页面的渲染时间,和过成功是否发生Crash,这个过程相对更短暂,指标更少,所以监控起来也更容易。
外卖的容器化大大提升了外卖业务的复用能力、动态能力、模块化和开发效率,但同时也带来了更长的逻辑链路,链路从时间维度上划分是:下载链路、加载链路、使用链路。例如我们在使用MRN容器的时候,会涉及到bundle的启动下载或预热下载,bundle解压缩,MRN容器引擎初始化,bundle加载,JS的加载、执行,页面渲染等步骤,其中的每个步骤都可能存在性能问题和质量风险。因此,我们需要升级我们的衡量指标系统来应对容器化带来的新的挑战。
5.2 链路指标
下载链路:在下载链路中下载容器所需的各种资源,在MRN和Mach中主要是bundle的下载任务,只有bundle下载成功,才能进行后面的各项操作。所以bundle下载的成功率是下载链路中最重要的指标,同时bundle下载的时机也很重要。外卖业务中有各种bundel上百个,如果在启动时拉取所有bundle,对冷启动时间会造成极大的影响。我们采用了bundle预热的方法,发布bundle是给bundle打上相应的Tag,在适当的时机去下载,避免集中下载。
加载链路:在加载链路中重要工作是对下载链路中下载的资源的解压和解析。例如在用PGA加载页面时,会进行模块的解析、模块匹配、模块降级、数据模型生成等步骤。在MRN中会进行bundle解压、引擎初始化、bundle加载等步骤。加载链路往往是比较消耗计算资源的步骤,对页面打开和加载时间影响较大,所以我们会比较关注加载链路的性能指标。
使用链路:使用链路和非容器化的使用阶段基本相同,会主要关注页面的加载时间、Crash率、页面页面FPS、页面卡顿等指标。除此之外,还会关注和容器本身特性相关的一些指标,例如在MRN容器中,我们还会关注JS错误率、JS渲染时间、白屏率等指标。
5.3 关键指标
因为容器化的使用形成了一个串行的链路,所以如果某个关键节点失败,会导致容器功能不可使用,关键指标的任务就是从上述众多的指标当中筛选出这些关键节点。例如在下载链路中bundle下载的成功率和API的成功率,加载链路中bundle加载的成功率和模块匹配的成功率,下载或加载失败都无法再进行链路中的后续步骤,针对上面的成功率指标,我们会添加分钟级别的实时监控告警,做到及时发现,快速响应和紧急修复。
在使用链路中模块渲染的成功率、Native Crash率、JS错误率也属于关键指标,这些任务的失败也会导致容器的不可用,针对这些指标我们也会采用实时监控措施,并且添加降级手段,例如回滚bundle版本,或者把MRN和Mach容器降级为Native容器。
6. 外卖容器化架构的监控运维
上面讲到了容器化架构的各项衡量指标,那么把这些指标具体落到实处的工作就是线上的运维监控工作。工欲善其事,必先利其器,对于监控运维工作,一定要有合适的监控工具辅助配合才能事半功倍,公司内有很多优秀的监控统计工具可供使用,这里的难点就是如何根据监控的需要判断选择合适的工具。还有就是合理的划分监控维度和数据指标的优先级,例如对于能够影响到链路稳定性的关键指标,我们需要做到分钟级的监控,一旦出现问题就能及时收到告警,对于非关键指标,则通过生成日报的方式,方便开发者的统计和分析。
工具的使用上主要分为大盘工具、具体异常工具、灰度降级工具、告警工具等(以下是美团内部使用的工具)。
大盘工具:主要使用CAT、天网、Crash平台等工具。这些工具收集、统计大盘数据,然后生成可视化的图标和曲线。方便开发者了解大盘的整体情况和变化趋势。
具体异常工具:使用Sniffer、Logan等工具。这些工具可以用来获取发生异常时的上下文和设备信息,回捞用户行为日志,方便定位排查具体问题。
灰度降级工具:使用ABTest平台、Horn等工具。用于下发配置,以进行灰度控制或开关控制。
告警工具:告警小助手。将告警通过IM软件及时发送到个人或群组,做到及时发现及时处理。
业务覆盖维度监控可以分为全局监控和局部(单业务)监控。
全局监控:监控各项容器化质量指标、性能指标,生成每日报表,方便跟踪监控容器化的整体质量。
局部(单业务)监控:实时监控每个页面、每个容器的线上数据,做到有问题及时发现,及时定位,及时处理。