4. 服务间同步通信基础
同步通信是微服务之间最直观的交互方式:调用方发起请求后阻塞等待,直到收到响应或超时。在 AWS 上,同步通信的承载方式通常是 ALB/NLB、API Gateway、Cloud Map 服务发现,以及 ECS/EKS/Lambda 计算载体。真正决定系统表现的,不是“用了 HTTP”,而是选择了 REST、gRPC 还是 GraphQL 这三种风格中的哪一种,以及它们与 AWS 基础设施的配合方式。
三种风格的本质差异
REST 以资源为中心,用 HTTP 方法和 URI 表达操作,报文通常是 JSON,语义简单、可读性强、调试成本低。gRPC 以服务方法为中心,使用 Protocol Buffers 定义接口,基于 HTTP/2 多路复用和二进制帧传输,天然支持流式调用和强类型契约。GraphQL 以数据图为中心,客户端在单次请求中声明所需字段,服务端按查询计划聚合多个数据源,适合前端驱动的聚合场景。
三者的关键区别可以归纳为:REST 是“资源 + 通用方法”,gRPC 是“方法 + 强契约 + 二进制”,GraphQL 是“查询 + 字段选择 + 单端点”。这决定了它们在延迟、吞吐、契约演进和调试体验上的不同取舍。
性能对比:不要只看单次延迟
在 AWS 同可用区内部,三种风格的端到端延迟差异主要来自序列化、连接复用和网关转发。以下为教学示例参数,用于说明量级关系,并非实测结果:REST 使用 JSON 序列化,单次调用约 2–8 ms;gRPC 使用 Protobuf 二进制,单次调用约 1–4 ms;GraphQL 若聚合 3 个下游数据源,单次请求约 5–20 ms。吞吐方面,gRPC 因 HTTP/2 多路复用和更小的报文体积,在同等实例规格下通常能获得更高的 QPS;REST 受限于 JSON 解析和 HTTP/1.1 队头阻塞,需要更多连接;GraphQL 的吞吐取决于 Resolver 的并发编排能力。
需要特别注意的是,AWS 上的性能瓶颈往往不在协议本身,而在网关和负载均衡器的配置。例如 ALB 对 gRPC 的支持需要目标组协议为 HTTP/2 或 gRPC,且健康检查路径必须与 gRPC 健康检查协议匹配;API Gateway 的 REST API 不支持 HTTP/2 到后端的原生 gRPC 透传,若强行使用会退化为 HTTP/1.1。因此选型时必须把“协议能力”和“AWS 承载能力”一起评估。
实现要点:从契约到部署
REST 的实现要点是契约先行。使用 OpenAPI 定义接口,在 API Gateway 中导入并生成 SDK,后端 ECS 服务通过 Cloud Map 注册,调用方通过服务发现获取实例地址。关键配置包括:为每个资源设置合理的缓存头,对写操作使用幂等键,对跨服务调用设置连接超时和重试策略。
# 示例:ECS 服务通过 Cloud Map 发现订单服务
aws servicediscovery create-service \
--name order-svc \
--namespace-id ns-abc123 \
--dns-config "NamespaceId=ns-abc123,RoutingPolicy=WEIGHTED,DnsRecords=[{Type=A,TTL=10}]"
# 调用方解析:order-svc.ns-abc123.local:8080
# 配合 ALB 目标组健康检查 /healthz,超时 2s,重试 2 次
gRPC 的实现要点是接口定义与连接管理。在 .proto 中定义 service 和 message,使用 protoc 生成客户端和服务端代码。AWS 上推荐将 gRPC 服务部署在 EKS 或 ECS 中,前端使用 NLB 或 VPC Lattice 做 L4/L7 转发。由于 gRPC 长连接特性,需要配置连接池和 keepalive,避免连接被中间设备静默断开。健康检查应使用 gRPC Health Checking Protocol,而不是 HTTP 探针。
// 示例:订单服务 gRPC 接口定义
service OrderService {
rpc GetOrder (GetOrderRequest) returns (Order);
rpc StreamOrders (StreamRequest) returns (stream Order);
}
message GetOrderRequest { string order_id = 1; }
message Order { string order_id = 1; string status = 2; double amount = 3; }
GraphQL 的实现要点是 Schema 设计与 Resolver 编排。在 AppSync 中可以使用 VTL 或 JavaScript Resolver 直接对接 DynamoDB、Lambda 和 HTTP 数据源;自建 GraphQL 服务则通常部署在 Lambda 或 ECS 上,通过 DataLoader 批量加载解决 N+1 问题。AWS AppSync 还提供缓存、订阅和细粒度授权,适合快速构建 BFF 层。需要注意的是,GraphQL 单端点会削弱基于路径的 WAF 规则和缓存策略,应配合查询深度限制和复杂度分析防止恶意查询。
选型决策:按场景而非偏好
如果服务需要对外暴露、被浏览器直接调用、或依赖 HTTP 缓存,优先选择 REST。如果服务位于内部、调用频率高、需要流式传输或强类型契约,优先选择 gRPC。如果前端需要灵活组合多个数据源、且团队愿意承担 Resolver 复杂度,GraphQL 是合适的 BFF 方案。在同一个系统中,三者可以共存:对外 REST、内部 gRPC、前端 GraphQL 聚合,这是 AWS 上常见的混合架构。