这篇文章是 RPC 系列的第一篇,打算写一个系列的文章,简单介绍下 Duboo2, Dubbo3, gRPC 及 RScoket 的使用方法及差异。在 Alligator 项目中借鉴了其中的一些思想,基于 TCP, Websocket 及 MQ,实现了一个简单的 RPC。RPC 涉及到内容比较多,这里选取了两个方面做为切入点:1)通信模式,包括 request-response, request-stream, stream-response, stream-stream, send-oneway; 2)协议,主要是协议字段,通过这些字段可以大概猜测出其实现方式。
一句话 RPC
Wikipedia 对 RPC 的解释:
In distributed computing, a remote procedure call (RPC) is when a computer program causes a procedure (subroutine) to execute in a different address space (commonly on another computer on a shared network), which is coded as if it were a normal (local) procedure call, without the programmer explicitly coding the details for the remote interaction.
这里有几个重点:
- RPC 调用通常是不同进程间的调用,而这些进程一般通过网络进行连接;
- 对上层应用而言,本地调用与远程调用在使用方式上没有差异;
- RPC 封装了底层通信的细节,不需要开发人员显示地编码。
下面以一个例子说明:
接口定义:1
2
3public interface HelloService {
String sayHello(String message);
}
客户端:
1 | public class HelloClient { |
在客户端为接口生成一个代理,并将方法名及参数序列化之后,通过一定的协议发送给服务器,最后同步读取服务端返回的数据作为方法的响应。
服务器:
1 | // 接口实现类 |
在服务端实现接口,监听网络的请求,按照协议,反序列化方法名及参数,并通过反射的方式映射到具体的接口实现,转换为本地方法调用,调用结束之后,再将结果返回给客户端。
一句话总结:RPC 就是一种网络编程技术,结合代理、序列化/反序列技术,通过一定的通信协议,实现类似本地方法调用的功能。
通信模式
RPC 一般有如下五种通信模式。
Send-Oneway
特点:只发送请求数据,服务器不需要响应,适用于发送一些不关键的数据,如日志上报。
Request-Response
特点:最常见的模式,客户端发送一个请求,服务器响应一个结果。
Reqeust-Stream
特点:发送一个请求,可以返回多个响应结果。
Stream-Response
特点:发送多个请求,响应一个结果。
Stream-Stream
特点:双向流的模式,客户端及服务器都向对方发送多个数据,互不干扰。
总结
一个完整的 RPC 流程包括三个步骤:
- 定义接口:可以使用中间语言,也可以使用特定的语言定义,如 JAVA;
- 生成客户端代理:根据接口定义,通过代码生成客户端代理,它封装了向服务端请求的代码;
- 编写服务器接口实现:生成服务器通信代码及编写接口的实现。
一个 RPC 框架通常提供代码生成的功能,客户端代理、服务器通信功能、序列化/反序列化的代码都会生成,开发者只需要编写接口定义及接口实现即可。