为什么说“HTTP是一种无状态协议”?

215

HTTP有HTTP Cookies。Cookies允许服务器跟踪用户状态、连接数、上次连接时间等。

HTTP有持久连接(Keep-Alive),可以通过同一TCP连接发送多个请求。


3
我不认为“无状态”适用于授权 - 特别是代理授权。在协商期间,它似乎是有状态的。对于NTLM身份验证,客户端需要记住代理身份验证的类型,服务器需要保持有状态,因为NTLM消息类型有一定的顺序。因此,我不确定我是否理解了答案。 - Lindsay Morsillo
1
我现在应该添加HTTP/1.1吗?因为我认为HTTP/2有状态。 - Jose Nobile
9
HTTP/2是有状态的。HTTP 1是无状态的。针对HTTP 1的后续添加,如cookies,增加了状态信息。但这些添加不属于“核心” HTTP 1规范。这就是为什么说HTTP 1是一种无状态协议,尽管在实践中并非如此。另一方面,HTTP/2设计时就包含了有状态组件。没有需要添加的内容来满足被标记为“有状态”的要求。 - Zamicol
还相关的内容:https://dev59.com/bmgu5IYBdhLWcg3wzKAc https://dev59.com/AVoV5IYBdhLWcg3wgu5H - Andrew
10个回答

159
尽管可以在同一HTTP连接上发送多个请求,但服务器不会将它们到达相同的套接字视为具有特殊含义。这完全是出于性能方面的考虑,旨在最小化重新建立每个请求连接所需的时间/带宽。

就HTTP而言,它们仍然是单独的请求,并且必须包含足够的信息来满足请求。这就是“无状态”的本质。如果没有服务器知道的一些共享信息,这些请求将不会与彼此关联,在大多数情况下,这是一个cookie中的会话ID。

1
当服务器记住会话(服务器端)并根据其自定义用户体验时会发生什么? - NurShomik
3
请参考 https://dev59.com/TnA75IYBdhLWcg3wAUF9#3521393 了解会话(sessions)通常的工作方式。 - cHao
16
HTTP并不是建立在TCP之上的,TCP的状态也不是HTTP的状态。这两者是完全独立的协议,处于堆栈中不同的层。如果你愿意的话,甚至可以通过命名管道或文件传输来提供HTTP服务,只要你能够让足够多的受虐狂同意,它就会正常工作,因为HTTP本身并不依赖于传输协议。在那个层面上,一切都只是请求和响应。这使得HTTP本身是无状态的,不管低层或高层协议使用/维护/需要的状态是什么。 - cHao
@cHao 好的,我承认。如果我们将无状态定义为“不一定需要状态才能运行”(请参见dimo414在下面列出的HTTP中状态选项的答案,引用自维基百科),并且如果我们严格按照每个协议本身而不是基于其下面的层来看待每个协议,那么我同意HTTP是“无状态”的说法。 - Andrew

110

来自维基百科:

HTTP是一种无状态协议。无状态协议不要求服务器在多个请求期间保留有关每个用户信息或状态。

但某些Web应用程序可能需要跟踪用户从页面到页面的进度,例如当Web服务器需要为用户定制Web页面内容时。这些情况的解决方案包括:

  • 使用HTTP cookies。
  • 服务器端会话,
  • 隐藏变量(当当前页面包含表单时),以及
  • 使用URI编码参数进行URL重写,例如,/index.php?session_id=some_unique_session_code。

使该协议无状态的原因在于服务器不被要求跨多个请求跟踪状态,并非不能这样做。这简化了客户端和服务器之间的合同,在许多情况下(例如通过CDN提供静态数据)最小化了需要传输的数据量。如果服务器必须维护客户访问的状态,则发出和响应请求的结构将更加复杂。因此,该模型的简单性是其最大特点之一。


似乎他们本应该不那么正式地宣布它是一个无状态协议,而是使用一些词语来说明它可以灵活地在无状态和有状态之间切换。 - dtc

21

HTTP 被称为一种“无状态协议”,因为每个请求都是独立执行的,没有关于之前执行的请求的任何信息。这意味着一旦事务结束,浏览器和服务器之间的连接也会断开。

协议 无状态 的原因在于,在它最初的设计中,HTTP 是一个相对简单的 文件传输协议

  1. 发送URL请求获取文件;
  2. 收到响应后获取文件;
  3. 断开连接。

甚至来自同一客户端的多个连接之间也没有维护关系。这简化了客户端和服务器之间的协议,并在许多情况下最小化了需要传输的数据量。


1
这并不是真的,特别是在HTTP/2中,请求取决于其他请求。Cookies、HTTPS、HTTP身份验证、Web存储、HTTP缓存、HTTP流标识符、HTTP/2头块、HTTP/2帧、头部压缩和机会主义加密都是有状态的。 - Zamicol

20
因为无状态协议不需要服务器在多次请求的过程中保留与每个通信方的会话信息或状态。
HTTP是一种无状态协议,这意味着浏览器和服务器之间的连接在交易结束后断开。

3
HTTP可以使用cookie将信息保存在服务器上。启用keep-alive的HTTP不会在每次请求时关闭连接。 - Jose Nobile
4
请查看这篇文章:- http://www.ecst.csuchico.edu/~amk/foo/advjava/notes/servlets/Cookies.html - Rahul Tripathi
21
将信息保存在服务器上并不意味着连接始终处于活动状态。 - srijan
1
@srijan 嗯,不是这样的。那又怎样呢?没有人声称过相反的事情。 - Mark Amery

10

现代 HTTP 是有状态的。古老的 HTTP 是无状态的。

在 Netscape 在 1994 年发明了 cookie 和 HTTPS 之前,HTTP 可以被认为是无状态的。随着时间的推移,出于各种原因,包括性能和安全性,许多有状态的组件被正式添加。但这些有状态的补充只是额外的内容,所以从俗语上说,HTTP 仍然是无状态的,因为最初的核心明确要求它是无状态的。

虽然 HTTP/1 最初追求无状态,但许多 HTTP/2 组件则完全符合有状态的定义。HTTP/2 放弃了无状态的目标。有状态的组件不再是“补充”,而是在 HTTP/2 标准的核心中定义。在 HTTP/2 规范(RFC 7540) 中有 125 处提到了"state",而没有提到"stateless"。

以下是有状态的 HTTP/1 和 HTTP/2 组件的简要列表(不详尽):

  • HTTP/2 RFC明确表示“头部压缩是有状态的。
  • HTTP/2流标识符的目的是状态。(一个完整的章节专门讲述了各种状态。)
  • 建立流标识符的HTTP/2 头部是有状态的。(RFC中的一个例子:“HEADERS帧可以在“空闲”,“保留(本地)”,“打开”或“半关闭(远程)”状态上发送。”)
  • HTTP/2 帧是有状态的。RFC中的一个例子:“特定类型的帧传输可以改变连接的状态。”
  • Cookie是有状态的,规范标题为{{link5:“HTTP 状态管理机制”(RFC 6265)}}。
  • 存储密钥的HTTPS是有状态的。还要注意,HTTPS所需的CA系统的整个目的就是进行状态管理。
  • HTTP身份验证需要状态。(这是如此明显以至于被忽视。)
  • Web存储是有状态的。(这是如此明显以至于被忽视。)
  • HTTP缓存是有状态的。按定义,缓存是有状态的。(这是如此明显以至于被忽视。)
  • 机会性加密是有状态的。
  • URL参数是有状态的。这是在1994年第一个正式的有状态机制(Cookie)出现之前应用程序实现状态的方式。即使不使用任何其他有状态的HTTP功能,如果将URL参数用于有状态,那么该HTTP应用程序就是有状态的。

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

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

HTTP/2是一个有状态的协议,但您的HTTP/2应用程序可以忽略有状态的特性以保持无状态。

现有的需要状态的HTTP/1和HTTP/2应用程序如果尝试以无状态方式使用它们,将会出现错误。例如,如果禁用了cookie,登录某些HTTP/1.1网站可能变得不可能,从而破坏应用程序。因此,不能安全地假设特定的HTTP/1或HTTP/2应用程序是无状态的。

总结:

状态机制是对最初无状态标准的HTTP的后续添加。虽然HTTP/1在俗语中被说成是无状态的,但实际上我们使用标准化的有状态机制,如Cookies和缓存。与HTTP/1不同,HTTP/2从一开始就在其标准中定义了有状态组件。特定的HTTP/2应用程序可以使用HTTP/2功能的子集来保持无状态性,但协议本身预计状态是常态,而非例外。错误的"HTTP是无状态的"是过时的教条,远离现代的有状态HTTP现实和理论,实际上你在日常生活中以有状态方式使用HTTP。

1
HTTPS是HTTP over TLS,与HTTP无关。密钥“存储”发生在另一个协议层。参见https://en.wikipedia.org/wiki/HTTPS#Difference_from_HTTP。 - Sebi2020
1
这是一个合理的答案。但为什么没有人支持它呢? - choxsword
如果HTTP是有状态的协议,那么客户端负载均衡是如何工作的呢?客户端随机地将请求发送到任何一台终端服务器,一切都可以正常运行。 - ns15
HTTP/2是无状态的。在这里讨论并解决:https://dev59.com/AVoV5IYBdhLWcg3wgu5H#36178703 - Monis
@Monis 显然,HTTP/2是有状态的,但在你看来,有状态的HTTP会是什么样子?HTTP要成为有状态的,需要满足哪些要求? - Zamicol

5

如果HTTP协议被设置为有状态协议,浏览器窗口将使用单个连接与Web服务器通信,以处理发给Web应用程序的多个请求。这使得浏览器窗口有机会在浏览器窗口和Web服务器之间建立长时间连接,并将它们保持在空闲状态长时间。尽管客户端中的大部分连接是空闲的,但这可能导致达到Web服务器的最大连接数。


1
HTTP已经具备了保持连接的功能,这意味着服务器不会关闭连接,客户端可以在同一连接上发出多个请求。 - Jose Nobile

5

HTTP是无状态的。而TCP是有状态的。 没有所谓的HTTP连接,只有HTTP请求HTTP响应。我们不需要维护任何东西来使另一个HTTP请求。 一个名为"keep-alive"的连接头意味着后续的HTTP请求和响应将重用TCP,而不是一直断开和重新建立TCP连接。


1
HTTP/2是有状态的,并且具有称为流的HTTP连接。 https://tools.ietf.org/html/rfc7540#section-5.1 - Zamicol

3

HTTP是一种无连接的协议,这导致了HTTP是一种无状态的协议。服务器和客户端仅在当前请求期间彼此知晓。之后,它们都会忘记对方。由于协议的这种性质,无论是客户端还是浏览器都无法在不同的网页请求之间保留信息。


2

什么是无状态?

一旦请求被发出并且响应被返回给客户端,连接将会中断或终止。服务器将完全忘记请求者。

为什么要无状态?

Web选择了无状态协议。这是一个非常聪明的选择,因为Web最初的目标是允许使用非常基本的服务器硬件向大量用户提供文档(网页)。

维护一个长时间运行的连接将会消耗巨大的资源。

如果Web选择有状态协议,则服务器的负载将增加以维护访问者的连接。


2
我认为某些人为“无状态”概念选择了一个非常不幸的名称,这正是整个误解的根源。它不涉及存储任何资源,而是关于客户端和服务器之间的关系。
客户端: 我在我的一侧保留所有资源并向您发送需要处理的所有重要项的“列表”。 做你的工作。
服务器: 好的...让我负责筛选重要内容以便给您适当的响应。
这意味着服务器是客户端的“从属”,每次请求后都必须忘记自己的“主人”。 实际上,“无状态”仅指服务器的状态。
参考链接:https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接