基本概念
为啥用RPC
我们平时调用的都是本地调用,比如
func main(){
a := 2
b := 3
result := calculate(a,b)
return
}
func calculate(x,y int) int {
z := x * y
return z
}
我们会把
- 将a和b的值压栈
- 通过函数指针找到calculate 函数,进入函数取出栈中的值2和3,将其赋予×和y
- 计算x * y,并将结果存在z
- 将z的值压栈,然后从calculate返回
- 从栈中取出z返回值,并赋值给result 这开起来很合理,但是这有一个问题,就是当我各个模块进行线上部署的时候是分开部署的,那么他们之间的信息怎么传递呢?这个时候就要用到RPC(远程函数调用)框架了
RPC基本概念
RPC需要解决的问题
- 函数映射
- 数据转换成字节流
- 网络传输 要解决这些问题才可以实现线上传输数据的功能
一次RPC的完整流程
- IDL通过一种中立的方式来描述接口,使得在不同平台上运行的对象和用不同语言编写的程序可以相互通信
- 通过编译器工具把IDL文件转换成语言对应的静态库
- 从内存中表示到字节序列的转换称为编码,反之为解码,也常叫做序列化和反序列化
- 规范了数据在网络中的传输内容和格式。除必须的请求/响应数据外,通常还会包含额外的元数据
- 通常基于成熟的网络库走 TCP/UDP 传输
编码层
用户端和服务端依赖同一份idl文件,然后idl文件生成不同语言的CodeGen到各个不同语言的服务器中
- 许多编程语言都内建了将内存对象编码为字节序列的支持,例如 Java 有java.io.Serializable,这种就是言特定的格式,就不能跨语言了
- JSON、XML、CSV等文本格式,具有人类可读性,这种是本格式,难以传递复杂信息,并且低效
- 具备跨语言和高性能等优点,常见有Thrift 的 BinaryProtocol,Protobuf等
协议层
- 协议构造
- 协议解析
网络通信层
Sockets API(套接字 API)是用于网络通信的接口,允许程序进行网络编程,通过网络协议(如 TCP/IP 或 UDP)在网络上进行数据交换。它为应用程序提供了与其他程序(无论是在同一台计算机上还是不同计算机之间)进行通信的能力。
但是一般高级的网络库/框架都封装了更复杂的通信机制,并提供了更高层次的接口,使得开发者可以专注于业务逻辑而不必关心底层的通信协议
稳定性
降级策略
降级(Degradation)是指在系统出现压力过大、异常或无法提供完整服务时,通过降低服务质量来保障系统的可用性和稳定性的一种手段。降级通常是为了解决系统负载过高或某个服务不可用时,采取的应急措施,确保系统整体的稳定性和用户体验。
降级可以包括但不限于 熔断、限流、超时控制等措施,这些都属于降级的一部分,但降级的范围可能更广。让我们具体看一下降级和熔断、限流、超时之间的关系。
注册中间件
注册一个包含了降级策略,限流,重试,负载均衡,BackupRequest的中间件来保证稳定性