早在几年前,移动终端的跨平台技术就不是一个新话题,WebView容器、React Native、Weex、Flutter、小程序和其他移动终端跨平台框架正在蓬勃发展。为什么跨平台如此有吸引力?让我们想象一下,如果我们能够实现一次性开发和多端再利用,我们可以降低公司的就业成本。对于开发,你只需要学习一个框架Android和iOS双平台开发。节省的成本可以投资于产品快速验证和快速推出。这对每个人都很有吸引力。本节首先简要介绍了一些移动终端跨平台技术,让读者更好地理解以下内容。
1.1.1 WebView容器
WebView容器的工作原理是基于Web该技术通过包装和暴露原始接口来实现界面和功能JavaScript调用,JavaScript编写的页面可以在系统本身运行WebView中间。这样做的优点是对前端开发人员更友好,可以快速实现页面交叉,同时保留调用原始能力,通过建造桥接层和原始能力打开。然而,在这种设计中,能力仅限于桥接层。当调用以前没有的原始能力时,需要增加桥梁。此外,浏览器内核的渲染独立于系统组件,不能保证原始体验,渲染效果会差得多。
1.1.2 React Native
2015年,Facebook推出了React Native,一推出就备受关注。它的思路是最大限度地利用前端的生态和Native的生态,和WebView容器最大的区别在于View渲染系统。React Native放弃低效浏览器内核渲染,转而使用自己DSL生成中间格式,然后映射到相应的平台,渲染成平台的组件。WebView容器,体验会有一定的提升。然而,渲染需要JavaScript在某些场景中,与原生的通信可能会导致卡顿。此外,渲染仍然存在Native层,要求开发人员正确Native有一定的熟悉度。
1.1.3 Flutter
2018年Google推出Flutter,通过Dart基于语言构建跨平台开发组件的所有组件Skia引擎自自绘,性能可以和谐Native平台的View相媲美。Flutter站在前人的肩膀上,参考React状态管理,Web的自绘制UI、React Native的HotReload同时考虑和Native通信的Channel开发工具链机制、自渲染、完整。Flutter与上述Recat Native、WebView容器本质上是不同的,它没有使用WebView、JavaScript解释器或系统平台有自己的原始控制器,但有自己独家的Widget,底层渲染利用自身的高性能C/C 发动机自画。然而,大多数移动终端在现有基础上形成了自己的结构Flutter,会形成原有的结构和Flutter双平台共存问题。目前,新的App是最有前途的跨端方案。
美团作为中国领先的生活服务电子商务平台,致力于将消费者和企业与技术联系起来,提供服务,以满足人们的日常饮食需求,并进一步扩展到各种生活和旅游服务。美团外卖作为公司最重要的业务之一,自2013年成立以来,已从单一类别扩展到附近食品、水果、蔬菜、超市、花卉、蛋糕、早餐、午餐、西餐、家常菜、小吃、快餐、海鲜、火锅、四川、蛋糕、烧烤、水果、饮料、甜点等类别。美团外卖可以说是目前电子商务领域最复杂的业务之一。
复杂的业务也给系统结构带来了巨大的挑战。美团外卖业务是目前电子商务领域最复杂的业务,主要来自以下特点:
综上所述,可以发现美团外卖不仅业务复杂,对外角色也复杂。在美团内部,外卖不仅是美团平台的渠道业务,也是平台业务。同时,美团外卖还承担着新业务发展的平台角色。这意味着支持美团外卖业务的发展是一件非常具挑战性的事情。
良好的结构来自于不断的演变,而不是设计。美团外卖的结构在历史上也经历了许多迭代。由于外卖业务形式的不断变化,原有的设计也需要跟随业务形式进行演变。在不断探索和实践的过程中,我们经历了一些重大的结构变化。考虑如何有效地重用代码来支持外卖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使用一套代码和两个平台推出开发技术栈带来的问题,理论上可以将人力效率提高一倍,支持的业务需求也可以提高一倍。结构如下图所示:
上面提到的外卖业务已经发展到很多App复用、单页多业务团队开发的业务阶段。在这样的业务场景下,要找到一个可持续的业务结构并不容易。在我们之前的架构演变之后,我们获得了宝贵的经验:在平台架构中,我们将App与业务解耦App做壳容器,业务形成独立的业务库,集成到壳容器中,从而屏蔽很多App的问题,提高了业务的复用度。在RN我们介绍了混合架构RN通过这个容器,业务被屏蔽了Android和iOS平台差异。借助这些成功的经验,我们进一步思考,如果我们尝试进一步细分外卖的业务场景,将不同场景下的基本能力构建成壳容器,并将业务集成到容器中,是否能更好地支持我们App单页多业务团队的现状如何?
容器结构的愿景是:
当我们抽象和标准化承载外卖业务的环境时,我们可以获得以下好处。首先,随着动态属性的提高,我们可以将必须写在客户端上的原始业务放在远端,大大提高了业务的动态性,并有可能随时启动业务。对于开发过程,编译和部署的速度也有了很大的提高。如果涉及到客户端的代码变化,客户端的编译和包装,即使是增量的编译,也至少是第二级的编译速度。容器完成后,我们只包装必要的业务,将业务动态发送到容器显示,客户端代码本身不会改变,这样我们就可以从第二级编译减少到第二级编译。同样,业务动态发布也有助于减少客户端包的大小。
然后,在应用程序中引入相同的容器SDK,容器屏蔽了应用程序之间的差异Android和iOS平台,在设计中,通过容器层尽可能屏蔽平台之间的差异,使业务开发人员只需要了解容器,不需要花费大量精力关注应用程序和平台之间的差异,大大提高了开发效率。
其次,容器化后,容器对所携带的内容有接口协议要求。只有满足容器定义协议,才能获得容器带来的好处,促进业务细分,保证业务开发中的模块化意识。此外,容器层提供的接口Android和iOS它是标准化的,业务发展也因为依赖标准化而趋于标准化,双端业务的一致性得到了提高。这些潜在的结构优势为未来的业务维护和扩张奠定了良好的基础。
从下到上,从左到右,可以解释整个外卖容器架构:
底层是系统服务,因为我们使用它H5和RN这种跨端技术栈,使得iOS系统和Android系统成为了最底层。
以系统服务为基础的集团Native基础设施建设,全公司通用,覆盖R&D项目各方面的基础服务。
基础设施是我们定义的容器层。我们试图用一个技术堆栈来解决所有的问题。但经过我们的探索,我们认为这是不可能的。良好的结构应与业务形式相匹配。业务需求决定了我们不能选择唯一的技术堆栈来解决所有问题。外卖业务场景的细分可以从以下三个方向进行页面分类:
再往上看,就是垂直业务。目前外卖有流量业务、交易业务、商业业务、商品业务、广告业务、营销业务、闪购业务等。业务垂直向下依赖,直接可见容器和基础设施,可以很好的获得各种已建能力来完成业务的需求。
顶部是承载的App目前有四端,包括外卖、点评、美团、闪购等。
与传统的移动终端相比,右侧是测试发布和在线监控App在架构方面,容器架构的测试、发布和监控更加精细。不仅要注意端本身的可用性,还要注意容器、容器携带的模块、模块显示的模板、模板中风格的可用性。
与传统的移动终端架构相比,集装箱架构从管理移动终端代码转变为管理移动终端的集装箱建设代码和业务远端开发代码,增加了容器和业务远端开发代码。这不仅是对技术的挑战,也是对长期客户开发学生的跳跃。
一致性挑战:容器需要在多个宿主应用程序中运行,宿主应用程序的环境一致性直接影响容器的一致性。我们的策略是双手准备。一方面,我们利用外卖业务的优势促进宿主应用程序的环境对齐;另一方面,我们将构建容器SDK,通过SDK将长期保持容器的一致性,也通过SDK内部设计屏蔽应用之间的差异;Android和iOS平台,我们通过分层设计尽可能屏蔽平台的差异。综上所述,一致性的挑战在于(1)宿主应用程序的环境一致性;(2)不同版本的容器一致性;(3)Android和iOS平台容器的对业务的一致性。
动态发布的挑战:长期以来,客户端同学的开发概念里面只有App版本的概念,而当我们逐渐把业务代码做成远端下发时,将会新增一个线上动态发版的概念。当我们在发布业务的时候,相对以往的工作,多出需要去考虑这个业务的版本,可以运行的容器对应的App上下界版本。另外,发版的周期也会新增业务的发版周期,不仅仅是App的发版周期。这两者在一起将会产生新的火花,业务的版本和App的版本如何适配的问题,业务动态发版的周期和App的发版周期如何适配的问题。外卖这边的解决方式是建设主版本迭代+周迭代的模型。
监控运维的挑战:以往的移动端架构,我们更加关注的是端本身的可用性,然而当我们演进到容器化架构的时候,仅仅关注端的可用性已经远远不能确定业务是可用的了。我们需要从端的可用性延伸出下载链路、加载链路,使用链路上的可用性,针对每个重要的环境,都做好监控运维。
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组件库和组件样式动态配置。
外卖在2018年底开始试验MRN容器在外卖业务上的应用,并在2019年上半年进行了大面积的页面落地。目前,外卖已有近60个RN页面上线,占外卖页面比例超80%,其中包括Tab页面“我的”、提单选择红包页、订单评价页等高PV页面。MRN容器的接入,给外卖App的容器化、动态化、人效提升、包大小瘦身等方面都做出了不小的贡献。
3.2.1 Titans容器简介
Titans容器是美团系App统一的Web容器组件,基于苹果提供的WebView组件,将WebView容器化,统一了WebView的UI展示和交互方式,规范了桥协议的使用范式,同时预置了诸多基础能力和业务能力。Titans容器大大提高了Web页面的开发效率和用户体验上的一致性。
Titans容器在外卖业务中的使用场景非常丰富,其中最重要的使用场景是各种运营页和活动页,例如点击首页顶部Banner的广告落地页、为你优选、限时秒杀等活动运营页等;还有客服页、帮助反馈页、商家入驻页、美团公益页等功能性页面;作为一级入口页面的美团会员页面,也是一个基于Enlight的Titans容器。
外卖容器化建设,首先需要要区分的是核心页面和非核心页面。外卖业务中对核心页面的定义是页面DAU>美团DAU的5%或者是下单关键路径。为什么要先按照是否为核心页面进行拆分呢?重点就在于改造的成本。核心页面的业务复杂度决定了它不容易做全页面的动态化,它比较适合做局部的动态化方案。核心页面的复杂度在于业务本身复杂,最重要的是核心页面往往会有多个垂直业务团队共同的开发维护,大家各自有重点关注的模块,做全页面的动态化,无法做到有效的物理隔离。
而对于非核心页面,业务功能和交互相对简单,组织关系也较为确定,更适合做标准的MRN和Titans容器化。所以我们的策略是核心页面做到支撑页面模块级别的业务动态和复用,非核心页面可以做到页面级别的动态化和复用。页面容器化的核心含义就是把一个页面划分为若干个模块,每个模块成为一个业务容器,每个容器的填充既可以用Native的方式实现,也可以用Mach实现(Mach是外卖自研的页面局部动态化技术),可以支持iOS/Android/小程序三端跨平台运行。页面本身则化身为容器的管理者,负责子容器的编排和布局,并支持其动态化。
页面容器化设计中主要分为三个阶段,模块有序化、模块编排化、渐进式业务落地。
从App页面开发的角度看,一个完整的页面可以按照不同的功能及不同业务属性划分出多个不同的模块。
业务构建泛指由多个业务模块组合拼装为一个业务页面的过程,涉及页面本身(UIViewController/Activity)以及各个业务模块的构造过程,前后端业务数据以及页面和业务模块之间的数据交互过程,业务模块内部的数据处理以及视图刷新流程。
模块标准化指的将业务构建涉及到的多个过程通过规范化的方式确定下来,形成唯一的标准。模块标准化一方面能够在解决业务共性问题的基础上提供业务难点专项解决方案,另一方面能够在框架基础上形成能力约束,减少重复建设、低质量建设的问题。
业务构建模块标准化中我们抽象了四层,下面将分别进行解读。
通过业务构建模块标准化的建设,业务模块已经是标准化的了,可以在跨页面间自由组合,这为页面容器化打下了基础。
在页面容器化中最基础的能力有以下几点:页面中业务模块可编排能力,动态上线前端AB实验的能力,增量上线动态模块的能力。实现这些能力最重要的就是进行前后端数据协议标准化建设。客户端根据数据协议中的模块唯一标识匹配并构造业务模块,在完成模块数据的填充后会根据数据协议中的模块布局信息完成模块的布局。针对Mach动态模块,我们创建了基于模板ID的模块匹配和数据填充流程,可以支持Mach动态模板的增量上线。在数据协议中针对前端AB实验我们预留了AB实验和通参字段,在数据填充阶段通过容器化接口传入动态模块中,用于支持AB实验的动态上线。
在容器化上线的过程中属于接口的大版本升级,为了保证容器的高可用性,客户端从模块级别和API级别实现了两套降级容灾方案。
模块级别的降级方案主要针对Mach动态模块,与Native模块不同,Mach动态模块需要预先下载动态模板才能正常地完成模块的载入和渲染。为了保证动态模块的加载成功率,我们一方面在接口上线前利用Eva(美团内部系统)对Mach模板的下载进行预热。另一方面,我们设计了动态模块的主动降级方案,针对动态模块的动态上线使用Native模块进行兜底降级,对于跟版动态模块使用App内置模板的方案进行兜底降级。
API级别的容灾方案主要为了保障客户端在新接口不稳定的情况下可以自行降级到旧接口。针对这个问题,我们对线上老接口设计了数据结构映射方案,在客户端通过配置化的方式可以把老接口的数据结构映射为新接口的数据结构。这样在上层业务无感知的情况下,可以做到容灾方案的上下线。
通过页面容器化,使得页面只需要关心页面级的构造方式,而无需关心某一模块内部如何实现动态化的。把页面与页面的模块分离,也符合目前外卖客户端的组织结构,有利于业务组间的协作。同时,页面容器化使得外卖核心页面具备了符合外卖业务场景下的动态能力,渐进式把Native静态模块过渡到具备动态能力的模块,从模块的维度使整个页面具备了动态能力。这种渐进式的迁移方案把容器迁移跟业务模块的迁移分隔开,大大降低了页面容器化改造的风险。
质量和性能指标是衡量我们App开发质量和用户体验的重要依据,是我们一直都非常关注的重点数据。在非容器化时代,我们大多数的指标都和App的使用环节紧密相关,因为在非容器化时代,逻辑链路相对简单,例如我们打开一个新页面时,我们首先创建页面实例,然后发起网络请求,同时页面会经历一系列生命周期方法,最后渲染。这时我们可能会关注网络请求的成功率和请求时间,页面的渲染时间,和过成功是否发生Crash,这个过程相对更短暂,指标更少,所以监控起来也更容易。
外卖的容器化大大提升了外卖业务的复用能力、动态能力、模块化和开发效率,但同时也带来了更长的逻辑链路,链路从时间维度上划分是:下载链路、加载链路、使用链路。例如我们在使用MRN容器的时候,会涉及到bundle的启动下载或预热下载,bundle解压缩,MRN容器引擎初始化,bundle加载,JS的加载、执行,页面渲染等步骤,其中的每个步骤都可能存在性能问题和质量风险。因此,我们需要升级我们的衡量指标系统来应对容器化带来的新的挑战。
因为容器化的使用形成了一个串行的链路,所以如果某个关键节点失败,会导致容器功能不可使用,关键指标的任务就是从上述众多的指标当中筛选出这些关键节点。例如在下载链路中bundle下载的成功率和API的成功率,加载链路中bundle加载的成功率和模块匹配的成功率,下载或加载失败都无法再进行链路中的后续步骤,针对上面的成功率指标,我们会添加分钟级别的实时监控告警,做到及时发现,快速响应和紧急修复。
在使用链路中模块渲染的成功率、Native Crash率、JS错误率也属于关键指标,这些任务的失败也会导致容器的不可用,针对这些指标我们也会采用实时监控措施,并且添加降级手段,例如回滚bundle版本,或者把MRN和Mach容器降级为Native容器。
上面讲到了容器化架构的各项衡量指标,那么把这些指标具体落到实处的工作就是线上的运维监控工作。工欲善其事,必先利其器,对于监控运维工作,一定要有合适的监控工具辅助配合才能事半功倍,公司内有很多优秀的监控统计工具可供使用,这里的难点就是如何根据监控的需要判断选择合适的工具。还有就是合理的划分监控维度和数据指标的优先级,例如对于能够影响到链路稳定性的关键指标,我们需要做到分钟级的监控,一旦出现问题就能及时收到告警,对于非关键指标,则通过生成日报的方式,方便开发者的统计和分析。
工具的使用上主要分为大盘工具、具体异常工具、灰度降级工具、告警工具等(以下是美团内部使用的工具)。
业务覆盖维度监控可以分为全局监控和局部(单业务)监控。
时间维度监控:可以按天、小时、分钟的时间维度。天级别的监控主要是一些非关键路径指标,例如一些性能指标,页面加载时间、页面FPS、JS渲染时间等,我们可以按天维度的生成数据报表,已邮件的数据发送日报。当App灰度上线时,我们会开始小时级别的监控,每过半小时通过IM软件向广播一些关键指标,方便开发者跟踪线上数据的稳定性。分钟级别的监控则是针对关键指标,观察分钟维度上的变化,如果关键指标超过阈值,或者波动过大,就会及时产生告警。
下面我们以一个开发者的视角去看一下外卖容器化架构的监控运维系统。从获取信息的方式上可以分为主动查询和被动推送,开发者可以通过监控工具监控全局和局部数据的变化趋势,也可以分析具体异常Case;也可以从IM工具,邮件等收到相关的推送数据,以便及时响应。在控制运维上,开发者可以通过Eva、Horn等美团内部的灰度系统进行灰度发布,当灰度期发现问题的时候,可以及时地通过停止灰度,版本回滚,关闭入口的方式进行降级容灾处理。
容器化使外卖业务具备了强大的动态化能力,但动态化能力又和需要相应的发布能力来支持,发布能力是我们业务开发质量和效率的重要保障,也是我们容器化建设工作过程中的重点环节,这一节主要介绍一下外卖容器化的发布能力。
从发布能力类型的角度看主要可以分为三种类型:(1)容器内容的发布,包括发布整个页面或者发布页面中的局部模块;(2)配置下发,通过API或其他配置平台,下发布局协议、AB测试、样式配置、功能配置、模板配置、容器配置等,大大提高了业务的灵活度和线上验证能力;(3)灰度、降级下发,通过UUID,用户画像等信息做到灰度发布,降级回滚等控制能力。
从发布资源的的角度看主要分为两种:一种是普通的资源,例如发布一个Web页面,或者通过发布新版API来控制页面局部容器的展示与否和展示的位置,同时我们也可以进行一些AB Test操作;另一种是bundle资源,主要是针对MRN容器和Mach容器,每个MRN容器和Mach容器的资源都会先被打包成一个bundle,然后通过发布系统下发到终端,然后终端解析bundle中的代码和资源,最终渲染页面。
从发布阶段的角度看,可以分为测试阶段、上线阶段、灰度阶段和全量阶段,其中上线阶段是最终的环节,我们增加了很多校验和保护手段来尽量保证上线操作的正确性。
虽然我们具随时备动态发布能力,但正常的版本迭代还是会存在中,所以外卖这边的节奏是周动态迭代+双周版本迭代,这保证了我们的开发工作有个一清晰的周期。在动态发布阶段中最关键的阶段操作上线阶段。以MRN为例,目前外卖业务中应有70多个bundle,再算上测试环境的bundle就有接近150个bundle,只是管理这些bundle就是一个复杂的工作,况且在进行上线操作时还是涉及发布的目标App、App版本的上下界、MRN版本的上下界等,一不小心就会造成操作失误,所以进行上线操作时需要非常谨慎。
我们针对操作上线阶段进行了事务流水线,通过流水线建立保护措施,一个bundle的上线要经历一个流水线的若干操作。首先,操作人根据上线SOP手册进行若干检查操作,同时编写标准格式的发布说明,然后周知相关核心人员后在操作系统上发起上线申请,Leader和QA收到申请后会进行检查并审批,审批通过后还要避开App使用的高峰期或节假日上线,上线后通过灰度发布观察各项数据指标,指标正常后全量发布。
bundle是我们最常发布的资源类型,这里再结合发布工具讲解一下bundle的发布过程。MRN和Mach都是以bundle的形式下发到设备终端的,我们在发布bundle的时候主要会用到两个工具,打包工具Talos和发布工具Eva(美团内部工具)。一个bundle的工程文件主要由三个部分组成:配置文件、源代码和资源文件,其中配置文件用于指导Talos对工程文件进行打包,多个bundle可以共享一份配置文件。当我们准备发布一个bundle时,先找到该bundle在Talos的发布模板,选择发布环境(测试或线上),然后进行一键打包,然后Talos会进行一系列流水线操作,包括Clone代码、配置环境、进行Lint检查、构建和上传等。Talos打包完毕后将bundle上传到Eva系统,然后Eva负责bundle的分包、上线、下线、灰度等操作,最终下发到终端设备上。
未来,我们还将引入美团住宿的MRN-DevOps来进一步的屏蔽当前多系统的问题,降低整个周期管理的成本,特别是发布前的人工检查成本,逐渐实现RD在一个平台上操作从研发到发布运维的所有实现。尽可能地减少人工成本,提升自动化。
上面介绍的是以bundle资源形式的发布流程,过程较为清晰简单。下面再结合外卖首页,介绍一下局部容器化的发布方式。外卖首页是典型的流式列表,在局部容器化的架构下,首页就是由一个个矩形容器以ListView方式布局的,容器分两种,Native容器和Mach容器,Mach容器是一个通用容器,我们可以编写不同的样式模板,下发到终端后交由通用Mach容器来渲染,以此达到只使用通用容器展示不同UI样式的目的,这里涉及了Mach的发布系统。
首页各子容器相当于一块块积木,它们的位置排布、展示与否、模板的选择等最终交由API控制,API具备了控制首页布局,样式展示的能力,而不再是单纯的数据源。同时,首页也涉及了AB能力、灰度降级策略等其实配置项下发系统。可以看到外卖首页的容器化是由多种发布能力配合支撑的,是外卖发布能力体系的“集大成者”。
好的架构是要随着业务的发展,不断演变去适应业务的发展。美团外卖从一个很小规模,每日单量只有几千的业务,逐渐地走到今天,每日单量峰值超过4000万,组织架构也从一个十几个人的团队,逐渐发展到现在多角色、多垂直业务方向,上千人共同协作的团队。移动端上的架构,为了适应业务的发展要求,也经历了组件化、平台化、RN混合化,再到现在向容器化的变迁。
容器化架构相对于传统的移动端架构而言,充分地利用了现在的跨端技术,将动态化的能力最大化的赋予业务。通过动态化,带来业务迭代周期缩短、编译的加速、开发效率的提升等好处。同时,也解决了我们面临着的多端复用、平台能力、平台支撑、单页面多业务团队、业务动态诉求强等业务问题。
当然,容器化架构带来好处的同时,对线上的可用性、容器的可用性、支撑业务的线上发布上提出了更加严格的要求。我们通过监控下载、加载、使用链路上的可用性,来保障线上动态业务的可用性。针对容器,我们利用成熟的测试基建,建设容器的自动化测试来保障容器的可用性。针对发布,我们建设迭代流程,配合发布流水线,将线上的发布变得更为可控。
截止到目前为止,外卖业务经过了几十个动态化业务上线窗口,累积共发版百次以上。未来半年,我们还将进一步从业务需求入手,将业务需求细分归类,让产品侧逐渐建立容器和动态化需求的概念,能够从源头上,逐渐的将业务进行划分,最终使得每个业务需求,都可以归类抽象成可以动态下发的业务和容器能力建设,从而进一步的完善容器化架构的能力和支持更多的的业务场景。
.扫码咨询与免费使用
申请免费使用