系统设计入门:从单体到微服务
架构演进的必然性
任何系统都会随着业务增长而演化。理解「为什么拆」比「怎么拆」更重要。
单体优先原则
先单体,后拆分——除非你 100% 确定某个模块需要独立扩展,否则不要过早拆分。
Monolith First 是 Martin Fowler 提倡的策略:初期用单体快速验证业务,待边界清晰后再渐进拆分。
拆分服务的判断标准
| 指标 | 阈值 | 含义 |
|---|---|---|
| 代码行数 | > 50k | 模块间耦合度高 |
| 团队规模 | > 10 人 | 沟通成本剧增 |
| 部署频率 | 差异 > 2x | 某些模块变更频繁 |
| 资源需求 | 差异 > 3x | CPU/内存需求不同 |
| 故障影响面 | 关键模块 | 需隔离降级 |
满足 2-3 项即可考虑拆分。
服务边界划分策略
1. 按业务能力(推荐)
订单服务 用户服务 商品服务 支付服务 库存服务
每个服务对应一个明确的业务域,团队可以端到端负责。
2. 按子域(DDD 思想)
核心域:订单、交易
支撑域:促销、积分
通用域:通知、日志
核心域投入最多资源,通用域可复用或外包。
3. 按数据所有权
服务应独占其核心数据,禁止直接跨库访问。通过 API 暴露能力。
常见架构模式
分层架构(Layered)
Presentation → Business → Data
简单清晰,适合中小型应用。
六边形架构(Hexagonal)
核心业务逻辑独立,适配器对接外部(DB、API、消息队列)。
┌─────────────┐
│ Ports │
└──────┬──────┘
│
┌────────▼────────┐
│ Domain Core │
└────────┬────────┘
│
┌──────┴──────┐
│ Adapters │
└─────────────┘
事件驱动(Event-Driven)
服务间通过事件通信,实现解耦:
Order Service → (OrderCreated) → Notification Service
→ (OrderPaid) → Inventory Service
拆分后的挑战
1. 分布式事务
跨服务的原子操作需要 Saga 模式 或 消息队列事务。
2. 数据一致性
最终一致性是常态,通过补偿机制(CQRS、Event Sourcing)解决。
3. 服务发现与治理
- 注册中心(Consul, Nacos, etcd)
- 配置中心
- 熔断降级(Resilience4j, Hystrix)
- 链路追踪(Jaeger, SkyWalking)
4. 部署与运维
- 容器化(Docker)
- 编排(Kubernetes)
- CI/CD 流水线
- 监控告警(Prometheus + Grafana)
技术选型建议
| 场景 | 推荐方案 |
|---|---|
| 初创公司 | 单体 + 模块化,后期拆分 |
| 电商平台 | 微服务 + 事件驱动 |
| 金融系统 | 分层 + 严格事务控制 |
| 实时应用 | 事件流(Kafka) + CQRS |
踩坑经验
不要为了用微服务而用微服务——它带来的是复杂度,不是银弹。
服务粒度宁粗勿细——拆得太细,运维和监控成本会爆炸。
先写服务合约(API Spec)再开发——契约先行,减少联调摩擦。
小结
架构是业务的映射。没有「最好的架构」,只有「最适合当前阶段的架构」。
从单体开始,在痛点出现时渐进演进,保持系统可理解、可维护、可演进。
下一篇:《微服务下的数据一致性方案实践》