当前位置: 首页 > 后端技术 > Java

Dubbo3的三重流控反压原理解析

时间:2023-04-01 16:47:40 Java

作者:顾鑫Triple是Dubbo3提出的一个基于HTTP2的开放协议,旨在解决Dubbo2的私有协议带来的互操作性问题。Triple基于HTTP/2定制了自己的流量控制,支持通过特定的异常通知客户端业务层服务器高负载,保护服务器不被大流量压垮,提高系统的高可用。1、流控和背压现状客户端和服务端在接收数据的时候都有一个缓冲区用来暂存数据,但是缓冲区的大小是有限的,所以可能会出现缓冲区溢出的情况。控制和保护数据溢出和丢失的风险。1.HTTP/1流量控制在HTTP/1.1中,流量控制依赖于底层的TCP协议。当客户端和服务器建立连接时,系统默认设置用于建立缓冲区。数据通信时,会告诉对方自己接收窗口的大小,也就是缓冲区中剩余的可用空间。如果接收窗口大小为零,则接收方缓冲区已满,发送方将不再发送数据,直到客户端清除其内部缓冲区,然后请求恢复数据传输。2.HTTP/2流控HTTP/2采用了多路复用机制,一个TCP连接可以有多个HTTP/2连接,所以在HTTP/2中,有更细化的流控机制,可以让服务端实现自己的Dataflow和连接级流量控制。当服务端和客户端第一次见面连接时,会通过发送HTTP/2SettingsFrame来设置初始流控窗口大小,用于Stream级别的流控,默认为65535字节。设置流控窗口后,客户端每次发送数据都会缩小流控窗口的大小,服务端收到数据后会发送一个窗口更新包(WINDOW_UPDATE帧)通知客户端更新窗口.客户端收到窗口更新包后,会增加相应值的流量控制窗口,从而达到动态控制的目的。2、三重流控反压Netty基于HTTP/2实现了基础流控。当服务器负载过高,客户端发送窗口为0时,新的请求发送不出去,会缓存到客户端等待发送请求队列中,如果缓存的数据过大,会导致内存溢出在客户端并影响业务程序。Triple基于Netty实现HTTP/2协议,并通过HTTP/2FlowController接口进行统一封装。实现分为入站和出站两个维度。Triple对入站流量使用Netty默认的流控实现,对出站流量实现自己的流控。基于服务器负载,将服务器流量压力透传到客户端业务层,实现客户端业务反压,暂停业务继续发送请求,保护服务器不被大流量压垮。1、连接初始化Triple在第一次建立连接时,通过TripleHttpProtocol初始化HTTP/2配置。默认流控窗口DEFAULT_WINDOW_INIT_SIZE=MIB_8,并在服务端和客户端添加自己的出站流控接口。2.Inbound流量控制Inbound流量会通过DefaultHttpLocalFlowController的consumeBytes方法进行更新和发送。1)传入HTTP流量,入口处更新数据大小2)找到对应连接实现数据消费3)更新流控窗口4)发送流控更新包(window_update)3、Outbound流控Outbound通过Triple的实现TriHttpRemoteFlowController自带流量控制,将服务器的压力反馈给业务层,保护服务器不被大流量压垮。1)发送数据时判断是否有窗口2)窗口为0时抛出特定异常3)反馈客户端流控异常4.总结传递给客户端上层业务,防止客户端业务持续发送数据,有效保护服务器不被大流量压垮和客户端内存溢出问题。三、未来展望目前,Triple已经基本实现了流控反压能力。未来我们会深度链接业务,根据业务负载自适应调整背压流控。一是调整流量控制窗口报文在入站上向服务器发送的时机,业务处理完成后,二是将客户端业务层与出站流量关联起来,动态调整客户端发送速率。这样就实现了一种基于服务器服务负载的动态抗压流控机制。欢迎来到DubboStarhttps://github.com/apache/dubbo。