微服务项目实战骨架设计
搭建微服务项目的第一步不是写业务代码,而是定骨架:模块怎么划分、依赖怎么管理、配置怎么约定、服务之间怎么协作。本文以一套完整骨架为例,从父工程、公共 SDK、注册中心、配置中心、网关到业务服务,逐个说明结构与关键配置。
一、整体模块划分
工程目录
微服务工程结构:
mall-parent # 父工程(依赖版本管理)
├─ mall-common # 公共 SDK
│ ├─ mall-common-core # 统一返回、异常、工具
│ ├─ mall-common-web # Web 层通用(全局异常、参数校验)
│ └─ mall-common-security # 鉴权相关(JWT、用户上下文)
├─ mall-gateway # 网关服务(8080)
├─ mall-auth # 认证中心(8081)
├─ mall-user # 用户服务(8082)
├─ mall-order # 订单服务(8083)
└─ mall-product # 商品服务(8084)模块职责
模块职责分工:
├─ mall-parent:统一 dependencyManagement(版本收敛)
├─ mall-common:跨服务复用的公共代码(SDK)
├─ mall-gateway:统一入口(路由/鉴权/限流)
├─ mall-auth:登录认证、签发 Token
└─ 业务服务:各自业务 + 独立数据库二、父工程依赖管理
父 POM
xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version>
<relativePath/>
</parent>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2023.0.1</spring-cloud.version>
<spring-cloud-alibaba.version>2023.0.1.0</spring-cloud-alibaba.version>
<mybatis-plus.version>3.5.7</mybatis-plus.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- Spring Cloud BOM -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud Alibaba BOM -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>依赖管理要点:
├─ 版本统一由父 POM 管理(子模块不写版本)
├─ Boot / Cloud / Alibaba 三套 BOM 对齐
├─ 三方库版本(MyBatis-Plus 等)在父 POM 声明
└─ 升级只改父 POM 一处三、公共 SDK 设计
统一返回与异常
java
// mall-common-core:统一响应体
public class R<T> {
private int code; // 200 成功,其他为错误码
private String msg;
private T data;
public static <T> R<T> ok(T data) { ... }
public static <T> R<T> fail(int code, String msg) { ... }
}统一异常体系:
├─ BusinessException(业务异常)
├─ GlobalExceptionHandler(@RestControllerAdvice)
└─ 错误码枚举:AUTH_401 / PARAM_400 / BIZ_50001 ...用户上下文
java
// mall-common-security:当前用户上下文(ThreadLocal)
public class UserContext {
private static final ThreadLocal<Long> USER_ID = new ThreadLocal<>();
public static void setUserId(Long userId) { USER_ID.set(userId); }
public static Long getUserId() { return USER_ID.get(); }
public static void clear() { USER_ID.remove(); }
}SDK 使用约定:
├─ 服务端从请求头 X-User-Id 读取并填充 UserContext
├─ Feign 调用时透传 X-User-Id 请求头
├─ 过滤器/拦截器在请求结束 clear(防线程复用串数据)
└─ SDK 尽量少依赖框架(核心模块零依赖 Spring Cloud)四、注册中心与配置中心
Nacos 部署
基础设施:
├─ Nacos Server:注册中心 + 配置中心(单机/集群)
├─ 持久化:MySQL(配置持久化)
└─ 命名空间:dev / test / prod 隔离服务接入配置
yaml
# 业务服务 application.yml
spring:
application:
name: mall-order
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: dev
config:
server-addr: 127.0.0.1:8848
namespace: dev
file-extension: yml配置组织:
├─ 全局配置:mall-common.yml(共享配置)
├─ 服务配置:mall-order.yml(服务独有)
├─ 动态刷新:@RefreshScope 标注配置类
└─ 本地兜底:spring.config.import 指定本地文件五、网关设计
网关配置
yaml
# mall-gateway application.yml
spring:
cloud:
gateway:
routes:
- id: order-route
uri: lb://mall-order # 通过注册中心负载均衡
predicates:
- Path=/api/orders/**
filters:
- StripPrefix=1 # /api 前缀剥掉
- id: product-route
uri: lb://mall-product
predicates:
- Path=/api/products/**网关过滤器
网关过滤器链:
├─ GlobalFilter:鉴权(白名单 + JWT 校验 + 透传用户头)
├─ RequestRateLimiter:全局限流
├─ 路由级过滤器:StripPrefix、AddResponseHeader
└─ 跨域配置:CORS 在网关统一处理java
// 网关透传用户信息到下游
ServerHttpRequest mutated = request.mutate()
.header("X-User-Id", userId)
.header("X-Trace-Id", traceId)
.build();六、业务服务设计
服务分层
业务服务内部结构(mall-order):
controller # 接口层(参数校验、R 包装)
service # 业务层(事务、业务规则)
mapper # 数据访问(MyBatis-Plus)
entity / dto # 数据模型与传输对象
feign # 跨服务调用接口关键配置
yaml
# mall-order application.yml
server:
port: 8083
shutdown: graceful # 优雅关闭
spring:
datasource:
url: jdbc:mysql://localhost:3306/mall_order
username: root
password: xxx
cloud:
openfeign:
client:
config:
default:
connectTimeout: 2000
readTimeout: 5000
management:
endpoints:
web:
exposure:
include: health, info, metrics, refresh跨服务调用
java
// mall-order 中的 Feign 接口
@FeignClient(name = "mall-product")
public interface ProductFeignClient {
@PostMapping("/api/products/deduct-stock")
R<Void> deductStock(@RequestParam Long productId,
@RequestParam Integer quantity);
}Feign 调用约定:
├─ 接口统一返回 R<T>(与 SDK 一致)
├─ 服务端全局异常已转成错误码(不抛框架异常)
└─ 调用方做降级兜底(fallback)七、启动顺序与联调
服务启动顺序
启动顺序:
1. Nacos Server(注册/配置中心)
2. MySQL / Redis(基础设施)
3. mall-gateway(网关,依赖注册中心)
4. mall-auth(认证中心)
5. 业务服务(user / product / order)验证清单:
├─ Nacos 控制台:所有服务实例健康
├─ 网关路由:curl 网关地址转发到业务服务
├─ 配置下发:改配置 → 服务热刷新
├─ 链路调用:下单接口全链路通
└─ 日志可观测:TraceId 贯穿本地联调
本地开发约定:
├─ 每个服务独立端口(8080 网关 / 8081 认证 / 8082-8084 业务)
├─ 数据库按服务拆分(mall_user / mall_order / mall_product)
├─ 本地配置走 Nacos dev 命名空间
└─ 跨服务调试用网关入口,避免直连八、骨架演进
从骨架到生产
骨架补充方向:
├─ 安全:网关鉴权完善 + 服务间 mTLS
├─ 事务:引入 Seata(跨服务写场景)
├─ 消息:Spring Cloud Stream(异步解耦)
├─ 任务:XXL-Job(定时任务)
├─ 可观测:SkyWalking + Prometheus + Grafana
└─ 部署:Dockerfile + K8s + CI/CD骨架设计原则:
├─ 先定规范(响应体、错误码、日志、请求头)
├─ 公共能力进 SDK(不重复实现)
├─ 基础设施独立部署(Nacos/DB/Redis)
└─ 每个服务可独立启动、独立发布总结
一套好的微服务骨架解决三件事:依赖版本统一(父 POM + BOM)、公共能力复用(SDK)、服务协作规范(注册发现 + 网关 + 配置 + 调用约定)。骨架搭好后,新增业务服务只需"复制一个模块 + 改配置",团队的开发成本集中在业务本身。骨架不是一次建完,而是随业务演进而持续补充——但规范与边界一旦确立,就不要轻易破坏。