• 基于大仓库的微服务差异化构建工具


    前言

    微服务架构已经成为了各个公司项目的标配,项目不用微服务架构,都不好意思说自己是做Web开发的,似乎使用微服务架构已经成为了一种政治正确。事实上,如果项目结构设计得当,是否使用微服务架构仅仅是实现上的细节罢了 。而随着项目规模的扩大,各种问题也会接踵而至...

    背景

    公司项目使用Monorepo的形式来组织代码,项目内分成了11个不同的微服务。每次开发完新功能,发测试环境时,CI都会将这11个不同的微服务全部重新构建打包成Docker镜像,然后再由开发人员手动点击“发布”按钮,将镜像部署到测试环境。整个过程耗费10-15分钟左右。

    其实这样的速度目前来说是没什么问题的,又不是抢着去投胎(误)。但实际上总会有那么一小部分场景,想要尽快发版看到结果。

    由于我司规模不大,负责前端的同学就坐在我旁边,有时候对接接口的时候,发现个BUG,或者临时改了个什么东西,而前端的同学又等着接。于是代码推上去之后,我就在那干瞪眼等着CI跑好,赶快点个【发布】,等发好了,最后告诉前端同学:“发好了,可以继续接了”。

    由于每次构建会影响所有微服务,因此在发布的整个过程中,服务是完全不可用的。

    缘起

    记得第一次产生解决问题的想法是在疫情时,忘记什么原因了,和leader一起,在屏幕前干瞪眼等了好久CI,那时跟leader感叹了下:“有空一定要撸个 根据改动的文件来构建服务 的工具。”

    虽然我本科读的是“软件工程”,但我却越发痴迷于语言细节和底层原理(在此之前其实我更喜欢偏宏观一些的软件工程、架构设计等领域)。恰巧前段时间粗略翻了几页柴大的《Go语言定制指南》,就想到 通过构建项目的依赖树,分析本次修改产生的影响,顺着依赖树往上,就能确定影响到了哪些服务的构建。

    破局

    有了想法之后,就该行动了。我创建了一个名为Veronica(维罗妮卡)的仓库。是的,这个名字很中二,取自复仇者联盟2中钢铁侠的一套外太空支援系统——维罗妮卡。

    veronica会分析并构建整个Go项目的依赖树, 现阶段veronica仅仅通过分析 .go 文件的import声明 ,以 package (目录)为单位来组织依赖树。这样实现的优点就是简单、分析速度快。缺点也是显而易见的,粒度较粗,当修改了某个包下的某个文件后,所有依赖这个包的微服务都会被veronica标记为受影响。

    要使用veronica,首先需要在项目根目录下放置 veronica.yaml 文件,该文件声明了项目的服务列表,以及其他的一些配置项:

    1. version: 0.1.1
    2. # service下的每个项都表示一个微服务
    3. services:
    4. api-gateway:
    5. # entrypoint 表示服务的入口,即服务的main包
    6. entrypoint: cmd/api-gateway
    7. # ignores 表示该服务忽略的文件列表,即使这些文件改动,veronica也不会判定它影响了当前的服务
    8. ignores:
    9. - 'pkg/**/*doc.go'
    10. # hooks 里的文件如果被改动,veronica会报告该服务收到影响,无论该服务是否真的依赖了这个文件
    11. hooks:
    12. - '**/Makefile'
    13. - 'go.mod'
    14. # 可配置多个服务,每个服务可以有各自的ignores和hooks
    15. assets-manager:
    16. entrypoint: cmd/assets-manager
    17. assets-cron:
    18. entrypoint: cmd/assets-cron

    在正确配置了文件之后,使用以下命令告诉veronica,你本次提交修改了哪些文件:

    git log --name-only -1 --pretty=format:"" | veronica

    -1 是指输出最后一次commit提交的信息,这条git命令会将最后一次commit改动的文件传递给veronica,接着veronica会向你报告,这次改动的文件影响了哪些服务的构建:

    1. cmd/assets-cron
    2. cmd/api-gateway

    这样我们就可以用shell脚本或其他方式,来单独构建受影响的微服务了。

    未来

    当前veronica还处于积极开发的阶段,许多特性还不稳定,报告的粒度也比较粗。下一步计划优化当前的项目结构,并尝试构建整个项目的AST,将veronica的报告级别控制到源代码层面:

    如图所示,当前的veronica只能根据文件的 ImportDecls 将依赖控制到目录级别。假设有如下两个服务:

    用户服务:

    1. import "pkg/util/idutil"
    2. func main() {
    3. idutil.GenUserID()
    4. }

    订单服务

    1. // 订单服务
    2. import "pkg/util/idutil"
    3. func main() {
    4. idutil.GenOrderId()
    5. }

    它们都共同依赖了 idutil 这个 package ,当我们修改了 GenOrderId 的实现后,当前版本的veronica会报告两个服务都受到了影响,而在veronica计划的正式版本中,将 仅会报告订单服务 受到了影响。

     

  • 相关阅读:
    MapStruct 代替BeanUtil 和ModelMapper
    P8196 [传智杯 #4 决赛] 三元组
    vue ant 两个页面 调用同一个接口 想在 前端的一个 接口传 一个固定的值 ,另外一个不变 ,查询条件默认值加上自己要的就好啦
    微信小程序怎么测试
    植被参数光学遥感反演方法(Python)及遥感与生态模型数据同化算法技术应用
    Vue rules校验规则详解
    SAP ERP系统解决光伏电池产业管理难题
    PHP伪协议详解
    C语言输出杨辉三角
    斯坦福JSKarel编程机器人使用介绍
  • 原文地址:https://blog.csdn.net/Q54665642ljf/article/details/126082486