6.7 KiB
6.7 KiB
tags, create time
| tags | create time | ||||||
|---|---|---|---|---|---|---|---|
|
2026-05-05 |
服务间通信
概述
微服务之间如何通信,是架构设计的核心决策之一。选错了通信方式,后面会带来一系列问题:耦合度太高、性能瓶颈、或者运维复杂度爆炸。
RPC vs RESTful API
对比分析
| 维度 | REST over HTTP/JSON | gRPC (HTTP/2) | GraphQL |
|---|---|---|---|
| 性能 | 序列化开销大 | Protocol Buffers,二进制高效 | 中等(JSON) |
| 人类可读 | URL + JSON 直观 | 需要 Proto 定义辅助理解 | 查询语言自描述 |
| 语言兼容性 | 广泛,任何能发 HTTP 的语言都能用 | 需要代码生成 | 需客户端 SDK |
| 缓存 | 天然支持 HTTP 缓存 | 不支持(HTTP/2 多路复用替代) | 可设计缓存层 |
| 版本管理 | URL 路径 (/v1/, /v2/) | Proto 文件向前兼容 | Schema 演进工具 |
| 适用场景 | 对外 API、跨团队/跨组织调用 | 内部服务间高频强类型调用 | 前端聚合查询、移动端 |
graph TB
subgraph "何时选什么?"
D{"你的场景是?"}
D -->|"对外暴露 API"| REST["REST over HTTP"]
D -->|"内部服务高频调用"| GRPC["gRPC"]
D -->|"前端/移动端复杂查询"| GraphQL["GraphQL"]
D -->|"异步解耦通知"| MQ["消息队列"]
end
混合通信模式(推荐)
实际工程中很少单一选型。最佳实践是混合使用:
sequenceDiagram
participant C as 客户端
participant GW as API Gateway
participant O as Order Service
note over C,O: 外部请求 — 用 REST/gRPC
C->>GW: POST /orders (HTTP/JSON)
GW->>O: CreateOrder (gRPC)
note over O,O: 内部处理 — 同步 + 异步组合
O->>O: 创建订单记录 (本地事务)
O-->>GW: {orderId: "ORD-001"}
GW-->>C: 200 OK
O->>O: Publish OrderCreated Event (MQ)
Note right of O: 通知类场景异步处理
同步通信
gRPC 协议详解
gRPC 基于 Protocol Buffers(Proto3),利用 HTTP/2 的多路复用特性,非常适合高性能的内部服务间调用。
[!tip] 深入阅读 06-gRPC — gRPC 深度指南,涵盖 Proto 进阶、流式调用、Interceptor、连接管理、生产最佳实践。
// proto/order/v1/order.proto
syntax = "proto3";
package order.v1;
service OrderService {
rpc CreateOrder(CreateOrderRequest) returns (CreateOrderResponse);
rpc GetOrder(GetOrderRequest) returns (Order);
rpc StreamOrders(StreamRequest) returns (stream Order); // 服务端流
}
message CreateOrderRequest {
string user_id = 1;
repeated Item items = 2;
float total = 3;
}
message Item {
string product_id = 1;
int32 quantity = 2;
}
enum OrderStatus {
UNKNOWN = 0;
PENDING = 1;
PAID = 2;
SHIPPED = 3;
CANCELLED = 4;
}
Proto3 注意事项:
- 字段编号(
= 1,= 2)不能重编——破坏向后兼容 - 新增字段标记为
optional时 Proto3 才能区分"未设置"和"默认值" repeated字段空数组不会省略,需要特殊处理
RESTful API 设计规范
GET /api/v1/orders → 获取订单列表
POST /api/v1/orders → 创建订单
GET /api/v1/orders/{id} → 获取订单详情
PUT /api/v1/orders/{id} → 更新订单(全量替换)
PATCH /api/v1/orders/{id} → 部分更新
DELETE /api/v1/orders/{id} → 删除订单
核心原则:
- 资源名词化:URL 用名词复数,不用动词
- 无状态:每个请求携带完整上下文(通过 Header 传 Token)
- 统一接口:用标准 HTTP Method + Status Code 表达语义
异步通信
事件驱动架构
[!question] 关键时刻的判断 用户点击"提交订单"后,系统要做:① 创建订单记录 ② 扣减库存 ③ 扣款 ④ 发送短信通知。哪些步骤必须同步完成?哪些可以异步处理?为什么?
答案:①~③需要立即得到结果或保证一致性,走同步流程;④纯粹的通知类场景完全异步,用消息队列解耦。即使扣款失败,短信也没必要发出。
graph LR
A["订单创建"] --> B{"是否需要同步响应?"}
B -->|"是"| Sync["同步 RPC 链"]
B -->|"否"| Async["异步 MQ 事件"]
Sync --> Stock["查库存 (RPC)"]
Stock --> Pay["支付 (RPC)"]
Async --> SMS["发短信 (Event)"]
Async --> Points["加积分 (Event)"]
Async --> Email["发确认邮件 (Event)"]
消息队列选型
| 方案 | 吞吐量 | 延迟 | 可靠性 | 特色能力 |
|---|---|---|---|---|
| RocketMQ | 极高 (百万级) | 毫秒级 | 事务消息支持 | 阿里出品,国内首选 |
| Kafka | 最高 (千万级) | 秒级 | 持久化 | 大数据生态集成 |
| RabbitMQ | 中等 (十万级) | 亚毫秒 | 高 | 灵活的路由模型 |
| Pulsar | 高 | 毫秒级 | 高 | 存储计算分离 |
发布订阅 vs 点对点
graph TB
Publisher[生产者] --> Broker[(MQ Broker)]
Broker --> Sub1["消费者组 A<br/>Topic: order-events"]
Broker --> Sub2["消费者组 B<br/>Topic: order-events"]
Broker --> Sub3["消费者组 C<br/>Topic: order-events"]
style Sub1 fill:#cfe2f3
style Sub2 fill:#d9e2f3
style Sub3 fill:#e2d9f3
- 发布订阅 (Pub/Sub):一个消息被多个消费组分别消费,每个组内只有一个实例收到
- 点对点 (Queue):一条消息只被一个消费者处理
同步与异步的组合拳
sequenceDiagram
participant Client
participant Gateway
participant Order
participant MQ
participant Notify
participant Analytics
Client->>Gateway: 下单请求
Gateway->>Order: 创建订单
Order->>Order: 写库 + 出消息(事务)
Order-->>Gateway: 返回 orderId
Gateway-->>Client: 202 Accepted ⚡
Note over MQ: 异步后续处理
MQ->>Notify: 发送通知
MQ->>Analytics: 数据统计
Note right of Client: 用户体验好:<br/>主流程快速响应<br/>非关键任务后台处理
[!keypoint] 关键洞察
- 同步链路:gRPC 直连,延迟低,适合核心事务链
- 异步链路:消息队列,解耦非关键路径,即使失败也不影响主干
- 核心原则:同步保性能,异步保解耦
关联笔记
- 02-服务治理/01-API网关 — API Gateway 负责协议转换
- 03-数据一致性/02-分布式事务 — 消息投递的一致性保障
- 05-部署运维/02-Kubernetes — Sidecar 代理透明拦截通信流量