深入浅出RPC 框架
对于在网络上使用的应用,如何在网络上更高效的调用显得尤为重要。特别是本地调用和远程调用这巨大的区别对比。
01 基本概念
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
}
-
将 a 和 b 的值压栈
-
通过函数指针找到 calculate 函数,进入函数取出栈中的值 2 和 3, 将其赋予 x 和 y
-
计算 x*y, 并将结果存在 z
-
将 z 的值压栈,然后从 calculate 返回
-
从栈中取出 z 返回值,并赋值给 result
1.2 远程函数调用(RPC - Remote Procedure Calls)
RPC 需要解决的问题
-
函数映射
-
数据转化成字节流
-
网络传输
函数映射
本地调用中,函数体是直接通过函数指针来指定的,我们调用哪个方法,编译器就自动帮我们调用相应的函数指针。
在远程调用中,无法使用函数指针这种方法,因为两个进程的地址空间是完全不一样的。所以函数都有自己的一个ID,做RPC时要给每个函数附上ID,还得有个ID 和函数的对照关系表(Map?),通过ID找到对应的函数并执行。
客户端传参(如何把信息发给支付服务)
本地调用中,我们只需要把参数压入栈里,让函数自己去栈里读取。
在远程调用中,客户端和服务端是不同的进程,需要通过内存来传递参数。
需要客户端转换一个字节流给服务端,再把字节流转成自己可以读取的格式。
网络传输
远程调用往往用在网络上,如何保证网络传输上的高效稳定。
1.3 RPC概念模型
1.4 一次 RPC 的完整过程
IDL(interface description language)文件
IDL 通过一种中立的方式来描述接口,使得在不同平台上运行的对象和用不同语言编写的程序可以相互通信
生成代码
通过编译器工具把 IDL 文件转换成语言对应的静态库
通信协议
规范了数据在网络中的传输内容和格式,除必须的请求/响应数据外,通常还会包含额外的元数据
网络数据
通常基于成熟的网络库走 TCP/UDP 传输