微服务模块划分和公共模块边界

zjc 于 2026-08-05 发布

微服务项目拆模块时,最容易走两个极端:一是所有东西都塞进公共模块,二是每个服务重复复制一份代码。这个项目最终采用的边界是:公共模块只放稳定契约和横切能力,不替业务服务决定运行时技术栈。

一、模块划分

service-common      公共契约和横切能力
service-provider    业务数据和核心接口
service-consumer    Feign 消费方
service-gateway     唯一流量入口
service-mail        邮件领域服务
MP-Generator        独立代码生成工具

MP-Generator 没放进父 POM 聚合,因为它是开发工具,不是线上服务。业务构建不应该因为一个代码生成器而增加数据库驱动等额外依赖。

二、service-common 里放什么

当前公共模块包含:

这些都属于多个服务共同遵守的契约,或者和具体业务无关的横切能力。

三、公共模块不能背太多运行时依赖

一个典型错误是把 Web、Swagger、数据库、Sentinel 全塞进 common。这样所有依赖它的服务都会被迫继承这些依赖。

这个项目后来重构成:

能力 声明位置
Web 容器 provider、consumer、mail
OpenFeign starter consumer
Swagger UI 各文档服务或 gateway
数据库和邮件 对应业务模块
WebFlux gateway

公共模块只保留源码直接使用的编译 API,例如 Spring Web 注解、Feign Core、Validation、SpringDoc common。

四、Gateway 不依赖 common

service-gateway 是 WebFlux 应用,service-common 里的 @RestControllerAdvice 和 WebMVC 切面不能直接复用。如果为了一个统一响应结构把 WebMVC 依赖带进 Gateway,很容易出现 Web 栈冲突。

所以 Gateway 独立实现:

五、自动装配边界

公共组件通过 Spring Boot 自动装配文件注册:

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

业务服务引入 service-common 后,不需要手动 @Import。但自动装配也应该克制,只注册真正全局生效的组件。