深入浅出RPC框架| 青训营笔记

20 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第13 天

基本概念

1.1 本地函数调用

func main( ){
	var a = 2
	var b = 3
	result := calculate(a, b)
	fmt.Println(result)
	return
}
func calculate(x, y int) {
	z := x*y
	return z
}

本地函数经常出现在我们写的单体项目中,就是直接调用某个包中的函数,这一过程发生在同一个进程中,不需要进行网络传输。

1.2远程函数调用(RPC - Remote Procedure Calls)

RPC(Remote Procedure Call Protocol)远程过程调用协议。一个通俗的描述是:客户端在不知道调用细节的情况下,调用存在于远程计算机上的某个方法,就像调用本地应用程序中的方法一样。

比较正式的描述是:一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。

image.png

函数映射

我们怎么告诉支付服务我们要调用付款这个函数,而不是退款或者充值呢?

  • 在本地调用中,函数体是直接通过函数指针来指定的,我们调用哪个方法,编译器就自动帮我们调用它相应的函数指针。
  • 但是在远程调用中,函数指针是不行的,因为两个进程的地址空间是完全不一样的。所有函数都有自己的一个ID,在做 RPC的时候要附上这个 ID,还得有个 ID 和函数的对照关系表,通过 ID找到对应的函数并执行。

客户端怎么把参数值传给远程的函数呢?

  • 在本地调用中,我们只需要把参数压到栈里,然后让函数自己去栈里读就行。
  • 但是在远程过程调用时,客户端跟服务端是不同的进程,不能通过内存来传递参数。这时候就需要客户端把参数先转成一个字节流,传给服务端后,再把字节流转成自己能读取的格式。

1.3 RPC概念模型

image.png

RPC框架的通信与具体的协议无关,RPC可基于HTTP或者TCP协议

1.4 一次RPC的完整过程

IDL (Interface description language)文件

  • IDL通过一种中立的方式来描述接口,使得在不同平台上运行的对象和用不同语言编写的程序可以相互通信

生成代码

  • 通过编译器具把IDL文件转换成语言对应的静态库

编解码

  • 从内存中表示到字节序列的转换称为编码,反之为解码,也常叫做序列化和反序列化

通信协议

  • 规范了数据在网络中的传输内容和格式。除必须的请求/响应数据外,通常还会包含额外的元数据

网络传输

  • 通常基于成熟的网络库走TCP/UDP传输

相比本地函数调用,远程调用的话我们不知道对方有哪些方法,以及参数长什么样,所以需要有一种方式来描述或者说声明我有哪些方法,方法的参数都是什么样子的,这样的话大家就能按照这个来调用,这个描述文件就是 IDL 文件。

服务双方是通过约定的规范进行远程调用,双方都依赖同一份IDL文件,需要通过工具来生成对应的生成文件,具体调用的时候用户代码需要依赖生成代码,所以可以把用户代码和生成代码看做一个整体。

1.5 RPC的好处

  1. 单一职责,有利于分工协作和运维开发
  2. 可扩展性强,资源使用率更优
  3. 故障隔离,服务的整体可靠性更高

总结

在微服务架构的时代,RPC是一个不可或缺的技术,今天主要了解了RPC框架的一些基本概念,至于底层的具体实现还需要进一步的学习。