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

214 篇文章 0 订阅
本文介绍了为解决大规模微服务项目构建问题而创建的Veronica工具,该工具基于代码改动分析依赖树,确定影响的服务,实现差异化构建。目前,Veronica通过分析import声明进行服务组织,未来计划通过构建AST细化报告粒度,提高效率。
摘要由CSDN通过智能技术生成

前言

微服务架构已经成为了各个公司项目的标配,项目不用微服务架构,都不好意思说自己是做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 文件,该文件声明了项目的服务列表,以及其他的一些配置项:

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

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

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

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

cmd/assets-cron
cmd/api-gateway

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

未来

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

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

用户服务:

import "pkg/util/idutil"

func main() {
    idutil.GenUserID()
}

订单服务

// 订单服务
import "pkg/util/idutil"

func main() {
    idutil.GenOrderId()
}

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值