RPC原理与实现| 青训营笔记

65 阅读4分钟

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

RPC框架

基本概念

  • RPC:Remote Procedure Calls
  • RPC需要解决的问题
    • 函数映射
      • 在远程调用中,函数指针是不行的,因为两个进程的地址空间是完全不一样的,所以函数都有自己的一个ID,在做 RPC的时候要附上这个 ID,还得有个 ID 和函数的对照关系表,通过 ID找到对应的函数并执行。
    • 数据转换成字节流
      • 在本地调用中,我们只需要把参数压到栈里,然后让函数自己去栈里读就行。但是在远程过程调用时,客户端跟服务端是不同的进程,不能通过内存来传递参数。这时候就需要客户端把参数先转成一个字节流,传给服务端后,再把字节流转成自己能读取的格式。
    • 网络传输

概念模型

image.png

一次完整的过程

image.png

好处

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

image.png

分层设计

以Apache Thrift为例

image.png

编解码层-生成代码

image.png

数据格式

  • 语言特定的格式

    • 许多编程语言都内建了将内存对象编码为字节序列的支持,例如Java有java.io.Serializable
      • 和这门语言绑死在一起了。安全和兼容性也是问题
  • 文本格式

    • JSON、XML、CSV等文本格式,具有人类可读性
      • 由于JSON在一些语言中的序列化和反序列化需要采用反射机制,所以在性能比较差
  • 二进制编码

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

二进制编码

  • TLV编码
    • Tag:标签,可以理解为类型
    • Length:长度
    • Value:值,可以是TLV结构

image.png

选型

image.png

协议层

image.png

协议构造

image.png

解析

image.png

Sockets API

image.png

  • backlog的含义有点复杂,这里先简单的描述:指定挂起的连接队列的长度,当客户端连接的时候,服务器可能正在处理其他逻辑而未调用accept接受连接,此时会导致这个连接被挂起,内核维护挂起的连接队列,backlog则指定这个队列的长度,accept函数从队列中取出连接请求并接收它,然后这个连接就从挂起队列移除。如果队列未满,客户端调用connect马上成功,如果满了可能会阻塞等待队列未满(实际上在Linux中测试并不是这样的结果,这个后面再专门来研究)

网络库

  • 提供易用API
    • 封装底层Socket API
    • 连接管理和事件分发
  • 功能
    • 协议支持: tcp、udp 和uds等
    • 优雅退出、异常处理等
  • 性能
    • 应用层buffer 减少copy
    • 高性能定时器、对象池等

关键指标

稳定性

  • 熔断:保护调用方,防止被调用的服务出现问题而影响到整个链路
    • 一个服务 A 调用服务 B 时,服务 B 的业务逻辑又调用了服务 C,而这时服务 C 响应超时了,由于服务 B 依赖服务 C,C 超时直接导致 B 的业务逻辑一直等待,而这个时候服务 A 继续频繁地调用服务 B,服务 B 就可能会因为堆积大量的请求而导致服务宕机,由此就导致了服务雪崩的问题
  • 限流:保护被调用方.防止大流量把服务击垮
  • 超时控制:避免浪费资源在不可用节点上

image.png

请求成功率-重试

  • 避免重试风暴

image.png

长尾请求

image.png

  • 我们预先设定一个阈值 t3(比超时时间小,通常建议是 RPC 请求延时的 pct99 ),当 Req1 发出去后超过 t3 时间都没有返回,那我们直接发起重试请求 Req2 ,这样相当于同时有两个请求运行。然后等待请求返回,只要 Resp1 或者 Resp2 任意一个返回成功的结果,就可以立即结束这次请求,这样整体的耗时就是 t4 ,它表示从第一个请求发出到第一个成功结果返回之间的时间,相比于等待超时后再发出请求,这种机制能大大减少整体延时。

注册中间件

image.png

易用性

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

image.png

扩展性

image.png 一次请求发起首先会经过治理层面,治理相关的逻辑被封装在middleware中,这些middleware会被构造成一个有序调用链逐个执行,比如服务发现、路由、负载均衡、超时控制等,mw执行后就会进入到remote 模块,完成与远端的通信

观测行

image.png

高性能

image.png

企业实践

Kitex

image.png image.png

  • 扩展性设计 image.png
  • 网络库优化

image.png

  • 编解码优化

image.png

  • 合并部署

image.png

image.png