您的单体应用正在成为部署瓶颈——每次更改都需要跨团队协调,并且账单中的一个bug可能导致整个应用程序崩溃。或者您正在构建一个新系统,其中不同的功能以不同的速度演进:订单管理每周更改,但库存逻辑每季度更改。您需要能够独立开发、部署和扩展的服务,它们通过事件而不是同步 API 调用进行通信,以避免创建级联故障链。
事件驱动微服务将系统分解为可独立部署的服务,这些服务主要通过异步事件进行通信。每个服务拥有自己的数据,在状态更改时发布领域事件,并响应来自其他服务的事件。这消除了时间耦合——服务 A 不需要服务 B 正在运行就能完成其工作。该模式结合了 CQRS (命令查询职责分离) 来分离写模型和读模型,事件溯源(event sourcing)来捕获状态变化的完整历史,以及 saga 编排来管理多服务事务,而无需分布式锁。
Explore more design patterns and system architectures
MicrocosmWorks 设计的事件驱动系统使用持久化的消息代理,例如 Apache Kafka 或 Amazon EventBridge,它们会保留事件,直到消费者成功处理,从而确保在中断期间不会丢失数据。我们实现了死信队列、指数退避重试策略和熔断器,这样,一个失败的微服务就不会阻塞整个事件管道。一旦下游服务恢复,它就会自动追溯未处理的事件,无需人工干预。
当您的服务不需要即时响应、需要解耦部署周期,或者当一个单一操作触发多个下游进程时,事件驱动通信是更好的选择。MicrocosmWorks 通常推荐事件驱动模式用于订单处理、通知管道和分析数据摄取,同时保留同步 API 用于需要亚秒级响应的用户面向查询。我们构建的许多生产系统采用同步读取和异步写入的混合方法。
MicrocosmWorks 在 Kafka topics 中使用分区键排序,以确保给定实体(例如特定订单或用户)的所有事件都由同一个消费者实例按顺序处理。对于需要跨实体排序的场景,我们实现 saga 编排器,结合幂等事件处理程序,可以安全地重新处理乱序消息。我们还在事件负载中嵌入矢量时钟或序列号,以便消费者可以检测和解决排序冲突。
MicrocosmWorks 采用 Saga 模式并使用补偿事务,其中每个微服务在完成其本地事务后发布领域事件,下游服务相应地做出反应或在失败时触发回滚补偿。我们将此与发件箱模式相结合,该模式将事件原子地写入本地发件箱表与业务数据一起,然后可靠地将它们发布到消息代理。这实现了最终一致性,而不会带来二阶段提交在性能和可靠性上的开销。
MicrocosmWorks 使用 OpenTelemetry 为每个事件注入关联 ID 和分布式追踪头,这使我们能够在 Jaeger 或 Grafana Tempo 等工具中,跨所有参与的微服务可视化业务事务的完整生命周期。我们还构建了实时事件流仪表板,显示每个服务的吞吐量、消费者滞后和处理延迟,从而可以轻松找出瓶颈。我们的标准可观测性栈包括带有事件元数据的结构化日志记录,以便任何单个事件都可以在几秒钟内从生产者追踪到每个消费者。
该架构围绕一个事件骨干网(Kafka、EventBridge 或 NATS)展开,它负责在服务之间路由领域事件。每个服务有三个边界:一个处理传入请求并发出事件的命令处理器,一个提供读优化投影的查询处理器,以及一个响应其他服务事件的事件处理器。一个 saga 协调器通过监听事件并在步骤失败时发出补偿命令,来协调多步骤业务流程(例如,订单履行)。
核心组件:| 层级 | 技术 |
|---|---|
| 计算 | Node.js (NestJS), Python (FastAPI), Go — 根据工作负载特性为每个服务选择 |
| 消息传递 | Apache Kafka (MSK), AWS EventBridge, NATS JetStream, RabbitMQ |
| 数据 | PostgreSQL (事务型), DynamoDB (键值), Redis (缓存/锁), EventStoreDB |
| 编排 | Temporal (工作流编排), AWS Step Functions, 自定义 saga 协调器 |
| 可观测性 | OpenTelemetry (分布式追踪), Datadog, Jaeger, 带关联 ID 的结构化日志 |
| 使用场景 | 避免场景 |
|---|---|
| 多个团队需要以不同节奏独立部署 | 您的团队工程师少于 5 人——结构良好的单体应用操作起来更简单 |
| 系统的不同部分具有不同的扩展特性 | 您正在构建 MVP 且需要快速交付——分布式系统构建速度慢 |
| 您需要强大的审计跟踪和事件重放能力 | 每个操作都需要同步、强一致性的响应 |
| 领域具有自然的有界上下文(订单、支付、库存) | 领域耦合紧密——拆分它会创建一个分布式单体 |
MicrocosmWorks 不会按技术层(API 服务、数据服务、认证服务)分解微服务。我们利用 DDD (领域驱动设计) 有界上下文沿领域边界进行分解。在编写代码之前,我们会举行事件风暴研讨会来绘制领域事件、命令和聚合——这决定了服务边界,而不是技术偏好。我们已为企业客户将单体应用迁移到事件驱动架构,最常见的经验是:从更少、更大的服务开始,以后再拆分,而不是反过来。
像应用程序代码一样进行版本控制、测试和部署的基础设施——因为您的平台的可靠性取决于其底层基础设施。