一、背景
1. 痛点
在服务端推进升级是一件比较困难的事情,面临的困难点包含但不限于:
- 稳定性风险:组件自身兼容性的问题或不正确升级带来的兼容性问题,可能带来线上稳定性风险。
- 升级投入&成本:组件升级至少需要研发执行升级、QA执行测试,测试通过后再逐步灰度发布,直至全量发布。整个过程需要研发、QA投入一定的研发、测试、观察的人力,单次升级时间至少以周为单位来计量。
- 升级推进成本:因以上投入成本&稳定性风险等其他因素影响,业务研发团队对组件的升级意愿较低。此外,升级进度还受团队排期、研发排查&解决问题的能力、多团队的协调参与、多角色的协调参与等因素影响。在大规模推进升级时,需要投入大量的项目管理、协调成本。
2. 现状
- 云音乐应用规模大,且线性增长:随着微服务的发展,服务拆分细化,叠加云音乐各业务快速发展,云音乐仅服务端应用总数早已突破千级,当协调多个团队、千级别的应用升级时,整个升级事项的投入是巨大的。
- Jar包风险治理率低:在目前架构风险巡检中,Jar包相关的风险因投入产出比低,其治理率在全部的风险治理中几乎垫底。Jar包的稳定性风险隐患随着业务的发展而逐步增大。
- 新技术落地周期长,多版本维护成本高:当应用规模相对较小时,我们可以针对少量应用,执行技术升级,但是当应用规模较大时,整体推进升级的难度较大,新技术落地的周期较长,在此过程中,多版本的维护成本高,带来额外的人力消耗。
3. 作用
在贵州机房迁移的背景下,云音乐面临着大批应用升级的问题,此前一次升级中,全部团队基本升级完,总体用了约1个多月的时间。对此,我们研发了自动升级平台,其核心解决升级自动化的问题。
- 在稳定性上
通过大范围的自动化部署/测试真实应用,提高组件的测试样本覆盖,提前发现并解决组件可能出现的兼容性、稳定性等问题。
自动解决多组件升级的问题,避免因不正确升级带来兼容性、稳定性问题。
- 在升级投入&成本上
对于需变更代码的升级,通过自动升级工具,串联自动代码修改、自动测试环境部署、自动CI验证,自动帮助研发完成大部分的代码修改以及验证工作。大部分情况下,无需测试介入,研发仅需合并代码,执行线上发布发布流程即可。
在升级推进成本上
通过自动升级平台,支持对任务的分发、中断、配置、信息收集等等,升级过程、进度管控完全可视化,大部分升级工作可以闭环在中心化执行,降低了多团队、多角色的协作成本。
4. 使用场景
- 场景1:技术架构升级
通过自动升级平台,可以自动化完成大范围应用的技术架构升级。例如:JDK升级、贵州机房迁移升级等场景。
- 场景2:组件风险治理
当组件存在风险时,可以借助自动升级平台,推进完成风险治理。
- 场景3:组件/Agent 兼容性测试
新发布组件/Agent时,目前主要在指定的测试工程里进行兼容性测试,覆盖场景可能存在不足,可以借助自动升级平台完成大范围的兼容性、稳定性等测试。
二、技术实践
1. 升级分类
升级分类因整体架构的不同,升级可分为如下几类:
图片
- 组件升级
即传统的Jar包升级,此种升级一般需要改动业务代码才能完成,也是目前整体占比最大的一类。
- Sidecar模式升级
边车模式,组件与业务应用解耦,组件侧的升级变更无需业务代码变更或仅需少量变更。例如:JavaAgent、ServiceMesh等方式。
什么是Sidecar模式
Sidecar 模式是一种常见的微服务架构模式,它通过在主应用程序旁边部署一个辅助应用程序(称为 Sidecar),来扩展主应用程序的功能。Sidecar 模式允许您在应用程序旁边添加更多功能,而无需额外第三方组件配置或修改应用程序代码。
此文中,我们取更为广义的Sidecar定义,将JavaAgent等作为一个辅助应用程序看待,也被视为Sidecar模式的一种实现方式。
Sidecar 模式优势&特点
- 可扩展性:通过添加 Sidecar 应用程序,可以轻松地扩展主应用程序的功能。
- 灵活性:Sidecar 应用程序可以独立于主应用程序进行部署、升级和维护。
- 可重用性:Sidecar 应用程序可以在多个主应用程序之间共享,从而提高代码重用率。
两者的差异点和共同点
- 组件升级相较于Sidecar式升级,整体升级流程上会存在些许差异,但也存在较多重合流程节点。
- 组件升级和Sidecar式升级,均需要考虑整个升级流程中的稳定性、兼容性、可维护性、升级规范性等问题。
2. 能力全景图
考虑到目前云音乐微服务架构未全面推进sidecar化,在贵州迁移中,主要涉及组件自动升级,此文主要对组件自动升级进行详细阐述,而Sidecar升级能力在未来规划中。
这部分主要介绍一下组件自动升级的能力全景,其包括底层通用能力、组件升级能力、升级任务等模块的核心能力,整体如下图所示:
能力全景图.png
- 底层通用能力部分,我们主要基于Git、发布平台、部署平台、自动化测试平台、代码分析&检索平台、线上监控,构建了底层的代码变更、测试部署、测试验证、线上发布、结果检测的能力。
- 组件升级能力部分,支持各类类型文件的变更。
- 在升级任务部分,我们基于自定义任务流编排和升级规则配置,支持自定义升级任务编排和多版本升级插件,以及多种维度的任务统计。
- 在使用场景上,自动升级平台可用于:JDK升级、技术架构升级、组件风险治理、组件/Agent 兼容性测试等场景。
3. 底层通用能力&流程编排
目前主要有以下5大底层通用能力:
图片
底层通用能力
- 升级变更。基于Git,实现分支创建/删除、代码提交/拉取、提交/关闭MergerRequest等能力。
- 测试部署。基于发布平台、部署平台、测试环境,实现测试环境创建、测试环境部署、资源释放释放/限流等能力。
- 测试验证。基于自动化测试平台、Sonar、部署平台,实现代码CI检测、自动化测试用例、部署验证等能力。
- 线上发布。基于发布平台,实现灰度发布、发布流程标准化、Agent发布等能力。
- 结果检测。基于代码分析、线上监控,实现代码升级检测、线上升级检测、Agent升级检测等能力。
以上通用能力在整合时,自动升级平台重点做了如下方面的设计
- 流程编排。为了适用不同场景的升级,自动升级对以上通用能力进行流程节点的细化,并支持编排。
- 资源释放&限流。在大规模升级时,需要占用大量的资源进行升级、部署、验证工作,为了避免对线上环境造成影响,自动升级平台对任务进行了限流,并在测试验证通过时释放部分资源、整个任务完成时,释放全部资源。
- 幂等&衰减重试机制。若需对底层平台进行读写轮询操作,需要注意操作的幂等,并且衰减重试,避免产生脏数据或对底层平台的请求压力过大。
- 可观测性设计。正常情况下的关键信息和异常情况下的异常信息,均需要详细记录,并可视化观测,减少升级时的问题排查成本。
4. 组件升级能力
4.1 必要性
以云音乐当前的现状来看,整体距离Sidecar升级(例:ServiceMesh、Agent、MultiClassloader)仍然相差较远,同时后续升级推进JDK21、ServiceMesh也需要自动升级平台的协助。
即使有了Sidecar,大范围业务代码的修改也可能是无法避免,变更代码式的自动升级和不变更代码的升级均需要,自动化变更代码的方式仍然是必须的基础建设。
4.2 核心特性
- 中心化操作:圈选应用后,根据升级任务配置,自动创建Git分支、自动创建测试环境并部署、验证。验证通过后,提交MergerRequest
- 团队研发操作:合并MergerRequest,在devops发布平台走发布流程
- 中心化操作:验证各个应用的Master分支升级情况、线上部署情况
4.3 能力介绍
组件自动升级插件基于OpenRewrite做了二次开发。这里简要介绍一下OpenRewrite:
- OpenRewrite支持大规模分布式源代码重构,以进行框架迁移、漏洞补丁和API迁移。
- OpenRewrite基于 Lossless Semantic Trees (LST),来实现代码的变更。
LST.png
- 目前除支持对普通Java项目中的java、props、properties、xml、pom.xml,也支持Spring、Micronaut、Quarkus、Jakarta、JDK17、JDK21的升级。
- 支持对变更的明细的观测&记录。
4.4 升级流程
图片
组件升级默认流程.png
以下为升级流程介绍,在此过程中加入了升级稳定性、兼容性保障的设计
- 创建代码分支。
拉取新代码分支:不污染Master分支,不影响研发流程。
- 版本升级。
分支升级。在新的代码分支,调用升级插件,实现升级
分支验证。再次验证分支升级的结果,避免升级错误。
测试部署节点。
会对各团队创建升级任务单,同时提前打通上线流程。
创建新的测试环境,并检查是否部署成功。确保不影响研发流程的同时,验证升级结果。
测试验证节点。
触发自动化测试用例并验证。验证业务逻辑是否正常。维护自动化测试用例是QA侧的日常工作,若不存在自动化测试用例,流程会卡住,可通知QA侧进行维护,或自行测试。
代码CI验证。验证代码CI正确。
此节点下,每步的执行结果无论是否成功,均需直接释放测试集群,避免在大批量升级时,占用过多的测试机器资源。当执行不成功时,需要将异常日志完整保存,方便问题排查。
代码合并
当前置所有节点通过后,可以认为自动升级已经成功完成了:升级、部署、验证的工作,此时会自动发起代码合并请求。
业务研发在Review后,将代码合并至Master分支
合并检测
系统会持续离线检测Master分支的组件依赖情况,从而检测是否完成升级
线上检测
系统会持续离线检测线上机器的组件依赖情况,从而检测是否完成升级并已上线。
释放资源
当所有检测通过后,认为该升级任务已完成,会执行各节点的释放资源方法,释放资源。例如:删除代码分支、再次检查并释放机器资源等。
除此之外,在每次大规模升级前,会先对指定范围内的应用提前预升级,从而提前摸查该次升级中的兼容性、稳定性问题。进而保障升级的准确性、升级推进时的效率。
以下为系统实现示例图:
系统示例图
点击应用名,可查看该升级任务中各个流程节点的详情数据。详情数据包括成功情况、变更明细、失败日志、失败原因、重试间隔、最大重试次数、当前重试次数、研发操作指引,以及一些基础信息展示等。以下为系统示例图:
系统实现示例图2.png
5. 任务编排&非功能性设计
为了适用不同场景的升级,自动升级对通用能力进行流程节点的细化,并支持编排,整体能力如下图所示:
图片
自定义流程编排.png
在任务编排中,我们重点做了如下设计:
- 支持任务编排。通过自定义配置实现节点顺序编排。
- 稳定性设计
幂等执行。消息可能存在重复消费,因此必须支持幂等消费。
资源释放&限流。在大规模升级时,需要占用大量的资源进行升级、部署、验证工作,为了避免对线上环境造成影响,自动升级平台对任务进行了限流,并在测试验证通过时释放部分资源、整个任务完成时,释放全部资源。
- 支持按异常类型自定义重试策略。因在升级、部署验证过程中,可能会出现各种异常导致不成功,自动升级平台支持按照不同的异常类型来自定义重试策略,包括:重试间隔时间、最大重试次数。
- 基于MQ的消息通知机制,进行任务节点的自动流转、任务路由、执行异步化。
- 过程信息、异常信息可视化。因任务依赖的系统/组件较多,对于过程信息、异常信息需要记录并可视化,降低任务的理解成本、问题排查成本。
- 扩展性设计。每个流程节点均支持异步的通知扩展,以及同步的前置/后置Hook调用。单个流程节点分为5个阶段:前置处理、前置hook、处理逻辑、后置hook、后置处理。每个阶段均可独立扩展。
6. 任务管控&功能性设计
自动升级平台支持任务的管控、统计,能力如下图所示
升级任务.png
- 支持升级范围的圈选。除支持按照应用、团队圈选应用外,还支持按照使用的Jar来圈选应用(即:若应用依赖某个Jar,则会自动纳入圈选)。
- 支持Jar包源&目标版本的设置,精准控制,避免升级错误。以下为示例图:
图片
- 与自动升级插件联动,支持升级规则的配置、升级插件版本的配置,支持不同的任务可执行不同的升级规则。
图片
- 支持升级任务编排。每个任务可独立定制自己的任务流程。
- 支持任务的重试、跳过、关闭(包含资源释放)、重新开始等管控功能。
- 支持任务统计。
支持团队、应用、任务阶段维度的统计。
支持结果检测统计。
支持执行时长、进度维度的统计。
三、运行数据
1. 支持事项
自动升级平台在近半年的时间里,支撑了贵州机房迁移测试环境演练升级、贵州机房迁移全量应用升级、网关ZK拆分升级三大事项。
2. 运行数据
- 一次性升级成功率约50%。在小范围、标准化的应用升级任务中,一次性升级成功率较高,在贵州机房全量应用升级中,一次性升级成功率约在50%左右。未能一次性升级成功的应用,研发也可借助升级平台进行问题排查&解决,提升升级效率。
- 贵州迁移约节省人日约500人日,效率提升约83%。自动升级平台按照1000个应用且仅升级一次保守统计,总体节省人力约500人日,升级效率提升约83%
节约人力:0.6d(研发+QA升级并验证单个应用的平均耗时) * 1000(应用数) - 0.1d(自动升级平台升级并验证单个应用的平均耗时) * 1000(应用数) = 500d
效率提升 :500/600 = 83%
- 数据对比如下:
图片
数据对比.png
3. 问题总结
对于未能一次性升级成功的原因,归纳主要有:
- 应用组件版本过于陈旧,不符合升级最低版本要求。
因版本跨度较大,有太大兼容性问题,自动升级平台不再予以支持。此部分应用在贵州机房迁移过程中,也大都不再升级,而是由各业务自行迁移。
- 测试环境配置维护不足,自动部署成功率低。
测试环境配置维护不足主要体现在:应用的构建、发布配置上,例如:健康检查未配置、启动类设置错误、内存参数设置不合理、期望启动时间设置不合理等等。
组件依赖的使用方式多样,也存在非标准的使用方式,升级工具覆盖不足。
非脚手架的老应用,组件依赖的的使用方式较为多样,也存在非标准的使用方式。
升级工具基于OpenRewrite进行二次开发,从实际运行的效果来看,OpenRewrite的一些开源规则仍有可完善的空间。
新发布组件,因带来新的依赖变更或依赖版本变更,带来新的兼容性问题。
例如:dts-sdk,在3.x除部分类路径、类名发生变更外,又新引入了servlet-api、jsp-api、logback、commons-beanutils-core等Jar包依赖,与云音乐技术中心的应用、组件存在普遍的不兼容问题。
查询的启动结果不准确。
部分应用可能因启动时间过长、多次自动重启,导查询的启动结果不准确
少量应用未接入自动化测试用例。
四、未来展望
以下为能力规划全景图:
图片
未来规划全景图.png
- 提升一次性升级成功率。
- 增加Sidecar升级能力的支持。
- 支持组件发布、版本管理、风险治理与自动升级的联动。降低组件自身风险、同时提升组件侧、治理侧的效率,形成整体的闭环
图片