赞
踩
QUIC 和HTTP2一样,同时提供流级和链接级别的流量控制。接收端发送WINDOW_UPDATE帧通知对端接收窗口的大小增长,比如说能接收更多的数据,发送端也可以发送BLOCKED帧表明数据发送受制于接收端的窗口,无法发送数据。因此,QUIC是通过WINDOW_UPDATE和BLOCKED帧来实现流量控制。
一个典型的应用场景就是接收服务器端内存有限,他必须通过一种流量控制协议来限制多个客户端同时发送大量数据,否则内存大量申请爆满而死。
某一端可以接收的数据的buffer最大长度。
流量控制的接收窗口最右端偏移和当前接收数据最大偏移的差值
流级流量控制就是QUIC某一条流接收端告诉另外一端可以接受多少这种流多少数据。针对的是特定流号的流,而不是整个链接。 本质来说,就是接收端告诉对端最多能发到偏移到多少的流数据。例如,某一条流N告诉接收到可以到偏移200字节的位置。但是发送端已经发送150字节,那么发送端最多就只能发送50字节。等发送端把150字节处理完毕,又重新发送WINDOW_UPDATE到400字节的偏移。发送收到后,已经发送150,那么就再能发送250字节。
图A 接收端窗口初始状态
如图,接收端在初始化的时候,依据资源的有限(比如说内存)设定接收窗口的最大值,比如说64K。随着数据的接收,如果处理速度过慢,或者网络丢包,这个接收窗口可能逐渐填满,直到为零。
图B 带缓存和消耗数据的流窗口图
这个图展现了接收端已经接收了一些数据的情形。我们处理消耗了绿色部分的数据 ,缓存了橙色部分的数据(百色缝隙可能是丢包导致数据没有到达)。
每当新的数据到来的时候,接收端一直更新记录接收数据的最大偏移,来更新流量接收窗口。同时取出数据的时候,也更新记录以及消耗数据的长度,如果消耗数据的长度大于了最大接收窗口的一半,如图C的时候,
bool send_update = (flow control receive offset - consumed bytes) < (max receive window / 2);
最大接收窗口向右移动当前消耗的字节,移动后的效果如图D.同时给对端发送更新帧,内容就是当前最大接收偏移的值offset。
图C 窗口状态达到了触发窗口更新条件
图D 窗口移动后的状态
流级别的流量控制虽然能起到控制流量的效果,但是不够充分,数据发送端可以在同一个链接创建多条流来发送数据,每条流都达到最大值的攻击方法。因此还需要链接级别的流量控制。
链接级别流量控制和流级别的一样,但是消耗字节,最大接收偏移都是穿插所有流,是所有流的最大值或者总和。举三条流的例子:
流名 | 接收字节 | 消耗字节 | |
---|---|---|---|
1 | 100 | 80 | |
2 | 90 | 50 | |
3 | 110 | 100 | |
链接 | 300 | 230 |
如图E 链接的接收字节取总和,消耗字节取总和,最大接收偏移取最大值
图E 流的流量控制计算
链接基本流量控制,确实就是导致慢流饥饿。虽然慢流不会导致链接中断,但是慢流很难得到流量控制的优先级。
接收窗口默认最小值16KB:
// Minimum size of initial flow control window, for both stream and session.
constuint32_tkMinimumFlowControlSendWindow= 16* 1024; // 16 KB
最大值:
// Maximum flow control receive window limits for connection and stream.
constQuicByteCountkStreamReceiveWindowLimit= 16* 1024* 1024; // 16 MB
constQuicByteCountkSessionReceiveWindowLimit= 24* 1024* 1024; // 24 MB
16 kb的最小值是为了0RTT数据交互,也是握手的同时也进行数据交互。同时两端也可以在握手期间通过CHELO和SHLO的kSFCW字段和kCFCW标签来交互对方最大接收窗口值。
如下例子
Chromium currently sets:
CFCW:15728640 // 15 MB
SFCW:6291456 // 6 MB
Google’s servers currently set:
CFCW:1572864 // 1.5 MB
SFCW:1048576 // 1 MB
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。