【架构艺术】Go语言微服务monorepo的代码架构设计

news/2025/3/24 20:09:45

近期因为项目架构升级原因,笔者着手调研一些go项目monorepo的代码架构设计,目标是长期把既有微服务项目重要的部分都转移到monorepo上面,让代码更容易维护,协作开发更加方便。虽然经验不多,但既然有了初步的调研,今天就分享一下笔者所面临场景的monorepo设计思路。

从语言特性上讲,Golang是非常适合做monorepo的,但根据不同项目研发需要,monorepo的目录结构可以定制成不同的形式。所以要做monorepo,首先要回答的问题是,做这个事情主要解决什么研发问题,优化了什么东西,否则投入量过多,ROI就会很低。

笔者所处的团队偏向于中台角色,每个同学都负责一个专项,不同专项之间可能共享很多三方能力的实现,并且团队距离业务比较近,研发更注重短平快,所以既往的代码实现质量方面,并不是非常完美。从这个角度来看,如果用monorepo做代码架构升级,主要能解决的问题,一是更精简的代码和模块化抽象,二是减少三方能力的冗余实现,三是通过一套研发实践规范代码管理,这样就能够在保证代码易扩展和模块易兼容的基础上,各个成员能够尽可能自由发挥,代码质量也不会轻易下降,这样长期就能让整个团队的技术迭代更加效率,服务实现的稳定性会更高。

然后就是整个代码架构长什么样子。笔者的项目,大概是这样设计:

- app:所有服务各自的代码
  - ${service_group}:按架构划分的服务组(模块)
    - ${service_name}:单个服务的代码(http/rpc等)
      - biz:业务逻辑
        - handler
        - middleware
        - service
      - conf:静态配置
      - main.go
      - build.sh:每个服务的编译
- lib:所有服务公有的代码
  - client:三方能力的client实现
  - common:枚举定义
  - model:数据结构(from idl)
  - dal:数据访问(gorm自动生成)
  - util:工具函数
- idl:协议
- script:脚本(编译/本地开发)
- Makefile
- go.mod
- go.sum
- README.md

由于很多服务需要共享数据结构,所以在设计上,idl、model做了单独提出,被所有服务可以引用。开发约定上,通过在script、Makefile做一些脚本,就可以自动指定某服务创建/更新项目代码,也可以随时自动生成/更新协议结构和gorm定义。

通过这样一个架构,首先代码精简和三方能力抽象都可以解决。然后,由于各类脚本的存在,每个业务专项的研发同学就不需要把过多精力关注在代码底层架构上,可以快速适应整个项目开发。就算长期有需要单独提出的能力,代码也可以很容易迁移到lib模块。这样整体上看,整个团队的代码质量在未来都能够有质的提升。

当然,从现状来看,这个项目结构未来可能会遇到的问题是,如果存量大服务的研发过程要迁移到这个monorepo,可能会踩什么坑,比如go-mod要处理兼容性问题,服务编译部署配置需要重新调整,研发脚本需要做额外的兼容,很多模块需要未来打散挪到lib等等。

上述这些基本上是小问题,大的问题是怎么在迁移项目的过程中,不影响既有的业务迭代。排除需要周末加班的的情况,笔者认为一个合理的解决方法是,在迁移前抽一些时间间隙,先找一些小的存量项目去做试点迁移,踩坑,整理最佳实践,然后再尝试迁移大项目,这样就不至于一下迁移遇到问题就阻塞很多。迁移的话,也是先把所有代码挪到app,保证编译部署是通的,然后在这个基础上再做代码重构和打散,把重要的公有能力给提取出来,去让代码逐渐演变成理想的形态。


http://www.niftyadmin.cn/n/5889983.html

相关文章

Android Retrofit 请求执行模块执行原理深入源码分析(三)

一、引言 Retrofit 是 Square 公司开发的一款优秀的类型安全的 HTTP 客户端,在 Android 和 Java 开发中被广泛使用。它通过简洁的接口定义和强大的注解功能,使得开发者能够轻松地进行网络请求。请求执行模块是 Retrofit 的核心部分之一,负责…

RabbitMQ 从入门到精通

1 MQ架构设计原理 1.1 什么是消息中间件 消息中间件基于队列模型实现异步/同步传输数据 作用:可以实现支撑高并发、异步解耦、流量削峰、降低耦合度。 1.2 传统的http请求存在那些缺点 1.Http请求基于请求与响应的模型,在高并发的情况下&#xff0c…

UE5.5 Niagara初始化粒子模块

粒子生成模块列表是每个创建的粒子都会调用一次对应的模块。此阶段中的模块设置每个粒子的初始值。粒子将从上到下的顺序执行模块。 下面,将列一下粒子生成常用的模块。 Initialize Particle 初始化粒子 所有粒子必需的基础模块,用于初始化粒子的基本属…

数据结构:排序详解(使用语言:C语言)

1.排序的概念及其运用 1.1排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录…

搞定python之三----序列、字典及集合

本文是《搞定python》系列的第三篇,演示了python的序列、字典和集合的简单用法和相互之间的区别。特别是序列,初次看的话没有java来的得劲,java区分的比较细,python虽然统一成一类,但是忘掉元组,字符串和列…

Insar结合ISCE2,某一个文件进行并行-stackSentinel.py

stackSentinel.py 依次执行 run_01 到 run_15,记录各自的日志 并行执行 run_16 里的所有命令,仍然记录日志 不知道对不对,测试的时间有点长就给停了 #!/bin/bash# ✅ 适用于 WSL/Linux runfiles_path"/mnt/e/insar_order_test/Stack…

Kubernetes 中的 Secrets 配置管理

一、Secrets 概述 在 Kubernetes 中,Secrets 是一种包含敏感信息的 API 对象,例如密码、OAuth 令牌、SSH 密钥等。通过使用 Secrets,您可以安全地管理这些敏感信息,避免将它们直接写入 Pod 定义或 Docker 镜像中。 Secrets 具有…

20 | 如何添加单元测试用例

提示: 所有体系课见专栏:Go 项目开发极速入门实战课;欢迎加入 云原生 AI 实战 星球,12 高质量体系课、20 高质量实战项目助你在 AI 时代建立技术竞争力(聚焦于 Go、云原生、AI Infra);本节课最终…