quic的流控算法

前提

quic提供流和连接维度的流控算法。一端发送WINDOW_UPDATE帧通知对端增加流控窗口大小,当有数据但是无法发送时发送BLOCKED帧通知对端。
一个很好的例子是,一个具有限制内存的server,它需要一种机制控制每个发送给它的客户端的数据量,从而控制内存使用。

面向流的流控

stream的流控算法简单的说就是,各端需要告诉对方在连接上我想收多少数据。
在quic里,流控就是通知我想收多少字节数据。举个例子:如果我们告诉对端,在流N上可以发送200字节数据。他们已经发了150字节,在阻塞之前还可以发送50字节。随着我们从stream上消耗数据,我们可以发送WINDOW_UPDATE告诉对方可以发更多数据了。
这里写图片描述
这里双方规定了一个最大的接收窗口大小。上面的图片表明一个空的流的状态。
这里写图片描述
上面图片显示了已经消费了一些数据的流的状态。需要注意的是流控窗口的减少只根据highest received byte offset。
我们在每个流上跟踪highest received byte offset。随着新数据的到来我们更新这个值。当一个流停止时,对端必须通过FIN或者RST通知我们发送的最大数据量大小。
这里写图片描述
什么时候发送WINDOW_UPDATE?
bool send_update=(flow control receive offset - consumed bytes)<(max receive window/2)

连接流控

stream流控对防止接收端接收太多数据作用有限。一个客户端可以在一个连接上通过好多流(最大100)发送大量数据,虽然每个流都有流控。所以为了防止数据大量发送,我们需要连接维度的流量控制方法。
连接流控算法和流的流控算法相似,不过要对本连接下所有的流做统计计算。
举个例子
stream 1 接收了100字节数据,应用层消费了80字节
stream 2 接收了90字节,消费了50字节
stream 3 接收了110字节,消费了100字节
从连接的角度看一共接收了300字节数据,消费了230字节。
这里写图片描述

其他的考虑和实现细节

这里在流和连接流控算法的实现上有些边界情况需要考虑进去。在一定时间内,通信的双方必须统一流控的状态。如果有一方认为可以发送比对方可以接受多的数据,当超量数据到达时连接将会关闭。相反的一方认为可以发送的数据比对方可以接收的数据少,少于max receive window size /2 ,它就会卡住。永远也等不来WINDOW_UPDATE。

在传输中RST

当在数据传输过程中,比如在发送接收数据完之前,一方决定重置连接,会发生什么呢?当接收到RST,A将会关闭相应的stream,忽略到将来到来的数据。这样会引起流控算法错乱。当发送RST时,我们会告诉对端最后发送的数据量。这样我们的连接流量控制算法可以记录具体stream的数据大小。

RST to RST

B同样需要知道A多少数据在发送过程中重置了。A不能收到RST就关闭stream,它需要通知B多少数据发送了。有两种方式做最后的数据量通知
1.RST frame 带最后数据偏移
2.Data frame 带FIN bit

BLOCKED

一端当要发送数据时,被流控阻塞了,需要发送BLOCKED给对方。

默认值

// Minimum size of initial flow control window, for both stream and session.
const uint32_t kMinimumFlowControlSendWindow = 16 * 1024; // 16 KB
// Maximum flow control receive window limits for connection and stream.
const QuicByteCount kStreamReceiveWindowLimit = 16 * 1024 * 1024; // 16 MB
const QuicByteCount kSessionReceiveWindowLimit = 24 * 1024 * 1024; // 24 MB

自动配置max receive window

这个大小的选择很重要,小了经常阻塞,大了浪费。
直接说算法本身吧,也不复杂

算法

更新
available window < max window size / 2,
当available window = max window size - consume size
开始发送WINDOW_UPDATE,更新max window size
跟踪发送window update的时间间隔,
if ( since_last_update < RTT * trigger factor )
then max window size = MIN(max window size * increase factor, upper bound).
*trigger factor is 2
*increase factor is 2
window 更新如下
max_received window offset += (max window size - available window)

初始值

google服务器
CFCW: 49152 // 48 KB (connection)
SFCW: 32768 // 32 KB (stream)
upper bound 16MB

后记

发现翻译文档还是挺累人的。主要怕表达不清原来作者想表达的意思。不好的地方,欢迎提意见!

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值