当前位置: 首页 > Web前端 > HTML

GDPStreamingRPC设计

时间:2023-03-28 02:02:11 HTML

介绍:GDP(GoDevelopPlatform)是百度使用的一个RPC框架。具有完整的RPCClient和RPCServer能力,可用于开发API、Web、后端服务等各种应用。GDPStreamingRPC是基于GDPRPC能力开发的流式RPC框架。是在实现功能的基础上设计的一套面向流传输场景的传输框架,为流传输应用场景提供解决方案。百度首选的streamingRPC方案是baidu-rpc(开源项目是brpc)streaming,GDPstreaming是go版本的brpcstreaming,为Go开发者提供的streaming接口方案。全文4700字,预计阅读时间12分钟。1.Streaming介绍1.1需要解决的问题在一些数据传输场景中,client/server需要相互发送和接收大量的有序数据。这些数据非常大或不断产生,以至于它们不能在RPC的消息体中。例如:分布式系统中不同节点之间传输的副本或语音数据。一个订单导出接口有10万条记录。如果使用传统rpc,需要一次性接收到100000条记录才能进行下一步。如果我们使用流式rpc,那么我们可以接收一条记录并处理一条记录,直到传输完所有数据。虽然client/server可以将数据拆分,通过多个RPC传输,但是存在以下问题:如果并行发送数据,无法保证接收端有序接收数据,逻辑上拼接数据相当复杂。如果是串行发送,每次发送都要等待一个网络RTT+数据处理延迟,尤其是后者的延迟可能难以预测。RPC框架常见的通信方式有简单RPC、服务端流式RPC、客户端流式RPC、双向流式RPC。它们的主要特点是:简单RPC:传入请求并返回响应。服务端流式RPC:客户端发送一个请求,服务端可以连续返回多个响应。一个典型的例子是客户端向服务器发送一个股票代码,服务器不断地流式传输股票的实时数据返回给客户端。客户端流式RPC:客户端发送多个请求,服务器返回一个最终响应。一个典型的例子是接收和处理日志文件。双向流式RPC结合了前两种RPC的特点。两端可以发送多个请求并返回多个响应。图1.rpc的四种常见通信方式。流式交互模型是让大块数据以流水线的方式在客户端/服务器之间传输。实现的是双向流式RPC。1.2设计目标协议兼容brpc流状态,接收消息顺序与发送消息顺序一致。不同的流消息可以并行序列化。一只股票支持建立多条流。由于brpc的stream框架已经在公司内外广泛使用,GDP的实现首选是协议和功能向brpc对齐,目标是实现go版本的brpc。一个传输任务可能不是一个流就可以完成的,并行处理使其更加高效。所有框架都需要保证发送和接收消息的顺序,以及一致性和并行性。在很多场景下,发送和接收的数据可能会导入或转发给其他协议服务,所以我们考虑实现自定义的序列化和反序列化方法来降低使用成本。对于IO密集型场景,tcp的连接开销非常大,我们经常会遇到一个socket连接占满网口的情况。套接字可以设计为创建多个流。这种方案使得流管理逻辑更加复杂,但是可以节省连接开销。即建立流和销毁流的代价很小。2.框架设计2.1基本概念流Stream允许用户在client/service之间建立用户态连接,称为stream。Stream的传输数据是基于message的,输入端可以不断的往stream中写入消息,接收端会按照输入端写入的顺序接收消息,用户可以创建或者关闭一个stream通过流客户端。流的客户端和服务器端是对称结构。message消息体,流式数据以消息为基本单位。streamconnector流连接,数据交互的实体,维护一个stockconnection,一个streamconnection上可以同时存在多个streamc。event触发事件,包括握手成功/失败、数据处理/处理失败、处理超时、流关闭等handler回调方法,不同的事件对应回调的执行。request请求,包括流信息和消息体,因为流传输是对称的,所以所有的response返回也是reqeust。2.2框架功能从功能上来看,streamingrpc可以分为以下几个功能:callbackextension在server端使用handler回调处理数据,每次请求时处理request,创建server时注册handler.您还可以实现其他类型的自定义处理程序。handler注册后,通过事件触发对应回调handler的执行。流组件Streamingrpc使用户能够在客户端/服务之间建立用户模式连接,称为流。流的传输数据以消息为基本单位。这一层是流处理逻辑的实体,包括事件注册分发、流状态查询、触发回调、判断超时、协议封装等都在这一层完成。流组件的公共部分是资源组件,它负责流和连接的管理。它主要负责创建流时分配给流的空闲流连接,以及关闭时的资源释放。流基础模块的流组件的公共部分是资源组件,负责流和连接的管理。主要负责创建流时分配给流的空闲流连接,关闭时释放资源。一个tcpsocket可以对应多个流,一个连接一个读写通道,消息体的边界特性允许多个流共享一个socket,多个流并行处理数据,串行传输消息。流管理主要负责创建流时选择空闲的流连接,关闭时释放资源,记录错误连接,并在连接读写超时或发生错误时关闭该连接上对应的流。基础组件提供rpc的基本能力和依赖组件,包括服务发现、负载均衡、网络拨号等,并提供流下连接的维护工作。通用组件包括日志、配置、环境信息等基本功能,使流层应用可以与基础设施无缝集成。由于流的结构是对称的,流组件层和基础组件层的结构是服务端和客户端共享的。2.3实现细节流交互一个完整的交互包括三个阶段:握手、通信、关闭。Streamclient首先在本地创建一个stream,然后通过RPC与指定的服务建立一个stream。如果服务在收到请求后选择接受流,则响应返回给客户端后,流将建立成功。过程中的任何错误都将RPC标记为失败,这也意味着流创建失败。以linux下建立连接的过程来类比,客户端先创建一个socket(创建流),然后尝试与远端建立连接(通过RPC建立流)。远端接受后,建立连接(接受后服务创建成功)。建立后,客户端和服务端分别生成一个streamid。Stream建立后,进入通信状态,使用RPC(strm协议)双工交互,stream提供stream发送和接收消息方法,framework负责创建streams和TCPsockets,server握手后生成stream,streamid和endstreamid一致共享一个stockconnection,建立后执行accept(context.Context)error方法与clientStream交互。创建或接受流时,用户注册的处理程序处理从对端写入数据、关闭连接和空闲超时等。关闭操作由任何段发起,通过RPC通知对端销毁该流流式传输并关闭本地资源。当股票上没有流时,连接同时关闭。下图是客户端建立和客户端关闭的流状态图:图3流式通信模型2.4待解决的问题如何保证在一个tcp连接上建立多个流。client和server的结构是对称的,包括streammanager,streamconnect,stream结构对应的是streamdistribution(manager),saveconnection(connect),datainteraction(stream)等功能。在建立流的过程中,一个tcp连接由一个streamconnect保存,一个streamconnect保存多个流。当client/server建立一个stream时,manager会检查哪个connect处于不饱和状态,即可以存储stream。如果没有生成Aconnect,则将stream存入此connect并申请资源。connect确保每个流并行发送和接收数据,并使用读取通道异步发送。消息体保证了数据边界。每次发送一个消息体,都是互斥的。读股票使用异步线程阻塞读取,通过流的streamid将数据分发到对应的流中。大多数情况下流处理异常时,流在传输完成后被客户端主动关闭,或者服务器在空闲超时后关闭,但当出现错误或网络异常时,需要保证退出机制的双端流。当任何一端处理异常时,流都会进入异常状态,进入关闭流程,向对端发送关闭请求,对端收到请求后也会进入关闭流程。服务端异常发起的流交互流程如下图:图4.Streamingframework流异常处理流处理网络异常。比如当一个stream发现读写失败时,会进入shutdown流程,同时通知streammanager。与此流共享连接的所有流都将由管理器通知并关闭。由于流的对称结构,对端感知到网络异常时会进入同一个进程。异常处理保证错误流不承担后续工作,保证异常连接的退出。图5流式网络异常处理当对流进行读写失败时,本地流会感知到,因此两端流交互失败,自动关闭流,释放资源,并通知流管理器同时这个stream共享一个stockstream被streammanager通知关闭,资源也被释放。如何注册回调框架在事件触发时执行相应的回调,服务端自定义回调方法定义为框架中的handler接口,实现相应的接口实现回调。这样做的好处是避免了注册多个回调方法。冗余代码和可扩展性问题。基本处理程序是服务器处理客户端请求的回调方法。定义类似:基本的handler定义了typeHandlerinterface{Handle(context.Context,Stream,Request)error}服务器的server结构体提供了注册方法来注册handler:Handler是基本的回调方法,必须实现,其他类型的实现可选,包括:握手响应、握手成功、握手失败、超时回调、错误处理、关闭流等。不同的回调方法对应不同的interface{},用户只需要实现相应的即可interface{}来完成自定义回调。===3。访问案例我们选择了一个语言访问模块。原有架构采用brpc实现语音上下行传输和处理。替换,如图:图6.用GDP流替换brpc流。通过性能测试,对比新旧模块的差异。其中成功率和延迟基本一致,实现平滑升级。GDP的StramingRPC性能指标方面:单实例小包(1k以内)的转发达到了2.5w/s,达到了同等环境下brpc的水平,可以满足高性能要求。与brpc相比,相同吞吐率下cpu提升了20%左右。4.总结Go具有动态语言所没有的并发和性能优势,占用系统线程少。与C++相比,Go语法简单,对公共协议的支持良好,使其能够在性能的基础上支持高效的业务开发、调试和运维。GDPStreaming提供Go版本的brpcstreaming,基于S.O.L.I.D.软件设计原则,使框架具有高度的可扩展性,为百度Gopher的流媒体应用提供了实用的解决方案。推荐阅读:百度APP视频播放解码优化百度爱饭饭实时CDP构建实践当技术重构遇上DDD,如何实现业务与技术的双赢?接口文档自动更改?百度程序员开发效率MAX技术秘诀!百度搜索平台低代码探索与实践------百度极客说百度官方技术公众号上线!技术干货·行业资讯·在线沙龙·行业大会招聘信息·介绍资料·技术书籍·百度外设