这是我参与「第三届青训营 -后端场」笔记创作活动的的第 5 篇笔记
目录
- 本地函数调用流程
- RPC 是什么
本地函数调用流程
func main() {
var a = 2
var b = 3
result := calculate(a, b)
fmt.Println(result)
// ...
}
func calculate(x, y int) (z int) {
z := x * y
return
}
调用过程:
- 将 a, b 的值压栈
- 通过函数指针找到 calculate 的起始地址,并取出栈中 a, b 的值,将其赋给形参 x, y
- 计算 x * y,并将结果存在变量 z 中
- 将 z 的值压栈,然后从 calculate 返回
- 从栈中取出 z 的返回值,并赋值给 result
但是在不同的进程间,程序的栈都是“私有”的,其他的进程不能访问其他进程的栈。也就是说,在一个程序中无法调用其他程序里的函数。
RPC 是什么
RPC,全称 Remote Procedure Calls 远程函数调用,可以让当前的程序执行其他程序中的函数,并且得到相应的返回值
要想实现 RPC,则需要解决这样几个问题:
-
函数映射
前面我们看过了本地函数调用的过程,想要进行函数调用,我们需要先知道函数在的位置。在本地我们是通过函数指针执向待执行函数在内存中的位置来实行的调用。而在RPC中,我们可以建立一张 ID 和函数关系的对应表,每一个可以远程调用的函数都具有唯一的 ID,并且再被调用前需要在这张表上进行注册。 -
数据转换成字节流
接下来是实参的压栈,因为不在同一块内存中,所以我们需要将实参转换为字节流,并通过一定方式发送到对应函数所在的远程地址,在远程将数据反序列化后,得到远程函数所需要的数据 -
网络传输
通过网络将字节流数据发送到远程的函数并执行,函数执行完成后将结果序列化后再返回远程调用的进程
RPC 和好处
- 弄够区分不同的职责,使职责单一化,有利于分工协作和运维开发
- 可扩展性强,能提高资源的利用率
- 能够实现故障隔离,使服务的整体可靠行性更高,避免由于单一服务的崩溃而导致整个系统的停机
PRC 带来的问题
- 被调用的服务宕机,调用方该如何处理?
- 在整体设计 RPC 框架时,采用负载均衡、断线重试等策略提高请求的成功率,提高调用的稳定性
- 网络异常波动等因素对远程调用的干扰该如何解决?
- 定时对网络设施进行检修和维护,保证网络畅通可用
- 若服务的请求突增导致服务器无法及时处理该怎样应对?
- 对程序进行优化,合理利用缓冲,使用内存池和对象池,减小 GC 开销