前四章定了边界与契约;本章回答服务之间怎么说话。选错模式会把 部分失败 放大成长链路阻塞,或把本该异步的通知硬拉成同步耦合。
请求/响应(Request/Response)是分布式中最直观的模式:调用方发请求、阻塞或异步等待响应。在 Java 微服务中常体现为 REST + OpenAPI 契约,practice 阶段用 OpenFeign 消费。
| 风格 | 特点 | ShopFlow 示例 |
|---|---|---|
| REST/HTTP + JSON | 通用、易调试、网关友好;性能略低于二进制 RPC | order → inventory 预留、查询 SKU |
| RPC(如 gRPC) | 强类型契约、HTTP/2、流式;需生成桩代码 | 高 QPS 内部调用、多语言团队(可选) |
| GraphQL / BFF 聚合 | 前端一次取多资源;聚合层负责扇出 | 商品详情页聚合(性能、容量与数据扩展 再展开) |
# 详见 OpenFeign、负载均衡与服务间调用;此处仅示意超时与幂等头
spring:
cloud:
openfeign:
client:
config:
inventory-service:
connectTimeout: 1000
readTimeout: 2000
# 调用时 Header: Idempotency-Key: {orderId}
当调用方不必立即知道下游处理结果,或需要削峰、解耦多订阅者时,使用异步消息。ShopFlow 中 PaymentCompleted、OrderCreated 等领域事件适合走 Kafka 等 MQ(详见 Kafka 事件驱动与 Redis 缓存)。
OrderCreated、PaymentCompleted),载荷含最小集成字段 + 事件 ID。flowchart LR Pay[payment-service] -->|publish| K[(Kafka topic)] K --> G1[order-service 消费者组] K --> G2[analytics 消费者组] G1 --> O[更新订单 PAID] G2 --> A[报表入库]
order 与 analytics 各用消费者组,互不影响进度;须幂等处理重复投递。
跨多个服务的业务流程(如下单 → 预留 → 支付 → 确认)如何协调?两种主流思路:编排(Orchestration) 由中央协调者按脚本推进;编舞(Choreography) 各服务监听事件、自行决定下一步,无中心大脑。
| 维度 | 编排 | 编舞 |
|---|---|---|
| 协调者 | order-service 或独立 orchestrator 调用各步 | 各服务订阅事件,本地状态机驱动 |
| 可见性 | 流程集中在一点,易画序列图 | 流程分散,须链路追踪串联 |
| 耦合 | 协调者知悉所有步骤 API | 服务只关心相关事件,添加订阅者较易 |
| 失败处理 | 常配合 Saga 补偿,由协调者触发 | 每服务自行补偿或发补偿事件 |
sequenceDiagram participant O as order-service 编排者 participant I as inventory-service participant P as payment-service O->>I: 同步 reserve I-->>O: 201 O->>P: 同步 initiate payment P-->>O: 202 Note over O: 等待 PaymentCompleted 事件 P-->>O: event PaymentCompleted O->>O: 状态 PAID
ShopFlow 入门采用「order 编排 + 支付异步事件」混合:关键同步、通知异步。
步骤 ≤ 3 且团队小:order 内编排往往足够。步骤多、多团队自治:可逐步引入编舞,但须统一事件 schema 与可观测性。勿在 API 网关 里写编排逻辑。
异步与重试使「至少一次投递」成为常态。须从生产端与消费端双侧保证正确性。
Idempotency-Key;异步用 eventId 或业务键。processed_events(event_id),重复则跳过。问题:订单入库与发 Kafka 两个操作无法共用一个本地事务。 Outbox 将待发事件与业务写入同一数据库事务,后台投递器异步发到 MQ。
@Transactional
void createOrder(CreateOrder cmd) {
Order order = orderRepo.save(new Order(cmd));
outboxRepo.save(new OutboxEvent(
"OrderCreated",
order.getId().toString(),
toJson(new OrderCreatedPayload(order.getId(), ...))
));
// 同一事务;投递器稍后 poll outbox → Kafka
}
第二次应识别为重复:查去重表或订单状态已为 PAID,直接 ack 不再改库。若仍重复扣减或重复发券,说明缺少消费端幂等。
basics 阶段原理收官。下表将本章概念映射到 practice 阶段 ShopFlow 工程(Java 21 + Spring Boot 3.5 + Spring Cloud 2025)。
| 本章概念 | Spring Cloud / 组件 | 实战章节 |
|---|---|---|
| 同步 REST + 契约 | OpenFeign + LoadBalancer | OpenFeign、负载均衡与服务间调用 |
| 统一入口、路由 | Spring Cloud Gateway | 服务注册发现与 API 网关 |
| 注册发现 | Eureka / Nacos | 服务注册发现与 API 网关 |
| 领域事件、Pub/Sub | Spring Cloud Stream + Kafka | Kafka 事件驱动与 Redis 缓存 |
| Outbox、跨服务一致 | 本地事务 + 投递器 / Saga | 分布式数据:事务、幂等与 Saga |
| 脚手架、BOM | Spring Boot 3.5 + Cloud BOM | Spring Boot 3.5 与 Spring Cloud 脚手架 |
你已具备分布式问题域、CAP、架构形态、DDD 边界、API 契约与通信选型基础。下一阶段在 ShopFlow 仓库中动手搭服务,建议从 Spring Boot 3.5 与 Spring Cloud 脚手架 开始。
每条对应上一节 h3,basics 阶段收官复述。
过关清单(勾选会保存在本浏览器)
0 / 5 已勾选
| 概念 | 一句 |
|---|---|
| 同步 | 当场要结果;宜短链 + 幂等 |
| 异步 | 事件解耦;消费幂等 |
| 编排 | 中央协调多步 |
| 编舞 | 各服务听事件自行反应 |
| Outbox | 写库与待发事件同事务 |
下一步:勾选过关清单、完成测验与 Demo;进入 practice 阶段,从 Spring Boot 3.5 与 Spring Cloud 脚手架 搭建 ShopFlow 工程。
填写同步/异步选型与 Spring Cloud 映射表,并解释 Outbox 与 createOrder 代码块关系。
createOrder + OutboxEvent 片段:去掉 outbox 直接发 Kafka 会破坏哪条 BASE 配套手段?「order→inventory→payment→短信→积分」全 OpenFeign 同步且无超时。最先应改哪一处?
支付改异步事件(或至少缩短链并设超时)。支付结果不必阻塞 order 线程;全同步长链最易触发「同步滥用」中的线程堆积与级联失败。
PaymentCompleted 被 order 与 analytics 分别消费——编舞还是编排?新增 analytics 订阅者应改 order 还是只加消费者?
analytics 侧属编舞(听事件自行处理)。新增 analytics 订阅者只加 Kafka 消费者,无需改 order 编排代码,这是编舞扩展性优势。
目录:demos/basics-05-communication-patterns-lab/。验收:集成点选型表 3 行均已填模式 + 理由。