深入浅出RPC | 青训营

133 阅读5分钟

st基本概念

什么是RPC

RPC,全称Remote Procedure Call, 即远程过程调用。

主要作用是屏蔽网络编程细节,实现调用远程方法就像调用本地方法(同一个进程中的方法)一样的体验。

同时屏蔽底层网络通信的复杂性,让我们更加专注业务逻辑的开发。

过程调用有时也被称为函数调用或子程序调用。

本地函数调用:

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. 函数映射
  2. 数据转换成字节流
  3. 网络传输

一次完整的RPC调用

35112f04cbcdadcbd142f934745bc24.png

  • IDL(Interface descriptlon language)

IDL通过一种中立的方式来描述接口,使得在不同平台上运行的对象和用不同语言编写的程序可以相互通信

  • 生成代码

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

  • 编解码

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

  • 通信协议

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

  • 网络传输

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

RPC的好处

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

RPC带来的问题

  1. 服务宕机,该如何处理?

  2. 调用过程中发生网络异常,如何保证消息的可达性?

  3. 请求量突增导致服务无法及时处理,有哪些应对措施?

    以上问题将有RPC框架来解决

RPC框架

RPC框架采取分层设计

  • 编码解码层
  • 协议层
  • 网络通信层

eg: 00e5e272d2e8f0677659dd29bbfab2f.png

编解码层

生成代码

497d40dc2e0fbbbdc8b4aab49c99071.png

数据格式

  • 语言特定的格式

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

  • 文本格式

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

  • 二进制编码

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

二进制编码

TLV编码

-Tag:标签,可以理解为类型

-Lenght:长度

-value:值,vaue也可以是个TLV结

struct Person{
  1: required string         userName,
  2: optional i64            favoriteNumber,
  3: optional list<string>   intersts
}

选型

  • 兼容性

    支持自动增加新的字段,而不影响老的服务,这将提高系统的灵活度

  • 通用性

    支持跨平台、跨语言

  • 性能

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

协议层

概念

  • 特殊结束符

    一个特殊字符作为每个协议单元结束的标示

    message body\r\nmessage body\r\n
  • 变长协议

    以定长加不定长的部分组成,其中定长的部分需要描述不定长的内容长度

lengthmessage bodylengthmessage body

协议构造

b9ecda67be14f0f1109722ab82aea23.png

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

协议解析

cb701659dae9383bb5df94b19caf7da.png

网络通信层

网络库

  • 提供易用API

    封装底层aocket API

    连接管理和事件分发

  • 功能

    协议支持:tcp、udp和uds等

    优雅推出】异常处理等

  • 性能

    应用层buffer减少copy

    高性能定时器、对象池等


关键指标

  • 稳定性
  • 易用性
  • 扩展性
  • 观测性
  • 高性能

稳定性

保障策略

√熔断:保护调用方,防止被调用的服务出现问题而影响到整个链路

√限流:保护被调用方,防止大流量把服务压垮

√超时控制:避免浪费资源在不可用节点上

37882bbd68d9ae043580176598df551.png

请求成功率

  • 负载均衡
  • 重试

长尾请求

backup request

930cbf74b18abaae4ebe63b127ac4ba.png

注册中间件

易用性:

√开箱即用:合理的默认参数选项、丰富的文档

√周边工具:生成代码工具、脚手架工具

简单易用的命令行工具:
生成服务代码脚手架
支持protobuf和thrift
内置功能丰富的选项
支持自定义的生成代码插件

扩展性

√Middleware

√option

√编解码层

√协议层

√网络传输层

√代码生成工具

观测性

  • Log、Metric、Tracing
  • 内置观测性服务

高能性

  • 场景

    √单机多机

    √单连接多连接

    √单/多client 单/多server

    √不同大小的请求包

    √不同请求类型:例如pingpong、streaming等


  • 目标

    √高吞吐

    √低延迟

  • 手段

    √连接池

    √多路复用

    √高性能编码解码协议

企业实践

  • 整体架构
  • 自研网络库
  • 扩展性设计
  • 性能优化
  • 合并部署