让我们从一个简单的自动售货机的类比开始:
换句话说,
HTTP/2 对其可处理的并发请求量是有限制的。 每当一个请求处理完毕(从自动售货机中购买并补充物品),紧接着就可以接受另一个请求。
但是,HTTP/3 对累计请求的处理量有限制。 即使请求已完成,总计数仍会增加 1(自动售货机中少了 1 件商品)。您需要等待自动售货机重新装满(新的累计限制)。
和大多数比喻一样,这个类比也有缺陷,但能帮助我们理解这里的高层次差异。
那么,让我们从更底层的角度来看看实际发生了什么。
假设 HTTP/2 和 HTTP 3 的请求数都限制为 3 个:
对于 HTTP/2:
请求 1 接收(并发请求数 = 1)
请求 1 被客户端快速重置(并发请求数 = 0)
请求 2 进入(并发请求数 = 1)
请求 2 被客户端快速重置(并发请求数 = 0)
请求 3 进入(并发请求 = 1)
请求 3 被客户端快速重置(并发请求 = 0)、
由于被客户端“快速重置”,3 这个并发限制被 "绕过"。
对于 HTTP/3:
请求 1 接收(累计请求数 = 1)
请求 1 被重置(累计请求数 = 1)
请求 2 进入(累计请求数 = 2)
请求 2 被重置(累计请求数 = 2)
请求 3 进入(creqs = 3)
请求 3 重置(creqs = 3)
如果请求 4 进入,HTTP/3 将以 STREAM_LIMIT_ERROR 结束。
因此,虽然 HTTP/2 的限制从未改变,但并发请求量却始终低于该限制。 而对于 HTTP/3,累计限制会增加,但只有当总请求数达到之前的限制时才会增加,而不是像http2在重置数据流的时候!
这里有一点细微差别。理论上,HTTP/3 实现可以在每次请求重置后更新(内部)累计限制,但这种实现方式很奇怪(通常要等到至少处理完一个数据包后才会这样做)。
因此,在上面的例子中,如果请求 4 与请求 1-3 在同一个数据包中(如快速重置),HTTP/3 就会出错,因为它只有在处理完整个数据包后才会更新累计限制。 因此,攻击者可以在每个数据包中容纳更少的请求。
因此,从概念上讲,HTTP/3 可能存在漏洞,但前提是实现过程中出现了奇怪的情况(非常急切地更新限制)。 否则,攻击就会受到每次往返最大累计请求的限制(因为限制更新需要先到达客户端,然后才能继续!)。
因此,HTTP/3的每秒最大请求次数比 http2 低得多,从而减轻了攻击。 IETF 的一份新文件建议在 HTTP/2 中使用 HTTP/3 流限制
我们将拭目以待未来的实现如何处理这一问题。
最后的技术补充:在 HTTP/3 中,实际上是由 QUIC 来管理限制,从技术上讲,限制是针对 "流 "而非 "请求 "的。