Files
cs-note/hhs/MS/02-服务治理/05-服务间通信.md
T
2026-05-24 11:42:38 +08:00

6.7 KiB
Raw Blame History

tags, create time
tags create time
microservice
rpc
rest
grpc
message-queue
event-driven
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 直连,延迟低,适合核心事务链
  • 异步链路:消息队列,解耦非关键路径,即使失败也不影响主干
  • 核心原则:同步保性能,异步保解耦

关联笔记