美团外卖持续交付的前世今生

总第381篇

2020年 第4篇

美团外卖自2013年创建以来,业务一直在高速发展,从早期单一的美食业务发展成为包含闪购、跑腿、闪付、营销、广告等在内的平台业务。每个业务团队虽然都有不同的业务形态,但是几乎都有相同的诉求:需求能不能尽快的上线?本文将从外卖的历史实践中,浅谈一个好的持续交付需要综合考虑哪些关键因素,希望对大家有所帮助或启发。

0. 前言

美团外卖自2013年创建以来,业务一直在高速发展,目前日订单量已突破3000万单,已成为美团点评最重要的业务之一。美团外卖所承载的业务,从早期单一的美食业务发展成为了外卖平台业务。目前除餐饮业务外,闪购、跑腿、闪付、营销、广告等产品形态的业务也陆续在外卖平台上线。参与到美团外卖平台的业务团队,也从早期的单一的外卖团队发展成为多业务团队。每个业务团队虽然都有不同的业务形态,但是几乎都有相同的诉求:需求能不能尽快地上线?

然而,Native应用的发布依赖于应用市场的更新,周期非常长,非常不利于产品的快速迭代、快速试错。同时,作为平台方,我们需要考虑到各个业务团队的诉求,统筹考虑如何建立怎么样的模型、配套什么样的技术手段,才能实现最佳的状态,满足各业务更短周期、高质量的交付业务的诉求。本文会首先回顾美团外卖从早期的月交付,逐渐演变成双周交付,再从双周交付演变成双周版本交付配合周动态交付的过程。然后从外卖的历史实践中,浅谈一个好的持续交付需要综合考虑哪些关键因素,希望对大家有所帮助或启发。

1. 交付模型

一个需求从产生到交付再到用户的手上,要经历需求调研、需求分析、程序设计、代码开发、测试、部署上线等多个环节。在整个过程中,由于涉及到不同角色的人员,而不同角色人员的认知存在差异,不同的程序语言存在差异,不同的开发方式也存在差异。在整个交付需求的过程中,还面临着需求可能会被变更、交付周期可能会被变更等各种情况。这些情况使得需求的交付变得非常复杂、不可预期。

而软件开发的首要任务就是持续、尽早地交付有价值的软件。怎么解决这一问题,是软件工程一直在研究的话题。早在20世纪50年代,软件领域就在积极地探索设计什么样的模型可以解决这些问题。常见的包括瀑布流模型、迭代模型、螺旋模型、敏捷模型等等。由于篇幅原因,本文不再做详细的介绍。

2. 什么是持续交付

关注持续交付,不同的企业、不同的团队站在不同的角度存在不同的定义。《持续交付2.0:业务引领的DevOps精要》一书认为,站在企业的角度,将持续交付定位为一个产品价值的开发框架,是一个工具集,其中包含了一系列的原则和众多实践,帮助提升企业的内部运转速度和交付效率。

从知乎话题“如何理解持续集成、持续交付、持续部署”,我们可以看到大部分研发团队,会从软件研发的角度进行定义,他们将软件的开发步骤拆解为持续集成、持续交付、持续部署,其中持续集成指开发人员从编码到构建的过程。持续交付指将已经集成构建完成的代码,交付给测试团队进行测试的过程。持续部署指将测试通过的软件交付给用户的过程。而产品团队会站在产品的角度来看,他们认为持续交付,是从需求的PRD文档提出来,到用户能够感受到这个需求的周期。

从美团外卖业务的角度,我们可以将持续交付定位为“外卖用户”和“外卖团队”之间的紧密反馈流。而外卖团队涉及到PM、UI/UE、RD和QA角色。如下图所示,产品同学从市场或用户的需求和反馈中收集到需求,转换为需求PRD文档,交由设计交互同学设计成期望用户所见的界面和行为,然后交给研发团队进行调研实现。研发团队实现后,再交给测试团队进行测试。等测试团队完成测试后,提交到应用市场,最终交付到用户手上,这个过程是本文所考虑的交付。“持续”指的是,外卖团队将外卖的业务拆分成不同维度的子业务,每个子业务持续通过这个迭代流程不断地优化各个子业务达到最优,从而使整个外卖业务达到最优。

3. 外卖持续交付模型的变迁史

3.1 外卖的早期交付模型

早期外卖的交付模式为“串行交付”,一个版本完成后,开启下一个版本。整个交付过程包括需求评审、需求开发、迭代提测、一轮提测、二轮提测、三轮提测、灰度提测和全量发布8个环节:

由于美团的外卖业务是一个双平台业务,需要同时开发外卖App和美团App。在人力安排上,我们会分成两个组,App组和频道组并行开发。App组开发当前的版本业务,频道组同步上个版本的业务到当前的美团平台版本。整个版本周期耗时六周半左右,遇到节假日会顺延,全年能发版11~12个,版本交付周期如下图所示:

交付模型中关键点

  1. 需求评审分为主打需求、非主打需求和统计需求。
  • 主打需求:客户端开发10d之前进行评审,评审8d后UI提供初稿,评审14d后UI定稿。
  • 非主打需求:两个三方评审窗口,窗口1为窗口2的前5d,窗口2为上一版本二轮测试地一天,UI定稿需要在客户端开发第一周内完成。
  • 统计需求:需求收集截止到立项评审前一天,三方评审为非主打需求评审后第二天。
    服务器在需求评审后,客户端开发第一周前,提供接口文档。
  • 客户端开发周期为两周,客户端开发第5个自然日API提测,客户端开发第5天发迭代提测包,第二周结束发提测包。
  • QA验收提测包,一轮3d、二轮3d、三轮1d。
  • 灰度3d,需避开节假日前发灰度。
  • 全量发布电子市场。
  • 单月发版优缺点

    优点:

    1. 每个版本可根据当版的情况控制版本的周期,可同时支持多个大需求的并行开发。
    2. 版本较为固定,各角色的分工明确,开发人员在开发期较为专注,开发效率高。
    3. 测试周期长,App能够得到充分的测试。

    缺点:

    1. 版本迭代周期较长,从需求评审开始到需求灰度,需要6.5周。无法满足日益增长的业务诉求,对于一些尝试性项目,无法满足PM急迫上线验证效果的需求。
    2. 发版频率低,每年只有11~12个版本。对标其他互联网公司,业务产出相对较低。
    3. 每个角色的利用率不高,如RD在开发期的时候,QA处在待测试状态。

    3.2 双周迭代的交付模型实践

    为了满足日益增长的业务诉求,我们提出了双周发版的交付模式,从而实现业务的快速迭代。贯彻的总体原则为:评审、开发、测试完全并行,以两周为固定周期,以需求维度持续交付。

    3.2.1 双周迭代模型

    在切换双周迭代模式之前,需要落地一些准备工作。例如统一版本排期的时间表、确定项目中各个角色的交付时间,让PM、UI、客户端RD、服务端RD和QA,各角色都能够清晰的知道自己接入的时间点,并在规定的时间点交付内容。由于各角色的任务和分工得到了明确,减少了协作中的沟通成本,各角色也可以如齿轮一样,持续产出交付给下游团队,整个交付周期效率得到了有效的提升,一个版本的周期缩短为5.5周,发版次数上升到22~24版本。

    版本各个角色分工详情示意图如下所示:

    双周模型中关键点:

    • W1需求评审:周三PM组织三方评审业务需求+埋点需求+UI需求。
    • W2排期:周三API RD出排期,周四客户端RD出排期,UI产出视觉初稿。客户端RD排期需细化至需求可提测时间点,便于QA、PM和UI提前协调测试、验收时间。
    • W3接口评审+服务端先行开发:接口文档,UI资源周四前到位。
    • W4客户端开发,周四API提测(最晚)。
    • W5客户端开发+冒烟测试:RD开发完后直接冒烟测试,以需求维度交付给QA,不需要等到最后一天集中冒烟测试;需求交付后,PM与UI可介入验收环节。
    • W6客户端测试+周二服务端上线:客户端一轮测试结束前,PM与UI应完成需求验收。
    • W7灰度+周二全量理想状态一个版本的周期为五周半。
    • W3时,PM会继续组织三方评审;W4时,API继续开发下版本;W5时,客户端RD会继续下一个版本的开发。

    3.2.2 分组交付

    双周迭代模式的变化也推动我们在人力分配方面的改进,人力安排演变经历了三个过程:

    在双周迭代的过程中,客户端的交付是连贯的,理想状态是每个RD可以隔版进行需求开发。但是大家都知道,写完需求是不可能没有Bug的,需求的估时也不可能都是5的倍数,这样就会造成很多RD既要开发当前版本,又要解决上个版本的Bug。这间接引入了2个问题:

    1. 个人成长方面:单个RD可能会在同一个时间段内,出现又要评审需求、又要开发需求、又要改Bug,时间长了会堆积疲惫感。另外,需求的估时不是5的倍数,每个版本单个RD是否能满人力工作是不确定的,不利于资源的分配。
    2. 人力分配合理性:版本的需求是存在不确定性的,而App的需求熟悉度是存在和RD一一对应的。当熟悉度最高的RD在上个版本的时候,当前版本的版本主R就会很头疼,是“能者多劳”还是“合理分配”,给人力分配的合理性又带来了新的挑战。

    后来我们经过内部研究,提出了AB分组的方案,保证AB组是隔版本进行开发。当组内需求拆分有冲突时,需要在内部协调消化,避免RD出现每个版本都会参与开发的情况发生。

    AB分组施行以后每个RD都是各版本开发的,不会出现同一个时间段内,要处理上个版本的Bug和当版需求的情况。但业务的熟悉度和RD的强对应关系还是没有得到解决,所以我们就进一步的思考,提出采用业务维度AB组。如下图所示,我们先将同学进行业务划分,在以业务组进行AB的划分。当然这个业务组人员的数量需要考虑业务的规划情况,当某一个业务需求量增长上来的时候,业务组的大小也需要同步进行增长。

    3.2.3 双周迭代的优缺点

    双周迭代的优点:

    • 提高了业务迭代效率,从而提升了业务的产出,以一月能够完成二个版本的交付速度,持续地交付版本,达到一年交付20-24个版本的交付目标。
    • 在人力整合利用上更加合理化,各角色都能够持续的产出,版本的交付周期变为5.5周。

    双周迭代的不足:

    相比之前的当月发版,虽然双周迭代带来一定收益,但还是存在一些客观的问题:

    • 从评审到交付,发布周期还是太长,产品快速上线的诉求依然不能得到很好的满足。
    • 敏捷性受到一定影响,对于特定需求和小需求不是很友好。

    3.3 双周结合周交付的模型实践

    外卖在历经了双周迭代后,一定程度的缩短了版本交付周期,提高了业务迭代效率,优化了人力安排,但是仍然存在一些问题。对于一些简单的需求来说,像外卖中“我的页面”模块的点击热区扩大(“我的页面”已经是RN页面),实际上开发只需要2天,却仍然要跟随版本迭代的节奏,5.5周后才能上线,需求交付周期仍需进一步缩短。另外,外卖自研动态化框架Mach在大量业务的应用落地,多种开发流程及交付需要,使得双周交付越来越难满足外卖业务版本迭代及交付的节奏。

    3.3.1 动态化能力的建设

    为了满足业务需求的快速上线及外卖面临的包体积的压力,外卖引入了动态化来解决此类痛点问题。外卖动态化能力建设的思路主要是:核心流程页面区域动态化,区域动态化方案采用外卖自研的Mach动态化框架,核心流程采用区域动态化,保证页面的稳定性及用户体验,非核心流程页面MRN化(Meituan React Native),通过MRN来替换所有的低PV页面,下线Native页面。具体技术细节可参考《React Native在美团外卖客户端的实践》一文。

    目前外卖低PV的MRN页面数量已达:56/67。已经覆盖了外卖所有的低PV页面,除核心流量页面均为MRN页面,从页面数量维度,MRN页面占比已达83.58%。

    Mach区域动态化覆盖了首页核心流量区、二级金刚页、订单页、点菜页及搜索页。目前上线的模板数已达43个。

    3.3.2 双周迭代&周迭代

    在完成了外卖动态化能力的建设后,外卖业务逐渐演进出了两类需求:

    1. 主版本需求,主版本需求主要是Native方式实现,结合少部分动态化需求。
    2. 敏捷开发需求,主要通过动态化和敏捷模型的加入实现高效的版本迭代,动态化主要指上节所介绍的动态化能力的建设,敏捷模型采用前文所说的敏捷模型。

    面对上述两类需求,现有双周迭代及分组交付流程,对于部分特定需求及小需求不太友好。目前无法做到需求最快速上线,如上述“我的页面”点击热区扩大。

    因此,我们在双周迭代的基础上,演进出了现在的双周迭代结合周迭代的交付模型。交付模型图如下:

    双周迭代结合周迭代的交付模型是在原有双周迭代的基础上,保持主版本需求双周迭代不变,增加每周的动态上线窗口。以每周二为动态上线窗口时间,周五为提测DeadLine,根据动态化需求的开发及提测时间来动态搭车上线。

    目前,外卖的周迭代需求分为两类:

    1. 纯动态化需求,根据需求开发及测试排期选择上线窗口,搭最近一次的上线窗口。
    2. 动态化结合Native需求,跟随主版本交付流程,在提测周发版上线,主要面向敏捷迭代内容。

    纯动态化需求由于不依赖Native发版,无需依赖Native的全回归,开发完成可随时提测,提测后功能测试完成即可上线,可以做到需求的最快速上线。敏捷迭代内容,不依赖主版本的评审,采用自主评审,自主决策跟版的策略。

    而多种动态化方案的开发模式,需要统一的动态化发版及上线能力的支撑。外卖周迭代发版及上线具体可以分为两步:

    1. 发版。将动态化模板进行打包,得到Bundle并上传,通过Talos平台(美团内部自研)进行打包。Talos是基于前后端分离思想设计的一套前端DevOps解决方案。
    2. 上线。将通过Talos打包得到的Bundle上线发布,发布通过EVA客户端动态分发平台进行线上发布。

    具体流程如下图所示:

    截止目前,外卖周迭代发版经过了15个上线窗口,共计发版50+次。

    双周迭代结合周迭代的交付方式进一步缩短了版本的交付周期,从需求收集评审到需求上线对于敏捷需求可以缩短到3.5周。对于纯动态化需求可缩短到1周,最终做到了需求评审做到了需求的快速上线、快速验证、快速修复,敏捷迭代。

    3.4 自动化版本管理系统

    在施行了双周迭代结合周迭代后,大大缩短了需求的上线周期,但是同时也提升了版本流程管理的复杂度。怎么样保证版本流程的正常运作呢?外卖C端涉及开发人员分为A、B组及敏捷开发人力;同时涉及美团频道及外卖App双平台,需要考虑双平台的版本迭代周期;涉及阶段多,各阶段都需要人工操作,执行事件多,双端执行事件总计40+;涉及双版本并行开发,仓库代码管理复杂。

    原有版本迭代流程,版本各阶段的所有事件都由相应负责人执行。

    1. 分支创建、版本降级检查、每日QA包号周知,仓库集成及基础库同步、打包,提测邮件等都由迭代工程小组人员负责执行。
    2. 仓库拉出Release分支,提审灰度后分支合并、集成、发版由外卖各仓库负责人负责执行。
    3. 周迭代、迭代、一轮、二轮、三轮提测阶段冒烟周知,则通过排班的形式,在冒烟提测当天,由人工提醒并监督。

    在版本迭代流程上会耗费了大量的人力。如何解放这部分人力,让整个版本迭代流程自动化,做到无人值守,减少人工操作的失误。这是此前外卖前端技术团队面临的非常头疼的问题。

    在我们规范了双周迭代&周迭代的流程后,版本各阶段的时间能够基本固定。为了能够做到自动化,我们把版本各阶段需要人工操作的事件整理归类,把事件确定到当前版本的固定一天固定时间点。以一个版本为例,我们整理归类如下:

    确定好所有事件的执行时间后,我们便尝试把所有需要人工操作的事件自动化。并通过在确定的时间去触发,来做到整个版本流程的自动化。

    早期的版本管理,我们依托于Gulf(美团内部日期管理系统)、QA-Assistant系统(美团内部事件通知系统)、CI及大象(美团内部通讯工具)消息,通过在Gulf系统提前配置好各版本各事件的时间,并通过QA-Assistant配置人员名单及消息,在固定时间节点,Gulf去触发QA-Assistant,通过上述方式,做到了各类提醒的自动化,并且在CI上部署上自动化Job,由人工触发。

    但是通过这种方式,存在一些弊端:

    1. 版本各节点事件都需人工单独一个个配置,且Gulf和QA-Assistant系统的触发一直需要关注。
    2. 仍然需要大量人工操作,只能做到流程的半自动化,人力还是无法做到解放。
    3. 版本流程无法做到可视化。

    为了解决上述问题,我们和Tide版本管理系统(美团内部组件)共建,实现了现在的外卖C端自动化流程管理。

    以Gulfstream的版本排期为基准,通过Tide版本管理系统进行事件触发。通过脚本将CI、Stash仓库管理系统、HyperloopX发版打包系统、大象整合,做到代码/分支管理自动化、打包集成自动化、周知提醒自动化、版本流程可视化。

    在版本开始前配置好当前版本,后续则会在版本的每个关键节点自动执行需要执行的事件。

    Tide版本管理可视化界面如下,按照版本各阶段及时间线顺序排列:

    各类事件提醒及执行通知如下:

    各类提醒确认结果即时展示:


    3.5 CI建设

    在CI建设方面,我们工作主要集中在以下5个阶段:准备阶段、PR检测、开发阶段、提测阶段和发版阶段。

    下面介绍三个CI工作中,外卖场景下的特定检查:

    • Aimeituan工程独立编译自动配置:同事反馈配置团App源码依赖的配置项较繁琐,切换开发分支时需要反复进行配置,为了提供RD的开发体验。通过脚本自动修改WM提测分支的源码依赖配置项,只需修改Aimeituan的gradle.properties一个属性实现源码依赖切换,实现一键切换的功能,提高版本开发效率,优化项包括:
      • 业务方依赖只保留团首页和外卖业务。
      • 只保留开发调试必要的插件:ServiceLoader和WmRouter,提高编译速度。
      • 只保留调试Flavor:提高编译速度。
    • 业务库检测是否有PR未合入:版本快速迭代对代码管理也带来了挑战,发生了几次因为RD未及时合入代码,影响QA提测进度的问题。因此在打提测包之前增加了一个检测环节,如果检测到有PR未合入提测分支,将在大象群统一周知发起人,提高版本的交付质量。
    • 定时检测壳工程是否有更新,自动触发打包,保证QA第二天能回归前一天所有的修改,避免测试返工的问题,提高版本测试有效性。

    总结

    • Aimeituan独立编译配置从5~10分钟(同事反馈从修改配置到同步完成的耗时)降低到45s左右,优化了80%~90%。

    • 在经过了几个版本的实践证明,自动化检测PR合入是有必要的,而且能够有效降低开发人为失误导致漏提交代码发生的概率。

    • 每天早上同步Aimeituan的Release分支,及时周知负责人同步结果,减少人工Check的重复工作。

    3.6 部署发布

    部署和发布,对于移动App来说,已经到了最后的环节。我们认为的部署行为主要指将一个还处在测试的版本提交到测试环境,然后让QA进行测试,发布行为主要指将测试完成的稳定版本提交到线上环境交付给用户。当然对于部署和发布,每个团队都可以思考自己的定义。例如我们进一步的细化部署和发布的行为,可以划分为部署测试环境、部署线上环境、部署回滚、发布灰度、发布灰度监控、发布全量、发布回滚、发布监控等等。下面主要介绍外卖业务在部署发布中,建设的业务事务流和无人灰度监控。

    3.6.1 发布事务流

    发布在整个交付过程中是最重要的一环,而这个环节涉及的角色主要是RD和QA。我们需要明确的定义这个环节RD和QA的事务,避免角色间沟通不畅,跨角色的任务不清的问题。外卖通过持续的优化流程,明确流程的操作行为,来监督流程的正常运行,形成当前的事务流,如下图所示:

    这里需要重点讲解图中的关键点:

    • 事务流中,RD负责交付代码到测试环境,QA同学负责测试环境的和线上环境的验证。RD和QA角色按照时间顺序,各自前面工作和后面工作,事项归属清晰明确。
    • 流程中设置TL Approve和QA Approve。同时RD作为代码的完成者,只具备测试环境的部署权限,最终线上的权限由QA掌控,做到了上线的双角色Check,避免了RD即是“裁判员”又是“运动员”的情况。
    • 当完成测试时候,部署线上环境和线上环境发布,都做到自动执行,通过自动化的手段节约重复的工作。

    3.6.2 无人值守灰度

    一个功能上线,往往要经历灰度到全量的过程。由于灰度已经是到了交付到用户手上的最终环境,灰度前的检查和放量都非常重要,需要做到万无一失。灰度的次数往往是全量次数的2~3倍,这使得灰度的成本在整个交付流程中也变得非常高。理想情况下,我们希望发布前的流程都做到自动化,灰度的过程,也无需人工参与,自动的放量、停灰、全量,出现异常自动执行灰度SOP、监控项也在灰度的时候自动开启,出现异常自动同步信息给相关方。但在实际过程中,由于平台的差异,部分环节还是很难做到,例如iOS的发布。下图是外卖业务无人值守灰度的流程:

    其中几个关键点:

    • 起始点来源于我们录入的GulfStream日期。由于双周迭代后,版本的迭代周期是可预期的,所以能够以季度维度录入GulfStream中,由此处触发整个链条的启动。
    • 我们利用Tide版本管理系统,将版本的日期自动读入,在需要发布的节点前,自动检查,做好自动化检查。部分无法自动化的,由Tide系统提醒RD和QA去做检查。
    • 定义好灰度放量策略,在发布时按照设定策略,自动发布放量。
    • 外卖业务非常复杂,监控的内容也很复杂,对这个环节不是很熟悉的同学,是很难胜任监控运维工作的,自动化更是无法执行。因此外卖的策略是将监控报警标准化,制定SLA,分级别定义监控、报警、预案、执行人,当版本发布后,触发监控Job,以分钟级去CAT(已经开源)、Sniffer、Crash等等平台去拉取当前灰度版本的数据和定义的指标比较。如果在合理定义范围内,继续监控。如果出现异常,大象定向通知相关处理人。这样使得灰度的自动化监控工作的执行过程是可操作的。

    4. 外卖持续交付的总结

    美团外卖业务,应该建立怎么样的模型、配套什么的技术手段,才可以在更短的周期内,高质量地交付业务,满足各团队的发展呢?我们从早期的单月交付,到双周交付,再到双周交付结合周交付,我们在不断地尝试和演进外卖的持续交付模型。随着不断的深入了解,我们发现这是一个很大的话题。到目前为止,美团外卖团队在这条路上只能算得上是刚刚起步。不过,在实践的过程中,我们也逐渐地摸索到一些经验,在此分享一下我们的思考。

    4.1 遵循原则

    首先我们认为持续交付需要遵循以下的原则。

    持续自动化

    在我们整个交付的过程中,有大量的工作是会重复进行的,如果我们不能将这些重复的操作逐渐变成自动化,我们就需要频繁、反复地去做一些看不到收益,但是又不得不去进行的事情。随着交付的内容变得越来越多,交付的速度要越来越快,团队的疲劳感会越来越重,最终疲于奔命。在实际的工作中,由于发布的形态流程的不标准、生成环境和数据的不一致,我们无法一次性做到所有环节自动化,但这不影响我们先站在全局去思考,去持续地拆解子问题,将子问题逐渐地变成自动化。随着整个交付过程的自动化程度不断提升,整个流程会变得简单容易,这样开发人员可以更加聚焦在完成功能本身的工作上。

    前置解决

    大部分人心理上对于比较麻烦、比较痛苦的事项,都倾向不做或者拖到最后去做。由于存在这样的心理,如果在交付流程中遇到问题,我们的方案很容易掉到一个陷阱中,倾向保持现状或延后再处理。但是,对于一个多人协作交付的业务来说,这是非常不可取的,越往后处理,对整个交付的影响越大,处理效率越低下。举个例子来说,一个PR可能导致一个历史功能不可用,如果我们在这个同学提这个PR的时候就拦截到,那么只会影响这个同学,也不需要回溯问题;如果延到代码集成环节,那么就需要想办法去找到是谁,然后因为什么原因提这段代码,本次集成就可能直接导致失败,影响其他正在集成的代码。如果拖到测试环境,那么就会涉及至少RD和QA等两个角色去追寻这个问题。所以在持续交付的过程中,我们尽可能尽早地将问题在刚出现时就解决掉,保障整个交付流水线的通畅。

    版本化

    在我们持续交付的过程中,要将每个环节尽可能的版本化。不仅仅从代码方面版本化,针对数据、配置、环境都可以进一步的版本化。版本化的好处是不言而喻的,首先在实现版本化的过程中,尽可能地将各个环节解耦开,让环节和环节之间没有强依赖。当某一个环节出现异常的时候,我们可以很快地降级到无问题的版本,从而保障整个流水线的持续运转。版本化的另一个好处,就是可回溯,当出现异常的时候,我们可以很快地对比历史版本和当前版本的差异,缩小范围,快速的定位问题。

    持续反馈

    在整个交付的过程中,每个环节都可能出错。当出错的时候,需要快速地反馈到相关的负责人。该负责人也需要尽快地将反馈的问题处理,给予一个稳定的版本。如果没有反馈这个环节,导致了整个交付流水线被阻塞的人,可能完全不知道自己造成了阻塞。另外,在一个功能的交付过程中,可能会有多次提交代码、多次集成、多次测试,如果每次是什么样的结果,都无法得到反馈,那么整个交付的风险会逐渐累积。只有将问题更早地反馈、更早地处理,才能有效地降低整个功能交付的风险。

    持续分解改进

    不管我们当前将整个交付的过程做到了多么高效,未来随着业务的发展,组织成员的加入和离开,交付的过程都在逐渐发生衍变。而这个变化,随着时间的推移,交付的效率又会开始逐渐下降。如果要长久地保持交付效率能够有持续的改善,我们需要不断地对抽象的交付过程进行分析,层层剥离,将整个交付过程转变成一系列小而可以解决的问题,然后持续地解决这些小问题。

    不管我们当前将整个交付的过程做到了多么高效,未来随着业务的发展,新成员的加入和离开,交付的过程都在逐渐发生衍变。正如《谈谈持续集成,持续交付,持续部署之间的区别》一文提到的“持续部署是理想的工作流”一样,想一劳永逸解决所有问题是一种理想的工作状态。

    随着时间的推移,交付的过程会出现新的问题,交付的效率又会开始逐渐下降。如果要长久地保持交付效率能够有持续的改善,我们需要不断地对抽象的交付过程进行分析,层层剥离,将整个交付过程转变成一系列小而可以解决的问题,然后持续地解决这些小问题。

    4.2 关键步骤

    针对上述原则,我们可以进一步地来指导外卖持续交付中的关键过程。通过前文所讲,我们认为持续交付就是从产品同学收集到需求,提交到研发团队,最终形成稳定的产品交给用户手上的过程,针对这个过程主要细化包括:

    提需求

    持续交付启动的第一环对应的就是PM提需求。俗话说“万事开头难”,“提需求”看似是一件容易的事情,其实背后是一个非常复杂的问题,涉及到策略选择、动态规划、排队论等一系列的理论。往往在大部分的团队中,“提需求”被认为是最简单的事情,这使得整个交付流程后续的工作,无法高效开展。我们细分析下,需求根据大小可以分成大需求、小需求;根据优先级可以分成高、中、低需求;根据开发的人员不同,又可以分成前端需求、后端需求、策略需求等等。

    需求提出来后,怎么快速地判断出如何划分这个需求,需求的优先级是什么,需求的上线时间怎么样,谁来做这个需求,这个需求会涉及到谁。在涉及到这个需求和其他需求的比较时,才能回答刚才提到的问题,这又涉及到需求的定义,需求产出比的基线问题。在外卖的交付模型中,对于“提需求”,主要遵循的是组织管理原则,即以组织结构为单位,当前组织下的PM给予当前组织下的RD提出需求,需求的优先级也以当前组织下的事项进行综合考虑。这样的好处,不言而喻,比较敏捷。劣势是当遇到跨组织需求,工作成本会急剧增加。

    同时,我们通过交付模型,将提需求的时间点可预见,在每次提需求的环节,严格要求每一组织下的需求给予明确的优先级。每次提出的需求数量、需求评审时长标准化。并且配套标准的需求模板,让PM在提出需求时,自我完成需求边界检查,需求涉及方的前置沟通。通过这样的组织管理手段、模板管理手段、流程标准化手段,来尽可能地保证提需求的质量。

    提代码

    当单个RD同学认为已经基本完成了功能开发后,就会进入到提代码的环节,也可以叫做代码集成环节。这个环节是个人行为和整体交付产生对接的环节。在这个环节我们要确保个人的行为不影响整体的流水线的进行。如何保障,我们采用的手段主要是本地检查+CI检查+集成测试。当代码检查通过后,代码的集成是自动完成,无需个人干预。

    不过,这里也存在一个矛盾点,如果本地检查+CI检查项+集成测试项越来越多,检查的时间将会非常长,这将会使得每次提交代码变得异常痛苦。而如何解决这个问题?最好的手段,我们认为是通过持续优化代码的架构,来让每次RD的代码修改尽可能范围小。这样对于有特定范围的修改,本次CI检查就存在可简化的可能性。

    部署测试

    当完成代码集成后,就需要进入到测试环节了。那首先我们需要将代码部署到测试环境,因为外卖主要提供App供测试包,所以我们的部署,主要就是打出App包来,周知QA测试。目前外卖的测试,分位一轮新功能测试、二轮全回归测试、三轮主流程回归测试。新功能因为新引入,可能存在前置条件,而在本次测试的过程中,存在需要编写自动化用例和人工测试的用例。

    但对于老功能,我们希望未来能够尽可能地采用自动化为主的方式。而在实践的过程中,我们发现自动化测试的一个很重要的前置条件是,数据和环境的可配置性、稳定性。试想下,数据不稳定,一会返回是空,一会返回不为空,是没办法自动化测试校验的。对于这个问题,目前我们的思路是通过建立各环节下根据标准协议定义的Mock数据,将复杂的全链条,拆分成不同节点,在通过配置去控制数据的环境。通过保障每个环节下的质量,来确保整体的质量。

    线上监控

    保障外卖业务正常线上运行,会需要监控多项的指标。对于如何做好线上监控,我们的思路是设立好各项基线的标准基线,通过脚本获取线上的版本,当检测到新版本,就会自动的创建当前版本的监控。当监控发现线上指标的值和设定的指标基线出现降低时,发生报警行为。而自动化监控最需要考虑的是误报率的问题。版本的发布正常通常又会分为2个阶段,灰度阶段和全量阶段。

    全量阶段量大,比较稳定,误报率较低。而灰度阶段,量小,不稳定,容易出现误报。而解决这个问题,最好的办法是,本次灰度对比上一次灰度的指标,而非对比上一次全量的指标,维度一样,可以有效地减少误报率。

    5. 展望

    当前,美团外卖业务仍然处于快速增长阶段,建立怎么样的流程、配套什么的技术手段,才能满足在更短的周期内,高质量地交付业务,进而满足各个业务的发展呢?毫无疑问,持续交付是解决这个问题的重要一环。但针对持续交付这个主题,美团外卖也算是刚刚起步。

    未来我们的建设主要集中在2个方向,精细化运营持续集成和建设自动化测试。如上文所述,随着业务越来越复杂,涉及的角色越来越多,代码集成的管控需更加严格,而严格的代码集成管控将增加团队成员每次提代码的痛苦。如何做到差异化的检查和准入,将是未来持续集成的建设方向。

    我们可以针对不同类型的PR,不同时间节点下的PR,实施不同的差异化定制规则检查,在合入质量和检查周期上寻找到一个合适的平衡点。另外对于测试环节,目前美团外卖还是主要集中在人工保障环节,大量的测试Case。我们希望未来能够尽可能地采用自动化为主的方式进行测试,而让QA可以集中精力测试新功能或非常边界异常的场景验证。

    6. 参考文献

    • 如何理解持续集成、持续交付、持续部署
    • 谈谈持续集成、持续交付、持续部署的区别
    • 持续交付2.0:业务引领的DevOps精要

    作者简介

    • 晓飞,2015年加入美团,美团外卖团队技术专家。
    • 王鹏,2017年加入美团,美团外卖团队高级工程师。
    • 江伟,2018年加入美团,美团外卖团队高级工程师。

    一、 背景 人脸检测技术是通过人工智能分析的方法自动返回图片中的人脸坐标位置和尺寸大小,是人脸智能分析应用的核心组成部分,具有广泛的学术研究价值和业务应用价值,比如人脸识别、人脸属性分析(年龄估计、性别识别、颜值打 ...