项目架构设计入门——从单体到微服务
作者: CaoZH
日期: 2025-12-15
本文为原创教程
2025 年底,技术圈有个共识:只有被过度设计的架构,没有被过度设计的前两年。
很多团队一上来就上微服务 + K8s + 事件驱动,结果半年后连业务逻辑都没理顺。架构是服务于业务的,不是用来炫技的。
本文梳理从单体到微服务的架构演进路径,帮你判断当前项目适合什么架构。
一、架构演进路径
1 2 3 4 5 6 7 8 9
| 初创期 成长期 成熟期 │ │ │ ▼ ▼ ▼ ┌────────┐ ┌──────────────┐ ┌──────────────────┐ │ 单体架构 │ → │ 垂直拆分 │ → │ 微服务/分布式 │ │ │ │ │ │ │ │ 一个应用 │ │ 按模块拆为多个 │ │ 按业务拆为独立服务 │ │ 一个数据库 │ │ 独立部署 │ │ 独立数据库 + 消息 │ └────────┘ └──────────────┘ └──────────────────┘
|
二、单体架构
适用场景
- 团队 1-5 人
- 项目启动初期
- 业务逻辑简单
- 需要快速验证市场
项目结构
1 2 3 4 5 6 7 8 9 10 11 12
| my-app/ ├── src/main/java/com/example/ │ ├── controller/ # 控制层 │ ├── service/ # 业务层 │ ├── repository/ # 数据层 │ ├── entity/ # 实体 │ ├── dto/ # 数据传输对象 │ ├── config/ # 配置 │ └── utils/ # 工具 ├── src/main/resources/ │ └── application.yml └── pom.xml
|
优势与劣势
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| ## 优势 ✅ 开发简单,学习成本低 ✅ 部署简单,一个 JAR/WAR 搞定 ✅ 调试方便,本地直接运行 ✅ 事务管理简单 ✅ 测试容易
## 劣势 ❌ 代码量增大后难以维护 ❌ 无法独立扩展某个模块 ❌ 构建和部署时间会变长 ❌ 技术栈被锁定 ❌ 团队协作冲突多
## 什么时候拆? - 代码量 > 10 万行 - 团队 > 10 人 - 构建时间 > 10 分钟 - 某个模块需要独立扩缩容
|
三、垂直拆分
当单体越来越大时,第一步不是上微服务,而是垂直拆分。
拆分方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| ┌─────────────────────────────────────┐ │ 单体应用 │ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │ │ │ 用户 │ │ 订单 │ │ 商品 │ │ 支付 │ │ │ └──────┘ └──────┘ └──────┘ └──────┘ │ └─────────────────────────────────────┘ │ 按模块拆分 ▼ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │用户服务│ │订单服务│ │商品服务│ │支付服务│ │ JAR │ │ JAR │ │ JAR │ │ JAR │ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ │ │ │ │ ┌──▼──────────▼──────────▼──────────▼──┐ │ 共用一个数据库 │ └──────────────────────────────────────┘
|
典型拆分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| services: user-service: build: ./user-service port: 8081 database: 共用
order-service: build: ./order-service port: 8082 database: 共用
gateway: build: ./gateway port: 80
|
四、微服务架构
适用场景
- 团队 > 20 人
- 业务逻辑复杂
- 不同模块需要独立扩缩容
- 需要独立技术栈选型
完整架构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| ┌─────────────────────────────────────────┐ │ 客户端(Web/App) │ └────────────────┬────────────────────────┘ │ ┌────────────────▼────────────────────────┐ │ API Gateway(网关) │ │ 路由 / 认证 / 限流 / 日志 │ └──┬──────┬──────┬──────┬──────┬─────────┘ │ │ │ │ │ ┌──▼──┐ ┌▼───┐ ┌▼───┐ ┌▼───┐ ┌▼───────┐ │用户 │ │订单 │ │商品 │ │支付 │ │ 通知 │ │服务 │ │服务 │ │服务 │ │服务 │ │ 服务 │ └──┬──┘ └──┬─┘ └──┬─┘ └──┬─┘ └──┬─────┘ │ │ │ │ │ ┌──▼───────▼──────▼──────▼──────▼───────┐ │ 消息队列(RabbitMQ/Kafka) │ └────────────────────────────────────────┘ │ │ │ │ │ ┌──▼───────▼──────▼──────▼──────▼───────┐ │ 数据库集群 │ │ 用户DB 订单DB 商品DB 支付DB │ └────────────────────────────────────────┘
|
关键组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| services: nacos: image: nacos/nacos-server:v2.3 ports: - "8848:8848"
gateway: build: ./gateway ports: - "80:8080" depends_on: [nacos]
user-service: build: ./user-service depends_on: [nacos, mysql, redis] environment: SPRING_CLOUD_NACOS_DISCOVERY_SERVER-ADDR: nacos:8848
order-service: build: ./order-service depends_on: [nacos, mysql, redis, rabbitmq]
rabbitmq: image: rabbitmq:3-management ports: - "5672:5672" - "15672:15672"
|
五、数据库拆分策略
1 2 3 4 5 6 7 8 9 10 11 12 13
| ## 阶段一:共用数据库 所有服务连同一个数据库,但按 schema/表前缀隔离
## 阶段二:读写分离 主库写入,从库读取,缓解数据库压力
## 阶段三:分库分表 按业务拆分数据库,每个服务有自己的数据库 大表按 ID/时间分片
## 阶段四:分布式数据库 引入 TiDB/OceanBase 等原生分布式数据库 对应用层透明,不需要手动分片
|
六、架构设计原则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| ## 1. 高内聚低耦合 - 相关功能放在同一个模块 - 模块间通过接口通信,不直接依赖实现
## 2. 单一职责 - 一个服务只做一件事 - 改动一个功能不需要修改多个服务
## 3. 渐进式演进 - 先单体 → 再垂直拆分 → 再微服务 - 不要为了用微服务而用微服务
## 4. 容错设计 - 熔断(Circuit Breaker) - 降级(Fallback) - 限流(Rate Limiting) - 重试(Retry)
## 5. 可观测性 - 日志(Logging):ELK / Loki - 指标(Metrics):Prometheus + Grafana - 链路追踪(Tracing):SkyWalking / Jaeger
|
七、总结
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| ## 架构选型决策树
项目初期(<5人 / <6个月) ↓ 单体架构 ✅ ↓ 项目增长(10+人 / 代码10万行+) ↓ 垂直拆分 ✅ ↓ 业务复杂(20+人 / 模块独立扩缩容需求) ↓ 微服务 ✅
## 记住这条原则
没有最好的架构,只有最适合当前阶段的架构。 过早的微服务化是万恶之源。
|
首发于 CaoZH 的笔记