RPC框架原理|青训营

74 阅读6分钟

基本概念

本地函数调用

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. 首先将a和b的值压栈。
  2. 通过函数指针找到calculate函数,进入函数取出栈中的值2和3,将其赋值给x和y。
  3. 计算x*y,将结果存在z。
  4. 将z的值压栈,然后从calculate返回。
  5. 从栈中取出z返回值,并赋值给result。

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

远程函数调用和本地函数调用区别是远程函数调用是通过网络调用函数。

RPC需要解决的问题

  1. 函数映射

    每个函数附上id,远程RPC通过id找到函数

  2. 数据转换成字节流

    RPC调用不能通过内存传递参数,需要客户端将数据转换成字节流传递给服务端,服务端再将字节流转换成数据。

  3. 网络传输

RPC概念模型

image-20230829200459834.png

一次完整的RPC调用

  • IDL(Interface description language)文件

因为客户端不知道服务端有哪些函数,所以需要IDL。IDL通过一种中立的方式来描述接口,使得在不同平台上运行的对象和用不同语言编写的程序可以相互通信。

  • 生成代码

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

  • 编解码

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

  • 通信协议

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

  • 网络传输

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

image-20230829202153300.png

RPC的好处

  1. 单一职责,有利于分工协作和运维开发
  2. 可扩展性强,资源使用率更优。可以单独提高某项功能的性能和取消或降低某项功能服务的性能
  3. 故障隔离,服务的整体可靠性更高

RPC 带来的问题

  1. 服务端宕机,客户端该如何处理?
  2. 在调用过程中发生网络异常,如何保证消息的可达性?正确性?
  3. 请求量突增导致服务无法及时处理,有哪些应对措施?

以上问题都可以通过RPC框架解决

分层设计

分层模型

编解码层、协议层、网络通信层。

07d981336bbcd7dd3bf1db4557444287.png

编解码层

生成代码

image-20230829203923522.png

  • 语言特定的格式

许多编程语言都内建了将内存对象编码为字节序列的支持,例如Java的java.io.Serializable。

  • 文本格式

JSON、XML、CSV等文本格式,具有人类可读性

  • 二进制编码

具备跨语言和高性能等优点,常见有Thrift的 BinaryProtocol,Protobuf等

二进制编码

TLV编码

  • Tag:标签,可以理解为类型
  • Length:长度
  • Value:值,Value也可以是个TLV结构
选型
  • 兼容性:支撑自动增加新的字段,而不影响老的服务,这将提高系统的灵活度。

  • 通用性:支持跨平台、跨语言

  • 性能:从空间和时间两个维度考虑,也就是编码后数据大小和编码耗费时长。

协议层

概念

协议是双方确定的交流语义,比如: 我们设计一个字符串传输的协议,它允许客户端发送一个字符串,服务端接收到对应的字符串。这个协议很简单,首先发送一个4字节的消息总长度,然后再发送1字节的字符集charset长度接下来就是消息的paload字符集名称和字符串正文.

持殊结束符:过于简单,对于一个协议单元必须要全部读入才能够进行处理,除此之外必须要防止用户传输的数据不能同结束符相同,否则就会出现紊乱

HTTP 协议头就是以回车(CR)加换行(LF)符号序列结尾。

变长协议: 一般都是自定义协议,有 header 和 payioad 组成,会以定长加不定长的部分组成,其中定长的部分需要描述不定长的内容长度,使用比较广泛

构造协议

image-20230829210756476.png

  • LENGTH: 数据包大小,不包含自身
  • HEADER MAGIC: 标识版本信息,协议解析时候快速校验
  • SEQUENCE NUMBER: 表示数据包的 seaID可用于多路复用,单连接内递增
  • HEADER SIZE: 头部长度,从第14个字节开始计算一直到 PAYLOAD前
  • PROTOCOL ID:编解码方式,有 Binary 和Compact 两种
  • TRANSFORM ID:压缩方式,如 zlib 和 snappy
  • INFO ID: 传递一些定制的 meta 信息
  • PAYLOAD: 消息体
协议解析

image-20230829211759289.png

网络通信层

Sockets API

image-20230829212809281.png

网络库

提供易用API

  • 封装底层Socket API
  • 连接管理和时间分发

功能

  • 协议支持:tcp、udp和uds等
  • 优雅退出、异常处理等

性能

  • 应用层Buffer减少copy
  • 高性能定时器、对象池等

关键指标

稳定性

保障策略

  • 熔断:保护调用方,防止被调用的服务出现问题而影响整个链路
  • 限流:保护被调用方,防止大流量把服务压垮
  • 超时控制:避免浪费资源在不可用节点上

image-20230829213452703.png

请求成功率

长尾请求

注册中间件

易用性

  • 开箱即用:合理的默认参数选项,丰富的文档
  • 周边工具:生成代码工具,脚手架工具

扩展性

image-20230829213902354.png

观测性

高性能

场景

  • 单机多机
  • 单连接多连接
  • 单/多Client 单/多Server
  • 不同大小的请求包
  • 不同请求类型

目标

  • 高吞吐
  • 低延时

手段

  • 连接池
  • 多路复用
  • 高性能编解码协议
  • 高性能网络库

总结

RPC是一种通过网络通信协议,让本地应用程序能够调用远程应用程序中函数的技术。在分布式系统中,为了提高系统的可用性和可伸缩性,常常需要将应用程序拆分为多个模块,并通过网络通信将它们连接起来。RPC框架就是用来实现这种网络通信的。

RPC框架的核心指标包括:

  1. 性能:RPC框架的性能直接影响到整个系统的性能,因此需要保证高吞吐量、低延迟和低抖动。
  2. 可靠性:RPC框架需要保证消息的可靠传输,避免数据丢失或乱序到达。
  3. 可扩展性:RPC框架需要支持高并发、大规模的请求处理,并且能够轻松地扩展到多个机器或数据中心。
  4. 安全性:RPC框架需要保证数据的安全性,包括身份认证、授权、加密等。
  5. 易用性:RPC框架需要简单易用,能够快速集成到现有的应用程序中。