远程函数调用-RPC
基本介绍
-
什么是RPC
- RPC(Remote Procedure Call)远程过程调用协议,一种通过网络从远程计算机上请求服务,而不需要了解底层网络技术的协议。RPC它假定某些协议的存在,例如TPC/UDP等,为通信程序之间携带信息数据。在OSI网络七层模型中,RPC跨越了传输层和应用层,RPC使得开发,包括网络分布式多程序在内的应用程序更加容易。
-
需要解决的问题
- 函数映射
- 数据转换成字节流
- 网络传输
-
RPC的概念模型(分为这五个部分)
-
一些基本概念
-
IDL文件:描述接口,使得不同平台上运行的对象和用不同语言编写的程序可以相互通信
-
生成代码:IDL文件转换成语言对应的静态库
-
编解码:
- 编码:内存中的表示转换成字节序列
- 解码:反之
-
-
通信协议:规范数据子啊网络中的传输内容和数据
-
网络阐述:基于网络库走TCP/UDP传输
-
-
PRC的好处
- 单一职责,有利于分工协作和运维开发
- 可扩展性强,资源利用率高
- 故障隔离,服务的整体可靠性更高
-
RPC的坏处
- 服务端宕机问题
- 网络异常时如何保证可达
- 请求量突增导致服务无法及时处理
分层设计
例子:
编解码层
-
数据格式
-
语言特定的格式:编程语言自带的将内存对象编码为字节序列的支持
-
文本格式:JSON、XML、CSV
-
二进制编码:具备跨语言和高性能的优点,例如Thrift、BinaryProtocol、Protobuf等
- 实现原理:TLV编码(Tag+Length+Value)
-
-
编解码层 - 选型的要求
- 兼容性:支持自动增加新字段,且不影响老的服务
- 通用性:跨平台跨语言
- 性能:编码后的数据大小、编码耗费的时间
协议层
-
概念
- 特殊结束符:一个特殊字符作为每个协议单元结束的标示
- 变长协议:以定长加不定长部分组成,其中定长部分需要描述不定长的长度
-
协议构造
- LENGTH: 数据包大小,不包含自身
- HEADER MAGIC:标识版本信息,协议解析时候快速校验
- SEQUENCE NUMBER: 表示数据包的 seqID可用于多路复用,单连接内递增
- HEADER SIZE: 头部长度,从第14个字节开始计算一直到 PAYLOAD前
- PROTOCOL ID: 编解码方式,有 Binary 和Compact 两种
- TRANSFORM ID: 压缩方式,如 zlib 和 snappy
- INFO ID: 传递一些定制的 meta 信息
- PAYLOAD: 消息体
-
协议解析 - 框架中如何对协议进行解析
网络通信层 - Sockets API
-
过程
-
bind:绑定接口
-
listen:监听传进来的连接
-
accept:阻塞模式等待connect发送请求
网络通信层 - 网络库
-
提供易用的API
- 封装底层SocketAPI
- 连接管理和事件分发
-
功能
- 协议支持:tcp、udp和uds等
- 优雅退出异常处理等
-
性能
- 使用应用层的buffer减少copy
- 使用高性能定时器、对象池等提高性能
关键指标
稳定性
-
降级处理
- 熔断:保护调用方,防止被调用的服务出现问题而影响整个链路
- 限流:保护被调用方,防止大流量把服务压垮
- 超时控制:避免浪费资源在不可用节点上
-
请求成功率
- 负载均衡:均匀的调用各个节点
- 重试
-
长尾请求
- Backup Request(备份请求)
- Backup Request(备份请求)
左边是普通重试,右边是备份请求。可以看到,备份请求的速度更快
注册中间件
- RPC框架通过中间件来灵活的注入各种服务治理策略,保证服务的稳定性
易用性
-
开箱即用:合理的默认参数选项、丰富的文档
-
周边工具:简单易用的命令行工具
- 生成服务代码脚手架
- 支持 protobuf 和 thrift
- 内置功能丰富的选项
- 支持自定义的生成代码插件
扩展性
- 提供丰富的扩展点(例如核心的传输层和协议层)
- Middleware
- Option
- 编解码层
- 协议层
- 网络传输层
- 代码生成工具插件扩展
观测性
- Log、Metric、Tracing
- 内置观测性服务
高性能
-
场景
- 单机、多机
- 单连接、多连接
- 单/多client、单/多server
- 不同大小的请求包
- 不同请求类型:例如pingpong、streaming
-
目标
- 高吞吐
- 低延迟
-
手段
- 连接池
- 多路复用
- 高性能的编解码协议
- 高性能的网络库