RPC框架分层
基本概念
远程函数调用 RPC
相比本地函数调用,RPC需要解决的问题: 1.函数映射:两个函数在不同的进程 2.数据转换成字节流:传参不能通过内存 3.网络传输
个人思考:RPC的本质是通过网络协议等实现不同计算机之间的远程通信调用,就像调用本地函数一样
一次RPC的完整过程
IDL文件
通过约定的规范描述接口
个人思考:IDL语言仅仅用于定义接口,不提供具体实现,方便规范,与其他语言不同
生成代码
通过编译器工具把IDL文件转换成语言对应的静态库
编码
从内存中表示到字节序列的转换称为编码,反之为解码,也常做序列化和反序列化
通信协议
现范了数据在网络中的传输内容和格式。除必须的请求/响应数外,通常还会包含额外的元数据
网络传输
通常基于成熟的网络库走TCP/UDP传输
RPC的好处
1.单一职责,有利于分工协作和运维开发 2.可扩展性强,资源使用率更优 3.故障隔离,服务的整体可靠性更高
不同服务有自己的分工,非常明确
针对不同服务分配资源
RPC的弊端
1.在调用过程中发生网络异常,如何保证消息的可达性?
个人思考:可以通过利用熔断、超时、重试等机制,避免网络异常的影响
2.请求量突增导致服务无法及时处理,有哪些应对措施?
个人思考:可以利用限流、负载均衡、优化性能等。
分层设计
编解码层
语言特定的格式
许多编程语言都内建了将内存对象编码为字节序列的支持,例如Java有java.io.Serializable 方便,代码量少,但是与编程语言绑定,兼容性差 文本格式 JSON、XML、CSV等文本格式,具有人类可读性 描述不严谨,无法区分整数浮点数、精度问题,没有模型约束,不方便调试 二进制编码 具备跨语言和高性能等优点,常见有Thrift的BinaryProtocol,Protobuf等
个人思考:二进制编码在一定范围内是合理的,只是在数据量小的情况下,数据包中大半为附带的其他信息
选型
兼容性 支持自动增加新的字段,而不影响老的服务,这将提高系统的灵活度 通用性 支持跨平台、跨语言 性能 从空间和时间两个维度来考虑,也就是编码后数据大小和编码耗费时长
协议层
概念
特殊结束符:以\n或者其他符号结尾 边长协议:length+message body
协议构造
LENGTH:数据包大小,不包含自身 HEADER MAGIC:标识版本信息,协议解析时候快速校验 SEQUENCE NUMBER:表示数据包的seqlD,可用于多路复用,单连接内递增
个人思考:多路复用是在一条连接上同时传输多个数据流,例如在传输层中,使用不同的端口号来区分和识别不同的数据流,并为每个数据包添加目标端口号,据此将数据包分发给相应的应用程序或服务
HEADER SIZE:头部长度,从第14个字节开始计算一直到PAYLOAD前 PROTOCOL ID:编解码方式,有Binary和Compact两种 TRANSFORM ID:压缩方式,如zlib和snappy INFO ID:传递一些定制的meta信息 PAYLOAD:消息体
协议解析
Peek ------------ Peek --------- Decode MagicNumber PayloadCodec Payload
网络通信层-网络库
提供易用API 封装底层Socket API 连接管理和事件分发 功能 协议支持:tcp、udp和uds等 优雅退出、异常处理等 性能 应用层buffer 减少 copy 高性能定时器、对象池等
关键指标
稳定性 易用性 扩展性 观测性 高性能
稳定性
熔断:保护调用方,防止被调用的服务出现问题而影响到整个链路(防止一个问题超时导致整个链路被影响)
个人理解:熔断可以监控各个异常服务,及时停止对其访问防止拖累整个系统
限流:保护被调用方,防止大流量把服务压垮 超时控制:避免浪费资源在不可用节点上
请求成功率
负载均衡-重试 重试:调用失败可以重新调用
长尾请求
由于各种原因存在,可以使用备份请求,减少延时