微服务拆分实操:用什么原则划边界
2026/6/11大约 6 分钟
微服务拆分实操:用什么原则划边界
微服务拆分实操:用什么原则划边界是系统设计的核心,它决定了系统的可扩展性、可靠性和可维护性。
本文介绍了微服务拆分实操:用什么原则划边界的设计原则和实践经验,帮助你提升架构设计能力。
spring:
application:
name: order-service
cloud:
nacos:
discovery:
server-addr: nacos-cluster:8848
namespace: production
group: ECOMMERCE
config:
server-addr: nacos-cluster:8848
namespace: production
group: ECOMMERCE
file-extension: yaml
shared-configs:
- data-id: common-config.yaml
group: ECOMMERCE
refresh: true
```java
// 服务间调用 - 使用 Feign + Nacos 服务发现
@FeignClient(name = "inventory-service") // Nacos 中注册的服务名
public interface InventoryClient {
@PostMapping("/api/inventory/lock")
Result<LockResult> lock(@RequestBody LockRequest request);
@PostMapping("/api/inventory/confirm/{reserveId}")
Result<Void> confirm(@PathVariable String reserveId);
@PostMapping("/api/inventory/cancel/{reserveId}")
Result<Void> cancel(@PathVariable String reserveId);
}
// 使用时自动负载均衡到 inventory-service 的多个实例
@Autowired private InventoryClient inventoryClient;5.3 监控与链路追踪
// 使用 Micrometer + OpenTelemetry 做全链路追踪
@RestController
public class OrderController {
@Autowired private MeterRegistry meterRegistry;
@PostMapping("/orders")
public Result<OrderResponse> createOrder(@RequestBody OrderRequest request) {
// 自定义指标
Timer.Sample sample = Timer.start(meterRegistry);
try {
OrderResponse response = orderService.create(request);
// 记录成功指标
meterRegistry.counter("orders.created.total").increment();
meterRegistry.counter("orders.amount.total")
.increment(response.getTotalAmount().doubleValue());
return Result.success(response);
} catch (Exception e) {
meterRegistry.counter("orders.created.error").increment();
throw e;
} finally {
sample.stop(Timer.builder("orders.create.duration")
.description("订单创建耗时")
.register(meterRegistry));
}
}
}5.4 API 网关
# Spring Cloud Gateway 路由配置
spring:
cloud:
gateway:
routes:
# 订单服务路由
- id: order-service
uri: lb://order-service # lb:// = 负载均衡
predicates:
- Path=/api/orders/**
filters:
- StripPrefix=0
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 100
redis-rate-limiter.burstCapacity: 200
# 商品服务路由
- id: product-service
uri: lb://product-service
predicates:
- Path=/api/products/**
filters:
- name: CircuitBreaker
args:
name: productCircuitBreaker
fallbackUri: forward:/fallback/products
# 全局过滤器
default-filters:
- AddRequestHeader=X-Request-Id, ${random.uuid}
- name: Retry
args:
retries: 2
statuses: BAD_GATEWAY, SERVICE_UNAVAILABLE第六部分:拆得太碎的代价
6.1 "微服务过小症"的症状
当微服务拆得过细时,会出现以下问题:
症状一:调试地狱
场景:排查一个订单创建失败的问题
调试路径:
API Gateway → order-service → inventory-service → product-service
→ payment-service
→ marketing-service (优惠券)
→ user-service (收货地址)
一个请求跨越 6 个服务,你需要:
- 登录 6 台机器/容器看日志
- 在 6 个代码仓库里找代码
- 追踪 Jaeger 中 6 个 span 之间的关系
- 在 Kafka 里找中间消息症状二:运维爆炸
N 个微服务的运维成本:
- N 个代码仓库
- N 条 CI/CD 流水线
- N 个 Dockerfile / Helm Chart
- N 组配置(开发/测试/生产)
- N 个数据库实例
- N × 2 个容器实例(至少)
- N 个监控告警规则
当 N = 50 时:
50 个代码仓库 × 3 分支 × 3 环境 = 450 个部署单元
运维团队已经哭晕在机房症状三:网络延迟累加
单体:查询订单详情 → 1 次数据库查询,耗时 5ms
微服务(过细拆分后):
order-service 查订单 → 5ms
user-service 查用户信息 → 10ms (RPC)
product-service 查商品信息 → 15ms (RPC)
payment-service 查支付状态 → 12ms (RPC)
logistics-service 查物流 → 8ms (RPC)
─────────────────────────────
总耗时:50ms(是单体的 10 倍!)6.2 合理的服务粒度
一个简单的判断标准:一个微服务 = 一个 2-Pizza 团队(6-8 人)可以维护的范围。
其他参考指标:
| 维度 | 太细 | 刚好 | 太粗 |
|---|---|---|---|
| 代码行数 | < 1000 | 5000-50000 | > 200000 |
| 数据表数量 | < 5 | 10-30 | > 100 |
| API 接口数 | < 5 | 10-50 | > 200 |
| 负责团队人数 | < 2 | 3-8 | > 15 |
| 独立部署频率 | 每天多次 | 每天/每周 | 每月 |
| 启动时间 | < 3 秒 | 5-30 秒 | > 2 分钟 |
6.3 什么时候该合并
如果你发现以下情况,说明拆过了,该合并:
- A 服务和 B 服务总是同时变更、同时发布 → 它们应该是一个服务
- A 服务崩溃了,B 服务完全不能用(强运行时耦合) → 它们应该在一个进程里
- A 服务和 B 服务共享大量代码(复制粘贴) → 应该抽取公共库,或者合并
- 一个简单功能要在 3 个以上仓库里改代码 → 边界划错了
// 合并过度拆分的服务
// 如果 order-processing-service 和 order-query-service
// 共享同样的数据库、同样的实体定义、总是同时发布
// → 它们应该是一个 order-service第七部分:拆分决策框架
7.1 微服务拆分决策树
┌──────────────────────────────────────┐
│ 当前是否是拆分的好时机? │
├──────────────────────────────────────┤
│ □ 团队人数 > 10 且多团队协作? │
│ □ 不同模块有不同扩展需求? │
│ □ 部署耦合导致发布缓慢? │
│ □ 存在独立技术栈/合规需求? │
│ │
│ 少于 2 项 → 保持模块化单体 │
│ 2-3 项 → 考虑拆分,但谨慎评估 │
│ 4 项以上 → 拆分 ROI 明确 │
└──────────────────────────────────────┘
↓ (确定拆分)
┌──────────────────────────────────────┐
│ 确定拆分边界 │
├──────────────────────────────────────┤
│ 1. 画出业务能力图谱 │
│ 2. 识别限界上下文 │
│ 3. 对齐团队边界(康威定律) │
│ 4. 确定数据所有权 │
│ 5. 画出服务间依赖图 │
│ │
│ 依赖图中有循环依赖?→ 重新审视边界 │
└──────────────────────────────────────┘
↓
┌──────────────────────────────────────┐
│ 确定拆分顺序与策略 │
├──────────────────────────────────────┤
│ 1. 先拆外围,后拆核心 │
│ 2. 先准备基础设施,再拆服务 │
│ 3. 每次只拆一个服务,验证后再拆下一个 │
│ 4. 数据库先用 Level 2 (独立 Schema) │
│ 5. 设置回滚方案 │
└──────────────────────────────────────┘7.2 拆分检查清单
技术检查清单:
组织检查清单:
如果以上超过 3 项未满足,建议先把基础设施建设好再拆。
总结
核心原则回顾
- 业务边界优先:按业务能力拆分,不是按技术层次
- 数据边界优先:每个服务有自己的数据库
- 康威定律:服务边界应匹配团队边界
- 渐进式拆分:先拆外围、先建基础设施、逐步迁移
- 够用就好:3-8 个微服务通常比 30 个更好
一句话总结
好的微服务架构不是拆出来的,是长出来的。 先有模块化单体,当边界清晰后再自然裂变为微服务。不要为了微服务而微服务——业务价值才是最终目标。
行动指南
| 如果你正在... | 建议 |
|---|---|
| 从零开始新项目 | 先用模块化单体,等业务边界稳定后再拆 |
| 单体已经很大 | 识别限界上下文,先拆外围非核心服务 |
| 已经拆了很多服务 | 检查是否有应该合并的"颗粒过小"服务 |
| 不确定要不要拆 | 回答 7.1 节的 4 个问题,客观评估 |
参考资料
- Sam Newman, 《微服务设计》
- Chris Richardson, 《微服务架构设计模式》
- Martin Fowler, "Microservices - a definition"
- Melvin Conway, "How Do Committees Invent?"
- Alibaba, 《阿里微服务拆分实践》