深入浅出 RPC 框架|青训营笔记

深入浅出 RPC 框架|青训营笔记

这是我参与「第三届青训营 -后端场」笔记创作活动的的第十二篇笔记。

本章目录:

image-20220612133314270

基本概念

本地函数调用

image-20220612133602775

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

image-20220612152955051

因为不是一个栈,因此每个函数需要搞一个ID,把对应的函数的ID传过去。
把对应的数据转成字节流传过去。

RPC 概念模型

image-20220612153150880

RPC整体流程如图。。。

一次RPC的完整过程

image-20220612154024242

比本地函数调用,远程调用的话我们不知道对方有哪些方法,以及参数长什么样,所以需要有一种方式来描述或者声明我有哪些方法,方法的参数都是什么样子的,这样的话大家就能接照这个来调用,这个描校件就是IDL文件。

刚才我们提到服务双方是通过约定的规范进行远程调用,双方都依赖同一份IDL文件,需要通过工具来生成对应的生成文件,具体调用的时候用户代码需要依赖生成代码,所以可以把用户代码和生成代码看做一个整体。

编码只是解决了跨语言的数据交换格式,但是如何通讯呢?需要制定通讯协议,以及数据如何传输?我的网络模型如何呢?那就是这里的transfer要做的事情。

RPC的好处

image-20220612154736779

RPC带来的问题

image-20220612155530161

小结

image-20220612155646086

分层设计

以Apache Thrifit为例

image-20220612155854204

编解码层

image-20220612155914440

生成代码

image-20220612160235138

数据格式

image-20220612160319090
image-20220612160415861

二进制编码

image-20220612160826188

TLV编码结构简单清晰,并且扩展性较好,但是由于增加了Type和Length两个冗余信息,有额外的内存开销,特别是在大部分字段都是基本类型的情况下有不小的空间浪费。

选型

image-20220612161110807

协议层

image-20220612161323704

概念

image-20220612161404720

协议构造

image-20220612161537743

协议解析

image-20220612172657899

先读取MAGIC,知道你是啥类型的协议,然后读取编解码方式,把Payload有效载荷解析出来。

网络通信层

image-20220612172842008

Socktes API(重要)

image-20220612173100525

这里和之前讲得差不多,客户端必须知道服务器的IP和端口号。

服务器端:socket函数创建一个套接字,bind将一个套接字绑定在一个地址上。listen监听进来的链接。
backlog:指挂起的连接队列的长度,当客户端连接的时候,服务器可能正在处理其他逻辑而未调用accept接受链接,此时会导致这个连接被挂起,内核维护挂起的链接队列,backlog则指定这个队列的长度。
accept函数从队列中取出连接请求并接受它,然后这个连接就从挂起队列中移除。如果队列未满,客户端调用connect马上成功,如果满了可能会阻塞等待队列未满(实际上在Linux中测试并不是这样的结果,这个后来再专门研究)。Linux的backlog默认是128,通常情况下,我们也指定为128即可。

connect 客户端向服务器发起连接,accept接受一个连接请求,如果没有连接则会一直阻塞到有连接进来。得到客户端的fd后,就可以调用read,write函数和客户端通讯,读写方式和其他I/O类似。
read从fd读数据,socket默认是阻塞模式的,如果对方没有写数据,read会一直阻塞,write同理。

socket 关闭套接字,当另一端socket关闭后,这一端读写的情况:
尝试去读会得到一个EOF(End Of File),并返回0.
尝试去写会出发一个SIGPIPE信号,并返回-1和errno=EPIPE,SIGPIPE的默认行为是终止程序,所以我们通常应该忽略这个信号,避免程序终止。
如果这一端不去读写,我们可能没有办法知道对端的socket关闭了。

网络库

image-20220612192648829

小结

image-20220612192819159

关键指标

稳定性

保障策略

image-20220612192925659

image-20220612193139978

某种程度上讲:熔断、限流、超时都是降级的措施

请求成功率

image-20220612193401357

长尾请求

image-20220612193639838

左侧是正常的请求:会花费t1+t2的时间。右侧是我们使用的p99时间内,我们认为t3时间内99%的请求都应当被返回了,然后当超过p99这个时间认为出了问题直接再发一次请求,所以t4为总花费时间。

长尾请求就是指的最后那1%的请求,这些请求明显高于平均时间。

image-20220612194243444

注册中间件

image-20220612194519113

Kitex Client和Server的创建接口均采用Option模式,提供了极大的灵活性,很方便就能注入这些稳定性策略。

易用性

image-20220612194734985

Kitex使用Suite来打包自定义的功能,提供一键配置基础依赖的体验。

扩展性

image-20220612194941369

主要通过中间件middleware来实现。

观测性

image-20220612195132350

Log:日志。Metric:监控面板,可以看服务的kps(网速)是多少,延迟是多少。Tracing:链式跟踪,排查问题的时候看层层请求,看哪个地方出了问题。

高性能

image-20220612195512589

高性能往往分成两个维度:高吞吐(单位时间内尽可能处理多的请求)和低延迟(一次请求发过去,返回时间尽可能短,更重要一点)。

小结

image-20220612195818447

企业实践

整体架构

Kitex

image-20220612200740572

自研网络库

背景

image-20220612200952888

Netpoll

image-20220612201150175

扩展性设计

image-20220612201347434

性能优化

网络库优化

image-20220612201509803

编解码优化

image-20220612201618158

image-20220612201814381

合并部署

image-20220612201936179

image-20220612202140053

小结

image-20220612202232884

课程总结

image-20220612202308712

posted @ 2022-06-12 20:27  杀戒之声  阅读(104)  评论(0编辑  收藏  举报