RPC 框架初探
什么是 RPC
RPC(Remote Procedure Call),远程服务调用,是分布式系统绕不开的话题。RPC 是一个大的概念,这里我们缩小一下讨论的范围,只关注多个服务(进程)之间通过网络进行通信的问题。
我们通常意义上理解的 RPC,一般公认是施乐公司(Xerox PARC)于 1981 年在论文 Remote Procedure Call 提出的:
Remote procedure call is the synchronous language-level transfer of control between programs in disjoint address spaces whose primary communication medium is a narrow channel.
远程服务调用 是指位于互不重合的内存地址空间中的两个程序,在语言层面上,以 同步 的方式使用 带宽有限 的信道来传输程序控制信息。
虽然市面上的 RPC 框架有很多,但在功能上基本大同小异,所有 RPC 框架都需要关注三个基本问题:
- 如何表示数据 :这里的数据包含传输控制的元数据,传递方法的参数,以及方法的返回值。因为信息传递发生在网络中,两端的服务势必需要约定好一个统一的序列化/反序列化协议;如
gRPC
的Protocol Buffers
协议、XML、JSON 等; - 如何传递数据 :信息经过序列化之后,如何通过网络,在两个服务的 EndPoint 之间相互操作,交换数据。这里“交换数据”通常指的是应用层协议,实际传输一般是基于标准的 TCP、UDP 等传输层协议实现。两个服务的交互不仅仅是传递一个序列化流来表示参数和结果就行,在此之外还有许多额外信息,比如异常、超时、安全、认证、授权、事务等等,都需要考虑如何传递;相当于 RPC 事先约定的控制协议;
- 如何确定方法 :因为调用的是语言层面的方法,这里就需要服务双方约定一个规范,针对“如何表示一个方法”、“如何找到一个方法”的问题提出一个 跨语言 的规范,这个通常称为
IDL(Interface Definition Language)
,IDL 有不同的实现,如gRPC
使用Protocol Buffers
作为 IDL。
随着分布式架构在最近几年的兴起,RPC 框架除了在满足这三个基本问题的基础上,逐渐朝着更高层次(不仅负责调用远程服务,还管理远程服务)和插件化的方向发展。下面我们就挑选几个比较流行的 RPC 框架,进行简单的对比。
Dubbo
Dubbo 是阿里实现的一个 RPC 框架,后来捐献给 Apache 软件基金会,称为 Apache 的顶级项目。Dubbo 在提供 RPC 功能的基础上,还添加了服务监控和治理的功能,如服务发现、动态配置、负载均衡、流量路由等,官方目前对 Dubbo 的定义是一款 服务开发框架,因其兼顾了数据层面的 RPC 调用和服务层面的监控管理。
Dubbo 提供的核心功能包括:
- RPC 服务定义、开发范式 :支持通过 IDL 定义服务,也支持编程语言特有的服务开发定义方式,如通过 Java Interface 定义服务;
- RPC 服务发布与调用 API :支持同步、异步、Reactive Streaming 等服务调用编程模式,还支持请求上下文 API、设置超时时间等;
- 服务治理策略、流程与适配方式 :在服务框架层面,Dubbo 定义了服务地址发现、负载均衡策略、基于规则的流量路由、Metrics 指标采集等服务治理抽象,并适配特定的产品实现;
Dubbo 目前的发展,已经脱离了 RPC 框架的范畴,向 Spring Cloud 靠拢了。
gRPC
gRPC 是 Google 开源的一个 RPC 框架,使用 HTTP/2
协议传输,使用 Protocol Buffers
作为 IDL 和序列化协议。
gRPC 是一个高效的 RPC 框架,相比于其他 RPC 框架,gRPC 具有简单、高效、跨语言的特点:
gRPC 支持 4 种模式的 RPC 场景:
- 常规 RPC。客户端发起调用,服务端返回结果:
rpc SayHello(HelloRequest) returns (HelloResponse);
- 服务端流式 RPC。客户端发起调用,服务端返回数据流,客户端从返回的流中读取,直到数据读完为止。gRPC 保证单个 RPC 调用中消息有序:
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
- 客户端流式 RPC。客户端发起调用,向服务端写入一系列消息。当客户端完成消息写入后,等待服务端返回响应。gRPC 保证单个 RPC 调用中消息有序:
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
- 双向流式 RPC。客户端写入流,服务端返回流。这两个流独立运行,因此服务端可以控制读写的节奏。gRPC 保证两个流中消息有序:
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
Thrift
Thrift 是 Facebook 开源的 RPC 框架。Thrift 架构设计和 gRPC 类似,也是先编写 IDL 文件,然后使用编译器生成对应语言的代码模块(stub)。最后业务调用即可。
Thrift 和 gRPC 的性能表现网上有很多资料,这里就不赘述了。但我简单看了一下两个框架的官方文档,感觉 Thrift 的文档相对维护得差一些。
总结
本文只是针对 RPC 做了一些概念上的整理,不涉及具体产品的技术实现。感觉目前市面上常见的 RPC 框架,基本可以划分为两类:一类是“大而全”的,这类框架在 RPC 的业务场景下向外拓展了很多功能,以 Dubbo 为代表,成员有新浪的 Motan 等;另一类是“小而精”的,这类框架专注于 RPC 的核心功能,以 gRPC、Thrift 为代表。