9 持续交付理论总结及面试
1 量身定制你的持续交付体系
虽然持续交付着重打造的是发布流水线的部分,但它所要达到的目标是在“最终用户”和“研发团队”之间建立紧密的反馈环:通过持续交付新的软件版本,以验证新想法和软件改动的正确性,并衡量这些改动对软件价值的影响。
2 配置管理
代码分支策略的选择
- 主干开发(TBD)
- GitHub Flow 是 GitHub 所使用的一种简单流程。该流程只使用 master 和特性分支,并借助 GitHub 的 pull request 功能。
依赖管理
Maven 使用 XML 格式的文件进行依赖配置描述的方式,叫作 POM(Project Object Model ),以下就是一段简单的 pom.xml 文件片段
在 POM 中,根元素 project 下的 dependencies 可以包含一个或多个 dependency 元素,以声明一个或者多个项目依赖。每个依赖可以包含的元素有:
groupId、artifactId、version: 依赖的基本坐标; / type: 依赖的类型,默认为 jar;/ scope: 依赖的范围;/ optional: 标记依赖是否可选; / exclusions: 用来排除传递性依赖;
代码回滚
- 第一种情况:开发人员独立使用的分支上,如果最近产生的 commit 都没有价值,应该废弃掉,此时就需要把代码回滚到以前的版本。
- 第二种情况:代码集成到团队的集成分支且尚未发布,但在后续测试中发现这部分代码有问题,且一时半会儿解决不掉,为了不把问题传递给下次的集成,此时就需要把有问题的代码从集成分支中回滚掉
- 第三种情况:代码已经发布到线上,线上包回滚后发现是新上线的代码引起的问题,且需要一段时间修复,此时又有其他功能需要上线,那么主干分支必须把代码回滚到产品包 V0529 对应的 commit。
代码回滚必须遵循的原则
- 集成分支上的代码回滚坚决不用
reset --hard
的方式,
三种典型回滚场景及回滚策略
- 个人分支回滚
- 集成分支上线前回滚 revert before merge request
- 集成分支上线后回滚
$ git fetch origin
$ git checkout master
$ git reset --hard V0529 # 把本地的 master 分支的指针回退到 V0529,此时暂存区 (index) 里就指向 V0529 里的内容了。
$ git reset --soft origin/master # --soft 使得本地的 master 分支的指针重新回到 V05javascript:;30,而暂存区 (index) 变成 V0529 的内容。
$ git commit -m "rollback to V0529" # 把暂存区里的内容提交,这样一来新生成的 commit 的内容和 V0529 相同。
$ git push origin master # 远端的 master 也被回滚。
3 环境管理
发环境,功能测试环境,验收测试环境,预发布环境,生产环境这五个大套环境。
了解各种配置方法
- 构建时配置
以 Maven 为例,实现多环境的构建可移植性需要使用 profile。
profile 是一组可选的配置,可以用来设置或者覆盖配置默认值。通过不同的环境激活不同的 profile,可以实现构建的可移植性。
maven initialize –Pdev & maven initialize –Pprod
- 打包时配置
- 运行时配置
4 构建集成
构建的提速
- 级硬件资源
- 搭建私有仓库
- 使用本地缓存
- 规范构建流程
- 以 Java 构建为例,Enforcer 检查、框架依赖检查、Sonar 检查、单元测试、集成测试这些步骤,并没有放在同一个构建过程中同步执行,而是通过异步的方式穿插在 CI/CD 当中,甚至可以在构建过程之外执行。
- 善用构建工具
- 以 Maven 为例
- 设置合适的堆内存参数
- 使用
-Dmaven.test.skip = true
跳过单元测试。 - 在发布阶段,不使用 Snapshot 版本的依赖
- 使用
-T 2C
命令进行并行构建 - 局部 / 正确使用 clean 参数
- 以 Maven 为例
构建检测
- Maven Enforcer 插件提供了非常多的通用检查规则,比如检查 JDK 版本、检查 Maven 版本、检查依赖版本,等等
5 发布及监控
发布
因此,我们想要的应该是:一个易用、快速、稳定、容错力强,必要时有能力迅速回滚的发布系统。
- 扩展到集群
灰度发布是指,渐进式地更新每台机器运行的版本,一段时期内集群内运行着多个不同的版本,同一个 API 在不同机器上返回的结果很可能不同
- 蓝绿发布: 是先增加一套新的集群,发布新版本到这批新机器,并进行验证,新版本服务器并不接入外部流量
- 滚动发布: 是不添加新机器,从同样的集群服务器中挑选一批,停止上面的服务,并更新为新版本,进行验证,验证完毕后接入流量。
- 重复此步骤,一批一批地更新集群内的所有机器,直到遍历完所有机器\
- 金丝雀发布: 从集群中挑选特定服务器或一小批符合要求的特征用户,对其进行版本更新及验证,随后逐步更新剩余服务器。
发布系统的用户体验
1 张页面展示发布信息: 发布中 / 未发布时
6 大页面主要内容
集群 / 实例 / 发布日志 / 发布历史 / 发布批次 / 发布操作。
发布系统的核心架构和功能设计
发布系统的核心模型主要包括 Group、DeploymentConfig、Deployment、DeploymentBatch,和 DeploymentTarget 这 5 项。
- Group 的属性非常重要,包括 Site 站点、Path 虚拟路径、docBase 物理路径、Port 应用端口、HealthCheckUrl 健康检测地址等,这些属性都与部署逻辑息息相关。
- DeploymentConfig,即发布配置,提供给用户的可修改配置项要通俗易懂
- Deployment,即一个发布实体,主要包括 Group 集群、DeploymentConfig 发布配置、Package 发布包、发布时间、批次、状态等等信息。
- DeploymentBatch,即发布批次
如何利用监控保障发布质量
- 用户侧监控,关注的是用户真正感受到的访问速度和结果;
- 端到端的监控 / 唯一用户 ID 的监控
- 网络监控,即 CDN 与核心网络的监控;
- 公网监控 / 内网监控
- 业务监控,关注的是核心业务指标的波动;
- 应用监控,即服务调用链的监控;
- 调用链监控系统,一般采用在框架层面统一定义的方式,以做到数据采集对业务开发透明,但同时也需要允许开发人员自定义埋点监控某些代码片段。
- 系统监控,即基础设施、虚拟机及操作系统的监控。
- 系统监控,指的是对基础设施的监控。我们通常会收集 CPU、内存、I/O、磁盘、网络连接等作为监控指标
6 测试管理
代码静态检查实践
代码静态检查; / 破坏性测试; / Mock 与回放
- SonarQube 采用的是 B/S 架构,通过插件形式,可以支持对 Java、C、C++、JavaScript 等二十几种编程语言的代码质量管理与检测。
如何提高静态检查的效率?
- 其一,能够缩短代码扫描所消耗的时间,从而提升整个持续交付过程的效率;
- 其二,我们通常会采用异步的方式进行静态检查,如果这个过程耗时特别长的话,会让用户产生困惑,从而质疑执行静态检查的必要性。
破坏性测试
- 第一,破坏性测试的手段和过程,并不是无的放矢,它们是被严格设计和执行的
- 第二,破坏性测试,会产生切实的破坏作用,你需要权衡破坏的量和度
因此,绝大部分破坏性测试都会在单元测试、功能测试阶段执行。而执行测试的环境也往往是局部的测试子环境。
混沌工程: chaos monkey
Mock与回放技术助力自动化回归
Mock 因为这样的模拟能力,为测试和持续交付带来的价值,可以总结为以下三点:
使测试用例更独立、更解耦 / 提升测试用例的执行速度 / 提高测试用例准备的效率
- 基于对象和类的 Mock: Mockito 或者 EasyMock 这两个框架的实现原理
- 基于微服务的 Mock: Weir Mock 和 Mock Server。这两个框架,都可以很好地模拟 API、http 形式的对象。
7 持续交付平台化
- 代码管理模块,往往会和代码审核、静态扫描和分支管理等模块相联系;
- 集成编译模块,也会与依赖管理、单元测试、加密打包等模块相生相随的;
- 环境管理模块,离不开配置管理、路由管理等模块;
- 发布部署模块,还需要监控模块和流控模块的支持。