代码的生命周期
- 产生需求: 涉及到需求管理
- 开发人员编码: 涉及到代码仓库, 多人协作等
- 代码测试: 一般只是简单的基础校验; 如语法规范, 注释格式, 提交信息, 依赖验证, 单元测试等;
- 打包: 产出交付物
- 测试环境验证: 功能测试,性能测试, 灰度测试等
- 生产环境部署: 可能会回滚
需要考虑的几个组件
- 代码仓库
- 代码编译
- 包管理
- 测试
- 部署管理
代码仓库
如果没有特殊需要, 一般也都是 git 管理了, git 的仓库可以考虑这几个
| 优点 | 缺点 | |
|---|---|---|
| github | 不需要介绍 | 国内访问存在不确定性 |
| gitee | 就是国内访问质量好 | 缺点就是可信度不高 |
| gogs | 如果只是单纯的 git 仓库, 这个就行了,轻量简单 | 功能单一 |
| gitlab | 可以私有化部署, 企业集成度比较高, 功能丰富 | 太重, 集成了太多杂乱的组件, 复杂 |
| gitea | 强烈推荐, 既轻量,又功能丰富 | 没有明显感觉 |
| onedev | 最近刚发现,感觉很不错,国产项目,似乎可以平替gitlab | 未知 |
CI
Continuous Integration 持续集成, 目的快速输出交付物。
频繁地将代码集成到主干的优点
- 小功能尽快合并, 可以快速发现错误
- 避免大版本更新合并困难;
需要的能力
- 自动代码合并, 不同的环境到不同的分支;
- 自动构建
- 测试: 单页测试和一些规范的验证。
CI工具非常多, 但一般主要考虑这几款
| 产品 | 介绍 |
|---|---|
| github-actions | 如果代码是在 github 上,当然是首选了; 有一定免费额度可以用, 小项目足够了 |
| gitlib-ci | 如果代码是在 gitlib 上,当然也是首选了 |
| gitea-runner | 如果代码在 gitea 上也是首选, 基本兼容 github-actions 的语法和插件。 但是这个项目的问题就是太新了,gitea 1.19 才开始正式支持, 也就是才发布几个月。 目前来说, 勉强可以用, 但稍微特殊一点的功能就不大能支持; 个人其实不大看好未来发展,因为开发进度的人员数量似乎有些不足,现在的进度也慢。 |
| jenkins | 老牌集成工具 |
| drone | 主力推荐, 轻量级,插件都是容器化方式,定制功能非常方便。 虽然是开源的, 但也需要注意一点商业许可问题,轻量使用是免费的 |
| Woodpecker | 因为 drone 的诡异的商业许可问题, 所以出现了开源平替。 基本兼容 drone, 推荐,个人非常看好 |
还有一些云厂商的, 比如阿里的云效等, 没用过,但如果深度使用他们平台的话,应该也是挺不错的。
一般简化流程
- 提交代码到功能功能分支
- 单元测试和代码评审或验证
- 合并到dev分支
- 自动发布测试环境验证, 压力测试, 集成测试等
- 合并main分支
- 发布生产环境
语义化版本
简单理解就是友好的版本号
通过 git commit 时标识信息来确认这次发布的类型,引导相应动作。
生成的版本号规则
- 主版本号: 当你做了不兼容的 API 修改
- 次版本号: 当你做了向下兼容的功能性新增
- 修订号: 当你做了向下兼容的问题修正
commit语义
commit 附带的 Message 格式遵守一定规范语法
- 方便工具解析和自动化流程
- 方便生成 ChangeLog 等
- 工具自动生成版本号
Commit 所遵守的规范称为约定式提交(Conventional Commits)
语义化发布首先将 Commit 进行分类, 常用的分类(Type)有:
| 标识 | 说明 |
|---|---|
| feat: | 新功能, 增加次版本号 |
| fix: | BUG 修复, 增加修订号版本号 |
| docs: | 文档变更 |
| style: | 文字格式修改 |
| refactor: | 代码重构 |
| perf: | 性能改进, 增加修订号版本号 |
| test: | 测试代码 |
| chore: | 工具自动生成 |
CD
Continuous delivery 持续交付
频繁地将软件的新版本, 交付给质量团队或者用户, 以供评审, 即快速进入测试环境验证;
Continuous Deployment 持续部署
目的是快速将交付物发布到生产环境中, 并验证新版本能否运行正常。
需要的能力
- 快速发布能力: 并行发布, 预推送等
- 快速验证能力:自动化实际业务测试能力
- 快速回退能力:通过备份、环境变量、软链接、重发或回退版本、切换流量等方式
常规工具栈
- 最早就是脚本推送重启了
- 然后就是 ansible 这一类集中管理工具
- 再然后就是 k8s 集群这类平台化容器管理方式
- 目前比较看好和推荐 Argo 来做 持续部署
- 云厂商自有的体系
- Terraform 基础设施
k8s集群环境工具栈
- k8s内有状态基础组件: k8s Operator
- 频繁变更的无状态业务应用: ArgoCD
- 不经常变更的外部组件: helm
- 临时性任务或开发中的新应用: yaml
- 多环境的区分部署: Kustomize, helm
云厂商工具栈
- 腾讯云: 云原生构建 Cloud Native Build https://docs.cnb.cool/zh/
- 阿里云: 云效
包管理
以前有过的方式
- 交付 war,jar, tar.gz 等形式的包文件,找一个文件目录或ftp进行存放
- 研发推送到统一的包仓库,如 npm 仓库, yum 仓库, mavn 仓库,pipy 等等
- 提交一个 release 到 github 或 gitea 或 gitlib 中
推荐的方式
如果不是最终交付的成品, 如果依赖库这种, 建议就是语言自身的私服中和 git release 两种方式组合管理
如果是最终交付物, 还是推荐 git release 方式和 ftp 类进行管理
发布模式
重建部署
版本A下线后版本B上线
重建策略是一个冗余的方式,它包含下线版本A,然后部署版本B;
服务的停机时间依赖于应用下线和启动耗时
优点:便于设置, 应用状态完整更新
缺点:对用户影响很大,预期的宕机时间取决于下线时间和应用启动耗时
滚动部署
又称 滚动更新或者增量发布
例如服务池有10个实例,
- 先增加2个新版本实例,
- 接收流量并且健康检查通过后;
- 下线旧版本 2 个实例;
- 循环上述过程直到全部更新。
相关参数
- 并行数,最大批量执行数:同时发布新实例的数目;
- 最大峰值:考虑到新增的实例数,即最大新旧副本数;
- 最大不可用数:在滚动更新过程中不可用的实例数;
- 最小可用数: 最少N个副本需要是正常的,才能进行下一轮次发布;
优点:
- 便于设置
- 版本在实例间缓慢发布
- 对于能够处理数据重平衡的有状态应用非常方便
缺点:
- 发布/回滚耗时
- 支持多个API很困难, 即 API 兼容性保障难
- 无法控制流量
蓝绿/部署
又名 红/黑
两种模式
- 日常情况下,环境由2个副本池运行,蓝绿各承担50%流量,蓝绿之间不存在互相调用;
- 日常只有1个区域, 旧区域下线时直接删除,新区域上线前创建。
发布过程
- 先将某一区的流量比例调整为0%
- 更新此区域的副本
- 调整新区的分流比例从 1%至5%进行验证,如果正常则提升至100% (旧区域减至0);
- 验证完全正常后,升级旧区域的应用版本;
- 最后流量再调整回各50%
如果升级失败则切换回旧副本。
优点:
- 可以提前内部或小范围验证新环境, 实时发布、回滚,
- 避免版本冲突问题,整个应用状态统一一次切换
- 有一个单元总是可用的,回滚快速;
缺点:
- 资源翻倍
- 在发布版本到生产环境之前,整个平台的主流程测试必须执行
- 处理有状态的应用很棘手
金丝雀部署
新版本向一小部分用户发布,验证后再完全放开。
通常流量是按比例分配的; 例如90%的请求流向版本A,10%的流向版本B;
用于缺少足够测试,或者缺少可靠测试,或者对新版本的稳定性缺乏信心的情况下。
优点:
- 版本面向一部分用户发布
- 方便错误评估和性能监控
- 快速回滚
缺点:
- 发布缓慢
A/B部署
与 金丝雀部署 模式类型,差别是 只将 符合特定条件的流量给到新版本。
用于测试特定功能的切换,并发布使用占大部分的版本
例如
- 根据用户uid
- 地理位置
- 设备类型, 语言等
优点:
- 多个版本并行运行;
- 方便提前获得客户反馈,减少致命的影响和低级的错误;
- 完全控制流量分布;
缺点:
- 需要智能负载均衡网关和更高的自动化发布程度。
- 对于给定的会话,很难定位问题,分布式跟踪是必须的
影子部署
即流量镜像模式
新版本B接受真实的业务流量请求,但是不产生响应;
例如大部分的查询类业务操作, 如果有写操作需要mork;
配置非常复杂,而且需要特殊条件,尤其是分出请求
优点:
- 可以使用生产环境流量进行性能测试
- 对用户无影响
- 直到应用的稳定性和性能满足需求后才发布
缺点:
- 双倍资源,成本昂贵
- 配置复杂
- 对于需要变更数据的业务操作要么关闭,要么定制操作;
- 不是真实用户测试,可能出现误导