微服务与整体架构:做出正确的架构决策
72% 的采用微服务的公司过早地报告了复杂性的增加,却没有带来相应的好处。 微服务的炒作导致许多团队将他们的应用程序分布在数十个服务中,而结构良好的整体应用程序本来可以更好、更快、更便宜地为他们提供服务。
本指南提供了一个诚实的框架,用于在整体架构和微服务架构之间进行选择,包括通常对成长型企业最有意义的混合方法。
要点
- 从整体开始,除非您有独立扩展或部署的特定且经过验证的需求
- 团队规模是微服务是否成功的最强预测因素:每个服务至少 3 名工程师
- “模块化单体”模式提供了大多数微服务优势,而无需运营开销
- 从整体迁移到微服务应该是增量的,一次提取一项服务
诚实的比较
整体优势
| 优势 | 详情 |
|---|---|
| 简单 | 一个代码库、一个部署、一个数据库 |
| 发展速度 | 无服务间通信开销 |
| 调试 | 一个日志流,堆栈跟踪跨越整个请求 |
| 测试 | 针对单个进程运行集成测试 |
| 重构 | IDE 重构适用于整个代码库 |
| 交易一致性 | 数据库事务自然地跨越所有操作 |
微服务优势
| 优势 | 详情 |
|---|---|
| 独立缩放 | 扩展热服务而不扩展冷服务 |
| 技术多样性 | 针对每个问题使用最好的语言/框架 |
| 团队自治 | 团队独立拥有和部署他们的服务 |
| 故障隔离 | 一项服务故障不会导致整个系统崩溃 |
| 独立部署 | 将更改部署到一项服务而不影响其他服务 |
微服务成本(经常被低估)
| 成本 | 影响 |
|---|---|
| 网络延迟 | 每个服务调用都会增加 1-10 毫秒,跨链相乘 |
| 数据一致性 | 分布式事务复杂;最终一致性令人困惑 |
| 运营费用 | 每个服务的部署管道、监控、日志记录 |
| 测试复杂性 | 集成测试需要运行多个服务 |
| 调试难点 | 请求跨多个服务,日志分布式 |
| 基础设施成本 | 负载均衡器、服务发现、每个服务的 API 网关 |
决策框架
由团队规模决定
| 团队规模 | 推荐 | 推理 |
|---|---|---|
| 1-5名工程师 | 巨石 | 没有足够的人员来维护多项服务 |
| 5-15 名工程师 | 模块化整体结构 | 无需运营成本即可实现未来开采的结构 |
| 15-50 名工程师 | 选择性微服务 | 在已证明可扩展或部署需要的地方提取服务 |
| 50+ 工程师 | 完整的微服务 | 团队自治和独立部署变得至关重要 |
根据扩展需求做出决定
| 场景 | 推荐 |
|---|---|
| 跨功能的均匀负载 | Monolith(扩展整个事物) |
| 一项热门功能,冷落 | 将热门功能提取为服务 |
| 具有不同缩放模式的多个功能 | 用于独立扩展功能的微服务 |
| 流量爆发(闪购) | 针对流量敏感组件的自动缩放微服务 |
根据部署需求决定
| 场景 | 推荐 |
|---|---|
| 每周一起部署所有内容 | 巨石 |
| 一个团队每天部署一次,其他团队每周部署一次 | 提取快速部署团队的代码 |
| 每个团队独立部署 | 微服务 |
| 合规性要求敏感功能的隔离部署 | 受监管组件的微服务 |
模块化整体架构:两全其美
模块化单体将代码组织成单个可部署单元内的边界明确的模块。模块通过定义的接口进行通信,而不是直接数据库访问。
架构
Single Deployment Unit
+---------------------------------------------------+
| [Orders Module] [Inventory Module] [Users Module] |
| | | | |
| +------ Internal API Layer ----------+ |
| | | | |
| [Orders DB] [Inventory DB] [Users DB] |
| | | | |
| +------ Shared Database Server ------+ |
+---------------------------------------------------+
NestJS 模块化整体模式
// orders/orders.module.ts
@Module({
imports: [
InventoryModule, // Explicit dependency declaration
UsersModule,
],
controllers: [OrdersController],
providers: [OrdersService],
exports: [OrdersService], // Controlled public interface
})
export class OrdersModule {}
// inventory/inventory.module.ts
@Module({
controllers: [InventoryController],
providers: [InventoryService],
exports: [InventoryService], // Only expose what others need
})
export class InventoryModule {}
模块规则:
- 模块通过导出的服务进行通信,而不是通过直接数据库访问
- 每个模块独占其数据库表 3.共享数据是通过服务方法访问的,而不是跨模块边界的JOIN
- 模块依赖关系在
imports数组中是明确的
何时将模块提取到服务中
提取时间:
- 模块需要独立扩展(例如图像处理、搜索)
- 该模块的部署频率与其他模块显着不同
- 该模块由单独的团队维护
- 该模块具有不同的技术要求(例如,Python 中的 ML 模型)
在以下情况下请勿提取:
- “看来这应该是一项服务”
- 你想要一个更干净的架构(重构整体架构)
- 您尚未确定具体的扩展或部署需求
迁移策略:整体架构到微服务
绞杀者无花果图案
逐渐用微服务取代单体功能,将流量路由到新服务,而旧代码仍然作为后备。
第 1 步:确定提取候选者(最高的扩展需求或部署摩擦)
第 2 步:与整体架构一起构建新服务
步骤 3:通过 API 网关将流量路由到新服务
步骤 4:通过并行运行来验证正确性
第 5 步:从整体中删除旧代码
数据迁移注意事项
| 方法 | 描述 | 风险 | 时间轴 |
|---|---|---|---|
| 共享数据库(临时) | 新服务读取/写入相同的数据库 | 模式耦合 | 周 |
| 每个服务的数据库 + 同步 | 每个服务都拥有自己的数据,异步同步 | 最终一致性 | 几个月 |
| 事件溯源 | 发布事件,服务打造自己的观点 | 复杂性 | 几个月 |
建议:在迁移过程中从共享数据库开始,然后在服务边界得到证明后转向每个服务数据库。
真实世界的架构示例
电子商务平台
Modular Monolith (recommended for most):
- Product catalog module
- Cart and checkout module
- Order management module
- User accounts module
- Inventory module
All in one deployable unit, backed by one PostgreSQL instance.
Selective Microservices (for high-traffic stores):
- Search service (Elasticsearch, scales independently)
- Image processing service (CPU-intensive, different scaling)
- Payment service (PCI compliance boundary)
Everything else stays in the monolith.
ERP 系统(Odoo 风格)
Monolith is the correct choice for ERP:
- Deep cross-module data relationships
- Complex business rules spanning modules
- Consistent reporting across all data
- Smaller concurrent user counts
- Transactional consistency critical
Odoo itself is a modular monolith: modules are installed/uninstalled,
but everything runs in one process with one database.
常见问题
我们的巨石是否阻碍了我们?
可能不会,除非您有特定瓶颈的证据。如果部署缓慢,请投资 CI/CD。如果某个组件需要扩展,请将其提取出来。如果团队互相踩踏,请强制执行模块边界。大多数“整体问题”实际上是微服务无法解决的代码组织问题——它们只会分发它们。
多少个微服务才算太多?
实际限制:每个负责运营的工程师不超过 3-5 项服务。一个由 5 名工程师组成的团队不应拥有超过 15-25 个服务。除此之外,运营开销占主导地位,工程速度下降。许多成功的公司运行 5-10 个定义明确的服务,而不是数百个纳米服务。
我们可以在一个整体中为不同的模块使用不同的数据库吗?
是的,这就是模块化整体方法。每个模块可以使用单独的模式,甚至可以在同一可部署单元中使用单独的数据库实例。这保留了数据所有权边界,而无需单独服务的运营成本。它还使未来的提取更加容易。
ECOSIRE 如何为客户解决这个问题?
我们建议大多数客户从模块化整体开始。我们的Odoo 实施服务 使用 Odoo 的模块化架构,我们的定制开发项目遵循 NestJS 模块化整体模式。仅当已证明需要独立扩展时,我们才会提取服务——通常是搜索、文件处理或外部集成。请参阅我们的 DevOps 指南 了解完整的架构理念。
接下来会发生什么
架构决策是基础。选择方法后,投资 CI/CD 自动化 以实现可靠部署,投资 监控 以实现运营可见性,并投资 API 网关模式 以管理服务间通信。
联系 ECOSIRE 获取架构咨询,或探索我们的 Odoo 实施服务 以获得可随您的业务扩展的 ERP 架构。
由 ECOSIRE 发布——帮助企业选择适合其发展阶段的架构。
作者
ECOSIRE TeamTechnical Writing
The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.
相关文章
API 集成模式:企业架构最佳实践
掌握企业系统的 API 集成模式。 REST、GraphQL、gRPC、事件驱动架构、saga 模式、API 网关和版本控制指南。
可组合商务:2026 年 MACH 架构指南
到 2026 年,掌握使用 MACH 架构的可组合商务。学习微服务、API 优先、云原生、无头策略,以实现可扩展的电子商务。
无头 ERP:为什么 API 优先架构是未来
了解为什么采用 API 优先架构的无头 ERP 能够提供更快的集成、更好的用户体验和面向未来的运营。包括 Odoo 无头指南。