HTTP/2 是无状态协议吗?

Posted

技术标签:

【中文标题】HTTP/2 是无状态协议吗?【英文标题】:Is HTTP/2 a stateless protocol? 【发布时间】:2016-07-10 18:14:48 【问题描述】:

据我了解,HTTP/2 带有一个名为 HPACK 的有状态标头压缩。它不会改变 HTTP 协议的无状态语义吗? Web 应用程序将HTTP/2 视为无状态协议是否安全?最后,HTTP/2 会兼容现有的负载均衡器吗?

【问题讨论】:

【参考方案1】:

HTTP/2 是无状态的。

原来的HTTP是一个无状态的协议,这意味着每个请求消息都可以被孤立地理解。这意味着每个请求都需要包含服务器为该请求提供服务所需的尽可能多的详细信息,而服务器不必存储来自先前请求的大量信息和元数据。

由于 HTTP/2 没有改变这种范式,它必须以相同的方式工作,无状态。

从official RFCs 也可以清楚地看到它。声明如下:

超文本传输​​协议 (HTTP) 是用于分布式、协作、超媒体信息系统的应用程序级协议。它是一个通用的无状态协议,可用于许多任务...

HTTP/2 的定义说:

本规范描述了超文本传输​​协议 (HTTP) 语义的优化表达,称为 HTTP 版本 2 (HTTP/2)...本规范是 HTTP/ 1.1 消息语法。 HTTP 的现有语义保持不变。

结论

HTTP/2 协议在设计上是无状态的,因为与原始 HTTP 相比,语义保持不变。


混乱可能来自哪里

HTTP/2 连接是在 TCP 连接之上运行的应用层协议(顺便说一句,没有什么能阻止您使用 HTTP over UDP 例如,这是可能的,但不使用 UDP,因为它不是“可靠的运输”)。不要将它与会话和传输层混合。 HTTP 协议在设计上是无状态的。 通过加密 SSL/TLS 连接的 HTTP 也不会改变此语句,因为 HTTPS 中的 S 关注的是传输,而不是协议本身。

HPACK,HTTP/2 的标头压缩,是一种专门为 HTTP/2 标头设计的压缩格式,在 separate internet draft 中指定。它不会改变 HTTP/2 本身,因此不会改变语义。

在RFC for HTTP/2 关于 HPACK 的部分中,他们声明:

标头压缩是有状态的。一个压缩上下文和一个 整个连接都使用解压上下文

这就是来自HPACK's RFC的原因:

2.2.编码和解码上下文

要解压头块,解码器只需要维护一个 动态表(参见第 2.3.2 节)作为解码上下文。没有其他 需要动态。

当用于双向通信时,例如在 HTTP 中, 端点维护的编码和解码动态表是 完全独立,即请求和响应动态表 是分开的。


HPACK 通过利用 HTTP等协议固有的冗余。的最终目标 这是为了减少发送 HTTP 所需的数据量 请求或响应。​​

HPACK 实现不能完全无状态,因为编码和解码表完全独立,必须由端点维护。

同时还有一些库,尝试解决HPACK问题,例如无状态事件驱动的HPACK编解码器CASHPACK:

HPACK 实现不能完全无状态,因为需要维护动态表。依靠 HTTP/2 将始终解码完整的 HPACK 序列这一假设,无状态是使用事件驱动的 API 实现的。

【讨论】:

我认为这个答案 (+1) 的 HPACK 部分的方向是错误的。显然,有状态。但状态是每个连接,而不是每个服务器或会话。每个连接状态并不是什么新鲜事。每个 TCP 连接都有。此外,状态是可消耗的。 @usr,很好的输入,关于每个连接的状态,我没有设法制定这个想法......如果你不介意,我会根据你的输入扩展我的答案。谢谢。 谢谢@usr @Farside!每个 TCP 连接的状态说明了一切 :) 我想最好在 HPACK 部分的开头提及它。 @Zamicol,您在没有确凿证据的情况下形成猜想。请先学习OSI 模型。 HTTP/2 连接是在 TCP 连接之上运行的应用层协议(顺便说一句,例如,没有什么能阻止您使用 HTTP over UDP,这是可能的,但不使用 UDP,因为它不是“可靠传输”) .不要将它与会话和传输层混合。 HTTP 协议在设计上是无状态的。例如,通过加密 SSL/TLS 连接的 HTTP 也不会更改此语句,因为 HTTPS 中的 S 关注的是传输,而不是协议本身。 @Farside 浏览有关 HTTP/2 协议的谷歌文档。他们清楚地强调了 HTTP/2 确实支持通过一个 TCP 连接的多个流这一事实。 developers.google.com/web/fundamentals/performance/http2【参考方案2】:

现代 HTTP,包括 HTTP/2,是一个有状态的协议。过去的 HTTP 是无状态的。

许多 HTTP/2 组件就是有状态的定义。

没有理智的人可以阅读 HTTP/2 RFC 并认为它是无状态的。错误的“HTTP 是无状态的”旧时教条是错误的并不代表 HTTP 的当前现实。

以下是有状态 HTTP/1 和 HTTP/2 组件的有限列表,并非详尽无遗:

Cookie,(被 RFC 命名为“HTTP 状态管理机制”) HTTPS,存储密钥因此状态 HTTP 身份验证需要状态 网络存储 HTTP 缓存是有状态的 流标识符的真正目的是状态 建立流标识符的标头块是有状态的。 引用流标识符的帧是有状态的 HTTP RFC 明确表示有状态的标头压缩是有状态的。 机会加密是有状态的。

Section 5.1 HTTP/2 RFC 是 HTTP/2 标准定义的有状态机制的一个很好的例子。

Web 应用程序将 HTTP/2 视为无状态协议是否安全?

HTTP/2 是一种有状态协议,但这并不意味着您的 HTTP/2 应用程序不能是无状态的。您可以通过仅使用 HTTP/2 功能的子集来选择不对无状态 HTTP/2 应用程序使用某些有状态功能。

Cookie 和其他一些状态机制,或者不太明显的状态机制,是 HTTP 后期添加的。 HTTP 1 is said to be stateless 尽管在实践中我们使用标准化的状态机制。 与 HTTP/1.0 不同,HTTP/2 在其标准中定义了有状态组件,因此是有状态的。特定的 HTTP/2 应用程序可以使用 HTTP/2 功能的子集来保持无状态。

如果尝试无状态地使用它们,需要状态的现有应用程序,甚至是 HTTP 1 应用程序都会中断。如果禁用 cookie,可能无法登录某些 HTTP/1.1 网站,从而破坏应用程序。假设特定的 HTTP 1 应用程序不使用状态可能并不安全。这对于 HTTP/2 没有什么不同。在 Netscape 在 1994 年发明 cookie 和 HTTPS 之前,http 可以被认为是无状态的。

和我说最后一次:

HTTP/2 是一个有状态的协议。

【讨论】:

Cookie 随每个请求一起发送,因此 HTTP 是无状态的。在 HTTP 之上运行的应用程序当然是有状态的。但我对 HTTP 本身很感兴趣,因此如果负载均衡器将后续请求发送到不同的机器,那会不会有任何问题。 HTTP/2 保留了无状态语义,因此路由后续请求的实例或机器无关紧要。换句话说,状态仅限于单个 TCP 连接,后续连接是独立的。 哈哈,Zamicol,你让我发笑“HTTP RFC 对 cookie 只字未提”……当然没有,难怪! =)您似乎在猜测这个主题,而不了解OSI模型。 HTTP/1.0 不是有状态的。 HTTP/2 也是如此,因为应用层仍然保持无状态......但是根据 RFC,它确实有一些有状态的组件,这也是正确的。 HTTP/2 连接是在 TCP 连接之上运行的应用层协议。不要将它与会话层和传输层混合。另请阅读上面写的@zeroone。投反对票。 @zeronone Cookie 是有状态的。 “随每个请求一起发送”是您的浏览器完成状态的方式。 Cookies 是在 HTTP/1.0 之后创建的。 HTTP/2 在 HTTP/1.0 的基础上引入了新的有状态机制。 @Farside “HTTP/2,因为应用层仍然是无状态的......但是根据 RFC 它确实有一些有状态的组件”我写了你正在解释的答案。你引用我作为你争论的来源。 ***.com/a/33681674/1923095 我认为混淆源于您查看协议的方向。通过至少类似于 OSI 模型的抽象分层,所有这些对客户端和服务器应用程序都是透明的。从 javascript 发出请求并在用 Python 编写的 Web 应用程序中处理该请求所需的代码不需要知道使用了哪个 HTTP 版本,以及有多少帧在不同的流中流动,谁知道有多少连接。你在那个浏览器中是对的,客户端需要维护一个关于连接的状态,但这是否使 HTTP/2 “有状态”取决于谁在问。

以上是关于HTTP/2 是无状态协议吗?的主要内容,如果未能解决你的问题,请参考以下文章

都说HTTP协议是无状态的,这里的「状态」到底指什么?

为什么说http协议是无状态的?

为什么说http协议是无状态协议

所有视图都应该是无状态组件吗?

Apache httpd服务——HTTP协议

cookie是啥?