Skip to content

RPC

RPC(Remote Procedure Call)即远程过程调用,是一种进程间通信方式。它允许程序调用另一个地址空间的过程或函数,而不用了解底层通信细节。

从程序员角度而言,RPC与本地调用几乎是相同的,它使得远程交互可以像本地调用一样简单。RPC框架屏蔽了底层的通信细节和网络交互复杂度。

常用的RPC框架包括gRPC、Thrift、Http-RPC等。使用RPC可以更容易实现服务间通信与集成,构建分布式计算系统。

下面是常见的RPC框架的组成结构

thrift

参考

Thrift 是 Facebook 开源的一个 RPC 框架,使用自己开发的接口描述语言(IDL)来定义服务接口和数据结构。

Thrift 通过代码生成产生不同语言的客户端和服务端代码。客户端与服务端可以使用 Thrift 的二进制协议进行通信,该协议具有良好的跨语言互操作性。

Thrift 支持多种服务模型,比如multiplexing、非阻塞异步 IO等。它支持众多流行编程语言,使用也比较灵活。但是其自有协议增加了一定额外开销。

Thrift是一个轻量级、跨语言的RPC框架,包含如下特性

  • 基于IDL(接口描述语言)生成跨语言的RPC clients and servers,支持超过20种语言
  • 支持二进制的高性能的编解码框架
  • 支持NIO的底层通信
  • 相对简单的服务调用模型

语法

Thrift 传输数据采用二进制格式,相对 XML 和 JSON 体积更小,对于高并发、大数据量和多语言的环境更有优势。

关键字

  • namespace 定义包名
  • struct 定义服务接口的参数,返回值使用到的类结构。如果接口的参数都是基本类型,则不需要定义struct
  • service 定义接口

数据类型

bool 布尔型
byte 8位整数
i16  16位整数
i32  32位整数
i64  64位整数
double 双精度浮点数
string 字符串
binary 字节数组
list<i16> List集合,必须指明泛型
map<string, string> Map类型,必须指明泛型
set<i32> Set集合,必须指明泛型

使用过程

在过去我参与过的项目开发中,前端会负责使用Node.js封装数据接口作为bff层,自己定制前端需要的数据。开发模式一般为

  • 后端提供Thrfit描述文件
  • 前端拿到描述文件后,通过thrfit编译器生成对应的Node.js接口lib文件
  • 在业务系统中,引入对应的lib文件,在封装的接口内调用,加工一下数据,然后通过HTTP JSON返回给前端。

接下来演示一个使用Java作为服务端编写接口,使用Node.js作为客户端通过Thrift调用接口的RPC调用过程。

首先,服务端开发人员根据业务需要,定义IDL接口文件,说明服务端要开放出去的接口函数、参数和数据结构

thrift
service UserService {
   bool addUser(1: User user);
}

struct User {
  1: i64 id,  
  2: string name
}

然后,服务端会通过服务端使用Thrift编译器,基于上述IDL接口描述文件,生成代码框架,实现服务器端逻辑。

java
public class UserServiceImpl implements UserService.Iface {

  public boolean addUser(User user) {
    // 实现加用户逻辑
  } 
}

最后在客户端,会根据相同的IDL文件,通过Thrift编译器生成客户端代码,用来调用服务器端导出的接口

thrift --gen js user_service.thrift

这个命令会生成一段js调用PRC服务端的代码,在自己的业务代码中,需要引入这个模块,然后使用相关的API完成接口调用。

gRPC

TODO 暂时没有使用过