您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 订阅
  捐助
ToB 前端 CI/CD 建设实践
 
作者:刘斌
  1641  次浏览      16
2021-5-10 
 
编辑推荐:
本文以百度ToB产品工程化为背景,介绍前端在CI/CD方面最佳实践。
本文来自于微信 KFiveTeam,由火龙果软件Anna编辑推荐。

背景

去年底团队接手负责 30 多个面向 ToB 的平台系统,系统多,需求紧,人力缺口一直存在,主要问题体现在:

前后端部署耦合:前后端资源部署在同一 Web 容器,后端上线会带着前端,同样前端也会带着后端;

研发流程不规范:各平台缺少统一的规范,比如分支规范,部署规范,联调规范等;

研发质量保证:缺少基本的质量保证手段,比如前端单元测试,前后端接口变更流程等;

通过技术手段提高研发效率一直是我们追求的目标。今年通过对业界和公司内部爱番番团队的相关技术调研,决定对现有研发流程进行改进规范,通过 CI/CD 能力建议,提高研发效率和降低运维成本(感谢爱番番团队的 CI/CD 工作!)

今天主要从以下方面来说明 CI/CD 针对 ToB 场景的最佳实践,除了说明做了 What 外,更重要希望能从价值收益上说明 How 和 Why。(注:ToC 与 ToB 各方面差异较大)

什么是CI/CD

简单理解:Continuous Integration/Continuous Deployment

深入理解:基于新兴的 DevOps文化,以管道的形式,通过自动化构建、测试和部署,缩小开发团队和操作团队之间的差距,以到达快速稳定的交付目的。

名词解释

DevOps

DevOps是 Development和 Operations的组合,是一种思想、一组最佳实践、以及一种文化,用于促进应用开发、应用运维和质量保障(QA)部门之间的沟通、协作与整合。以期打破传统开发和运营之间的壁垒和鸿沟。

CI

CI即 ContinuousIntegration的缩写,开发人员将会频繁地向主干提交代码,这些新提交的代码在最终合并到主干前,需要经过编译和自动化测试流进行验证;

CD

CD可对应多个英文名称,持续交付 ContinuousDelivery和持续部署 ContinuousDeployment;

Continuous Delivery

完成 CI 中构建及单元测试和集成测试的自动化流程后,持续交付可自动将已验证的代码发布到存储库。为了实现高效的持续交付流程,务必要确 CI 已内置于开发管道。

持续交付的目标是拥有一个可随时部署到生产环境的代码库。

Continuous Deployment

对于一个成熟的CI/CD管道(Pipeline)来说,最后的阶段是持续部署。作为持续交付——自动将生产就绪型构建版本发布到代码存储库——的延伸,持续部署可以自动将应用发布到生产环境。

涵盖范围

涵盖软件开发全生命周期,作用于各个阶段

基本原则

可靠性

CI 流水线需要很快

独立环境中构建和运行

预发布环境和生产环境等价

流程规范

CI/CD 实施的基本前提条件是根据团队的技术能力现状,制定符合团队实际情况的研发流程规范。

技术全景图

研发流程规范

分支开发,主干测试,RB上线

历史分支保留,确保随时上线发布

未测试代码不带到线上

定期检测同步代码机制,尽量避免冲突

各项检查能力CI上落地,保障高质量交付

代码版本分支是自动化构建的基础,开发团队必须遵守

feature非必需分支,各团队根据实际开发协同场景的复杂度,酌情使用

分支命名规范包含上线日期的做法,仅适合ToB场景

Pipeline规范

编译:使用统一的集群编译

安全扫描:啄木鸟、猫头鹰

静态代码扫描:包含代码规范和潜在的Bug

端测试:自动化,稳定性

云端部署(BOS/CDN)

部署设计

方案一与方案二的区别是index.html放在BOS还是RD服务器?

优先推荐方案一:

与后端解耦更彻底,html的更新可由前端来控制

前端版本号管理放在html里,不用更新version.js,部署更简单

方案一里有些后端可能无法配置转发;

备注:最优方案是由BFE配置转发规则至BOS,不用经RD集群,但目前BFE无法直接转发至BOS。

版本说明

前端静态资源版本一般分两种方式管理:

Hash版本号:基于文件内容的MD5值,取部分长度或全部长度,做为文件的版本号,每个文件都有不同的版本号,适合于增量发布,节约存储空间。例如:index.abcd12.js,manifest.123456.js等

时间戳版本号:以当前构建时间点为准,生成时间文件夹,构建结构部署在时间文件夹下。适合于全量发布。

目前选用时间戳版本号,考虑有如下:

Hash版本,适合容器化部署,比如Docker、Jarvis,每次包括所有资源文件;Bos如果使用Hash,文件夹下同名资源会有很多,显得较乱。

部署目录结构实例

performance
|----
202101281200
| |---- css
| |---- js
| |----index.js
|----
202101291200
| |---- css
| |---- js
| |----index.js
version.js
index.html

index.html 和 version.js 承担版本号维护,每次上线时更新版本号。

单元测试

现状

前端中是大部分是无测试的,国外的一项调查显示,有43%的developer没有做过任何前端相关测试,两个主要原因:

前端属于GUI编程,浏览器很多,要在这么多浏览器上做几轮测试,其实是成本很高,很昂贵;

某些类型的产品当中,很多时候UI界面迭代的更快,测试跟不上迭代;

以上两点导致前端测试不受重视,很多开发可能工作好几年年仍未写过测试。

我们为什么要做单测

ToB 业务 与 ToC 相比:

业务会相对稳定:UI页面稳定变化少

稳定性要求极高:需要频繁的进行回归测试,服务的是付费用户

持续升级迭代:迭代周期相对较长

单测带来的收益:

减少Bug:如今的项目大多都是多人分模块协同开发,当各个模块集成时再去发现问题,定位和沟通成本是非常高的,通过单元测试来保证各个模块的正确性,可以尽早的发现问题,而不时等到集成时再发现问题;

放心重构:对于持续升级迭代的项目,代码不断的在变化和重构,通过单元测试,开发可以放心的修改重构代码,减少改代码时心理负担,提高重构的成功率;

改进设计:越是良好设计的代码,一般越容易编写单元测试,多个小的方法的单测一般比大方法(成百上千行代码)的单测代码要简单、要稳定,所以在编写单测的过程中,如果发现单测代码非常难写,一般表明被测试的代码包含了太多的依赖或功能,需要反思代码的合理性,进而推进代码设计的优化,形成正向循环;

前端自动化测试分层

E2E测试:是一种黑盒测试,测试的是应用的执行是否从头到尾都按设计完成。整个应用程序已在实际场景中进行了测试,其中包括测试组件之间的通信,例如数据库,网络,API等,以及在各种浏览器中执行代码基本上测试一切。设置会花费很多时间,而且成本最高。

集成测试:测试程序之间的交互,例如,UI和API之间的通信。设置所需的时间较短,也不太昂贵。

单元测试:是最小粒度的测试,因为它包括将代码的孤立部分作为单元进行测试。这些单元可以是方法,属性,某一个UI元素点击、输入这样的动作等形式。例如说我有一个函数,通过入参的不同,去覆盖逻辑的不同if else 这样的分支,然后去确认函数的返回值是否与我们预期的一致,代码是否按预期执行,这就需要写断言,对于前两个测试类型来说,这是最快,最便宜的实现方式。

可以看到在金字塔中走的越高,建立我们的测试所花费的时间和成本(越耗时,失败时的信息越模糊,越难跟)就越多。这就是为什么许多项目倾向于专注于单元测试的原因,因为它们可以通过涵盖大多数场景,省时省力的去测试我们的代码。

测试框架选型

Jest表现强劲,在满意度和使用度维度都有不错的表现:

优秀的性能:对测试用例并发测试,只执行发生改变的文件所对应的测试,测试速度快;

集成度高:零配置,默认提供所有的东西,比如 Mock(干掉 Sinon)、Test Runner(干掉 Karma)、Matcher(干掉 Chai)、Test Coverage(内置 istanbul);

守护模式:注重开发者体验,能够在编码的时候帮助我们快速获得测试结果的反馈;

前后端规约

现状问题

随着业务逻辑越来越复杂,前后端分工与协作难免会出现争议,表现在:

存在一定的职责模糊地带,比如数据格式拼装、格式转换等工作,即可以由前端来完成,又可由后端来完成,需要多次沟通讨论,沟通成本高;

前后端分离的模式下,前后端职责进行分工,导致开发沟通成本高,客户体验差(渲染速度慢,耗电高)等问题;

故制定此标准,意在明确前后端分工,减少沟通成本,减少开发维护成本,提升客户体验。

基本原则

后端按业务领域拆分接口,接口数据结构避免与UI展现耦合。前端应关注交互渲染逻辑,根据UI展现需要进行数据拼装和转换;

浏览器处理性能有限,移动端续航能力有限,为了保证流畅稳定的客户体验,在批量计算,排序,分页等大数据量计算时应放到后端完成,后端返回最终结果,而非中间结果;

前端网络环境复杂且不稳定(2G/3G/4G/WIFI),应尽量减少前后端网络交互次数,单页面网络请求数量不建议大于3个;

在遇到对前端渲染速度要求极高,且后端接口数量及数据结构无法满足要求时,可做BFF层(Backend For Frontend)进行接口适配或者采用服务端渲染(SSR)技术完成;

接口遵循最简原则,屏蔽业务实现细节,避免无效字段,避免暴露过多的业务逻辑,避免冗余的多级嵌套格式出现;

其他具体的约定参考阿里的《Java开发手册》里的前后端规约章节。

工程能力地图

价值体现

工程能力地图的价值:

规范研发和上线流程:需求、开发、准入、测试、部署与运行全流程的最佳实践指导;

推荐工具链方案:全流程中推荐符合公司场景的最优工具;

YAPI 平台

价值体现

无论是前端还是后端开发,都或多或少地被接口文档折磨过。前端经常抱怨后端给的接口文档与实际情况不一致。后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新,随着时间推移,版本迭代,接口文档往往很容易跟不上代码。

Swagger 提供了一套规范去定义接口及接口相关的信息,RD 只需要按照规范编写描述文件,就可以做到自动生成各种格式的接口文档,生成多种语言的客户端和服务端的代码,以及在线接口调试页面等等。

YAPI 对各角色同学都有价值:

后端同学实现「代码即文档」,简化接口文档维护;

前端同学实时的,全自动的,更加真实的Mock数据,完成自动化部署服务,及自动联调工具;

QA同学实现基于 Swagger接口数据的契约测试,结合ITP平台,实现自动生成契约测试;

对整体平台的价值,主要体现在稳定性:后端同学修改接口后,前端使用Mock数据,可及时发现接口变更,解决接口变更的流程沟通问题(沟通永远是最高的成本)。

F&Q

问:BOS/CDN部署会不会有安全问题?

答:前端把所有代码都发给客户端,一般不存在部署方面的安全问题。如果真要考虑,可以通过平台域名访问,在网关或 Nginx 转发至BOS资源。

问:BOS部署会不会存在其他问题?

答:照目前我们一年多的经验来说,没有因为BOS部署发生问题。如果要一定要考虑问题,可能事故回滚时,缓存问题可能要注意,在附录中的部署方案中,有详细的实践、实测和方案说明。

问:版本号使用时间戳的做法合适吗?

答:时间戳的版本号适合ToB的场景,上线频率较少,不像ToC每天都有很多上线。

   
1641 次浏览       16
相关文章

为什么要做持续部署?
剖析“持续交付”:五个核心实践
集成与构建指南
持续集成工具的选择-装载
相关文档

持续集成介绍
使用Hudson持续集成
持续集成之-依赖管理
IPD集成产品开发管理
相关课程

配置管理、日构建与持续集成
软件架构设计方法、案例与实践
单元测试、重构及持续集成
基于Android的单元、性能测试