单体架构 vs 微服务架构
单体架构(Monolithic Architecture)和多实例部署
单体架构:所有功能模块在一个应用内,共享同一个数据库。
最佳实践:模块化单体(Modular Monolith)
虽然是单体应用,但内部应保持清晰的模块边界(如 NestJS 的 Module 机制)。Jungle 项目就是典型的模块化单体,各个业务模块(分类、用户、订单)在代码层面是解耦的,只是部署在一起。这样既享受了单体的开发便利,又避免了项目演变成“巨石项目”,未来需要拆分时也更容易。
Jungle 项目结构:
┌────────────────────────────────────────┐
│ Jungle 后端应用 │
│ │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │分类模块 │ │用户模块 │ │订单模块 │ │
│ └────────┘ └────────┘ └────────┘ │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │库存模块 │ │产品模块 │ │客户模块 │ │
│ └────────┘ └────────┘ └────────┘ │
└────────────────┬───────────────────────┘
↓
┌──────────────┐
│ PostgreSQL │ ← 一个数据库
└──────────────┘
部署方式(多实例):
┌─────────────────────────┐
│ API Gateway (Traefik) │ ← 统一入口 / 自动发现 / SSL
│ (Docker) │
└────────────┬────────────┘
│
┌──────┼──────┐
↓ ↓ ↓
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Jungle │ │ Jungle │ │ Jungle │ ← 3个容器
│ 实例 1 │ │ 实例 2 │ │ 实例 3 │
└─────┬────┘ └────┬─────┘ └────┬─────┘
│ │ │
└──────┬────┴────────────┘
↓ (jungle_internal)
┌──────────────┐
│ PostgreSQL │ ← 共享同一个数据库
└──────────────┘微服务架构(Microservices Architecture)
微服务:按业务领域拆分成多个独立服务,各自数据库,通过 HTTP/RPC 通信。
改造 Jungle 成微服务:
┌─────────┐
│ Client │
└───┬─────┘
↓
┌──────────┴──────────┐
│ API 网关 (Traefik) │ ← 统一入口 / 路由分发
└──────────┬──────────┘
│
┌───────────────┼───────────────┐
↓ ↓ ↓
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 分类服务 │ │ 用户服务 │ │ 库存服务 │
│ (NestJS) │ │ (NestJS) │ │ (Golang) │
└─────┬────┘ └─────┬────┘ └─────┬────┘
↓ ↓ ↓
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 分类数据库 │ │ 用户数据库 │ │ 库存数据库 │
│ (PG) │ │ (PG) │ │ (MySQL) │
└──────────┘ └──────────┘ └──────────┘实战推演:Jungle 的微服务化改造之路
如果有一天 Jungle 的业务量暴增,需要从当前的模块化单体转型为微服务,我们需要经历以下核心步骤:
代码物理拆分(Repo Split)
- 将
src/modules/inventory等业务模块剥离为独立仓库。 - 将
src/shared中的工具类、认证守卫提取为私有 npm 包(@jungle/common),供所有服务复用。
- 将
数据库垂直拆分(Database Split)
- 最痛苦的一步:将原本的
Join关联查询(如订单查用户)改为 API 聚合或数据冗余。 - 每个服务只能访问自己的数据库,绝对禁止跨库查询。
- 最痛苦的一步:将原本的
通信改造(RPC/Message Queue)
- 进程内的方法调用(
this.userService.findById)变为网络调用。 - 同步调用:使用 gRPC 或 HTTP(NestJS 自带 Microservice 模块)。
- 异步解耦:引入 RabbitMQ/Kafka,例如“订单创建成功”后,发送消息通知“库存服务”扣减,实现最终一致性。
- 进程内的方法调用(
基础设施升级
- 引入 配置中心 (Nacos/Apollo) 管理分散的配置文件。
- 引入 链路追踪 (SkyWalking/Jaeger) 解决跨服务排查难问题。
- 引入 分布式事务 (Seata/Saga) 保证数据一致性。
延伸阅读
- 微前端架构:了解微服务思想在前端领域的应用。
架构认知与选择
单体架构不是落后,微服务不是银弹。
选择的核心标准:
- 团队规模:能否维护微服务的复杂度?
- 业务复杂度:是否真的需要拆分?
- 技术储备:团队是否有微服务经验?
- 运维能力:是否有 DevOps 团队支撑?
对于大部分项目来说:
- 从单体开始 ✅
- 做好模块化设计 ✅
- 必要时再拆分 ✅
- 不要过早优化 ❌
记住:架构是演进的。