第二章 访问远程服务
2.1 远程服务调用(RPC)
2.1.1 进程间通信机制
- 核心方式 :
- 管道(Pipe):单向通信,用于父子进程
- 信号(Signal):异步事件通知,不传递数据
- 套接字(Socket):跨网络通信基础,支持TCP/UDP
- 共享内存:高效但需同步机制,适用于高频数据交换
- 消息队列:异步通信,解耦生产消费方
2.1.2 通信成本关键要素
- 网络延迟:物理距离、路由跳数、协议栈处理时间
- 序列化开销:JSON/XML文本协议 vs ProtoBuf/Thrift二进制协议
- 资源消耗:连接池管理、线程模型(阻塞IO vs NIO)
- 典型延迟对比 :
- 本地方法调用:纳秒级
- 同机房RPC:0.1~1ms
- 跨地域RPC:10~100ms
2.1.3 三大核心问题
-
数据表示(序列化)
- 类型安全:强类型语言需要严格类型映射
- 版本兼容:字段增删时的前向/后向兼容策略
- 性能指标:序列化速度、数据压缩率、内存占用
- 典型协议:Protobuf(Google)、Thrift(Facebook)、Avro(Hadoop)
-
传输协议
- TCP长连接:复用连接降低握手开销
- HTTP/1.1:文本协议,支持持久连接
- HTTP/2:多路复用,头部压缩
- QUIC:基于UDP的可靠传输,0-RTT握手
-
服务定位
- 接口描述语言(IDL):定义服务契约
- .proto(gRPC)
- .thrift(Apache Thrift)
- 服务发现机制:
- 客户端直连(硬编码IP)
- 注册中心(Zookeeper、Consul、Nacos)
- DNS服务发现
- 接口描述语言(IDL):定义服务契约
2.1.4 RPC统一化尝试
-
CORBA(公共对象请求代理架构)
- ORB核心组件实现跨语言调用
- IDL编译器生成存根代码
- 失败原因:复杂规范、厂商实现差异、性能问题
-
Web Service体系
- SOAP协议:XML格式信封
- WSDL服务描述
- UDDI服务注册
- 问题:XML解析开销大,协议臃肿
2.1.5 RPC框架分化
-
主流实现对比:
框架 协议 序列化 传输 特点 gRPC HTTP/2 Protobuf TCP 多语言支持,流式通信 Thrift 自定义二进制 Thrift TCP 跨语言,代码生成 Dubbo 自定义 Hessian Netty 阿里生态,服务治理 Spring Cloud HTTP REST JSON HTTP 声明式接口,生态整合 -
性能关键点:
- 二进制协议相比文本协议节省30%-50%带宽
- 连接复用减少TCP握手开销
- 零拷贝技术降低内存复制次数
2.2 REST设计风格
2.2.1 REST本质理解
-
架构约束:
- 客户端-服务器分离:前后端独立演进
- 无状态:请求包含完整上下文
- 可缓存:明确缓存声明(Cache-Control)
- 统一接口 :
- 资源标识(URI)
- 表述操作(HTTP方法)
- 自描述消息(Content-Type)
- 超媒体驱动(HATEOAS)
- 分层系统:代理、网关透明接入
- 按需代码:JavaScript扩展客户端
-
常见误区:
- ≠ HTTP API:REST是架构风格,HTTP是实现载体
- ≠ CRUD映射:复杂操作可通过资源状态变更表达
2.2.2 RESTful设计实践
-
资源设计原则:
- 名词化URI:/users/{id}/orders
- 避免动词:用PUT /orders/{id}/cancel代替POST /cancelOrder
- 版本控制:URI路径(/v1/users) vs 请求头(Accept-Version)
-
HTTP方法语义:
方法 幂等性 安全 典型应用 GET 是 是 获取资源 POST 否 否 创建资源或触发操作 PUT 是 否 全量更新 PATCH 否 否 部分更新 DELETE 是 否 删除资源 -
超媒体控制(HATEOAS):
json{ "id": 123, "status": "pending", "_links": { "self": { "href": "/orders/123" }, "cancel": { "href": "/orders/123", "method": "DELETE" } } }
2.2.3 Richardson成熟度模型
- Level 0:使用HTTP作为传输隧道(SOAP over HTTP)
- Level 1:资源分离(不同端点对应不同操作)
- Level 2:HTTP动词+状态码规范使用
- Level 3:超媒体驱动,实现HATEOAS
2.2.4 REST局限性
- 复杂操作表达 :
- 批处理需设计特殊资源(/batch-operations)
- 事务性操作难以用单一资源表达
- 性能瓶颈 :
- 多次请求问题(n+1查询)
- 无二进制协议支持(可通过Protocol Buffers over HTTP缓解)
- 版本管理挑战 :
- URI版本导致客户端硬升级
- 媒体类型协商(Content Negotiation)复杂度高
关键对比:RPC vs REST
维度 | RPC | REST |
---|---|---|
通信范式 | 动作导向(调用方法) | 资源导向(操作资源状态) |
协议绑定 | 强绑定(特定协议) | 弱绑定(HTTP通用协议) |
服务发现 | 需要IDL和代码生成 | 通过超媒体动态发现 |
性能 | 高(二进制协议) | 中(文本协议) |
适用场景 | 内部服务间高效通信 | 公开API、跨组织集成 |
变更影响 | 接口变更需重新生成代码 | 可通过超媒体减少客户端修改 |
现代架构融合趋势
- gRPC-Web:浏览器端支持gRPC协议
- GraphQL over HTTP:声明式查询与REST端点结合
- RSocket:双向流式通信,支持RPC模式
- Service Mesh:在基础设施层统一处理RPC通信(如Istio的Envoy代理)
多选题
题目1:关于远程服务调用(RPC)的三个基本问题,以下哪些描述正确?
A. 如何表示数据(序列化协议)
B. 如何传递数据(传输协议)
C. 如何确定调用哪个方法(服务发现与路由)
D. 如何保证调用的高性能(负载均衡)
题目2:REST设计风格的核心约束条件包括哪些?
A. 客户端-服务器架构
B. 无状态通信
C. 统一接口
D. 必须使用JSON格式
题目3:RMM(Richardson成熟度模型)的四个层级包括哪些?
A. Level 0:基于HTTP的简单RPC
B. Level 1:资源化接口
C. Level 2:使用HTTP动词和状态码
D. Level 3:超媒体驱动(HATEOAS)
题目4:以下哪些是RPC与REST的典型区别?
A. RPC基于方法调用,REST基于资源操作
B. RPC通常使用二进制协议,REST使用文本协议(如HTTP)
C. RPC强调透明性,REST强调显式通信约束
D. RPC天然支持缓存,REST不支持缓存
题目5:关于"透明通信"的挑战,以下哪些描述正确?
A. 网络延迟和分区容错会影响透明性
B. 本地调用和远程调用的错误处理逻辑可以完全一致
C. 序列化/反序列化可能引入性能瓶颈
D. 服务发现与负载均衡是实现透明通信的必要条件
题目6:RESTful系统的"统一接口"原则包含哪些具体约束?
A. 资源的唯一标识(URI)
B. 通过标准HTTP方法操作资源
C. 自描述消息(如Content-Type)
D. 必须使用HATEOAS实现超媒体驱动
题目7:以下哪些是RPC分裂的原因?
A. 不同厂商对性能和协议的优化需求不同
B. 语言和框架的生态系统差异
C. REST设计风格的普及取代了RPC
D. 分布式事务的复杂性
题目8:关于HTTP/2对REST的影响,以下哪些描述正确?
A. 多路复用技术降低了HTTP/1.1的队头阻塞问题
B. 头部压缩减少了网络传输开销
C. HTTP/2的二进制协议更适合REST的文本交互
D. HTTP/2的流式通信与REST的无状态原则冲突
题目9:REST的不足与争议包括哪些?
A. 缺乏强类型接口定义,导致开发效率低
B. 超媒体驱动(HATEOAS)在实际应用中难以实现
C. 无状态约束无法满足复杂业务场景的会话管理需求
D. 对性能敏感的场景(如高频交易)不适用
题目10:以下哪些是设计分布式系统时需权衡的通信成本?
A. 网络延迟与带宽限制
B. 序列化/反序列化的计算开销
C. 服务发现与路由的复杂度
D. 代码的可维护性和团队协作成本
答案与解析
题目1答案:ABC
解析:
- RPC的三个基本问题是:数据表示(序列化)、数据传输(协议)、方法确定(服务定位)。
- D选项"高性能"是优化目标,但并非基本问题。
题目2答案:ABC
解析:
- REST的六大核心约束包括:客户端-服务器、无状态、统一接口、分层系统、缓存、按需代码(Code-On-Demand)。
- D选项"必须使用JSON"错误,REST支持多种数据格式(如XML、JSON等)。
题目3答案:ABCD
解析:
- RMM的四个层级为:
Level 0(简单RPC)、Level 1(资源化)、Level 2(HTTP动词+状态码)、Level 3(HATEOAS)。
题目4答案:ABC
解析:
- D错误,REST通过HTTP缓存机制(如Cache-Control)支持缓存,而RPC通常不原生支持缓存。
题目5答案:ACD
解析:
- B错误,远程调用需处理网络超时、重试等特有错误,与本地调用不同。
题目6答案:ABC
解析:
- D是Level 3的约束,属于RMM的扩展,非"统一接口"原则本身。
题目7答案:AB
解析:
- C错误,REST并未取代RPC;D是分布式系统的通用问题,非RPC分裂的直接原因。
题目8答案:AB
解析:
- C错误,HTTP/2的二进制协议与REST的文本交互无直接关联;D错误,HTTP/2的流式通信与无状态原则不冲突。
题目9答案:ABCD
解析:
- 所有选项均为REST的典型争议点。
题目10答案:ABCD
解析:
- 所有选项均属于通信成本范畴(网络、计算、系统复杂度、开发成本)。