Web应用中的状态(会话状态、应用状态、有状态协议、无状态协议、REST无状态约束)

结论先行

1 组件交互层次的“状态”

  • 会话状态(session state):组件在先后多次交互之间维护的上下文(context)信息。
  • 服务端是无状态的:服务端组件不保存会话状态。
  • 服务端是有状态的:服务端组件保存了会话状态。
  • HTTP是无状态协议:协议要求【服务端组件】只依赖当前请求中提供的信息来理解请求,而【不依赖于】从其他请求中保存的【会话状态】来理解请求。当服务端组件做到了这一点时,会产生如下效果:每个请求都是独立的,请求之间没有上下文关系。为了能让服务端组件做到这一点,需要客户端组件的配合,即客户端组件必须在请求中提供服务端组件理解该请求所需的全部信息。
  • REST的无状态约束:要求组件【交互】时,客户端组件【不能利用】任何【服务端组件保存的会话状态】。客户端组件为了满足此要求,必须把对方理解本次交互所需的全部信息都在本次交互中一起提供给对方。因为需要提供全部信息,客户端组件就必须保存所有会话状态。

2 应用软件使用层次的“状态”

  • 应用状态:当没有未完成的请求时,应用软件所达到的一种稳定的状态。
  • REST(表述性状态移交)的含义:通过移交表述,实现【应用状态】的迁移。Web应用是一个由网页组成的网络(即一个虚拟状态机),用户通过选择链接在应用中前进(即应用状态迁移),导致系统将下一个页面(即下一个应用状态)的相关表述移交给用户,并为用户呈现出来,以便他们使用。

3 应用软件存储数据层次的“状态”

  • 客户端状态:临时存储在客户端内存或文件中的数据。
  • 资源状态:持久化存储在服务端数据库中的数据。

4 网络传输层次的“状态”

  • 状态:传输两端(源端口、目的端口)在先后多次通信之间维护的上下文信息。
  • TCP 是有状态协议:协议要求传输两端对每个数据流,在传输前【初始化】两端的状态信息(握手),在传输中【维护】两端的【状态信息】。即TCP要求双方都要维护状态,并确保双方记忆同步。因此,一个连接中的每次通信都是有依赖关系的,不独立。
  • UDP是无状态协议:UDP对传输两端都不要求维护状态。发送方对应用层交下来的报文,既不合并,也不拆分,并且不保证数据包一定能到达接收方,也就无需维护上下文。因此,每一次通信都是相互独立的,无依赖关系。

1 组件交互层次的“状态”

HTTP协议(和URI规范一起)定义了组件在Web上交互的通用接口,客户端组件和服务端组件通过一对HTTP请求/响应完成一次交互。

会话状态(session state):组件在先后多次交互之间维护的上下文(context)信息。

1.1 HTTP是无状态协议

【RFC 7230】Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing 在2.3节中的解释如下:

HTTP is defined as a stateless protocol, meaning that each request message can be understood in isolation. Many implementations depend on HTTP’s stateless design in order to reuse proxied connections or dynamically load balance requests across multiple servers. Hence, a server MUST NOT assume that two requests on the same connection are from the same user agent unless the connection is secured and specific to that agent. Some non-standard HTTP extensions (e.g.,[RFC4559]) have been known to violate this requirement, resulting in security and interoperability problems.

Http 被定义为一个无状态协议,这意味着每个请求消息都可以被孤立地理解。许多实现依赖于HTTP 的无状态设计,以便跨多个服务器重用代理连接或动态对请求做负载均衡。因此,服务器不能假定同一连接上的两个请求来自同一用户代理,除非该连接是安全的并且特定于该代理。一些非标准的HTTP 扩展(例如,[RFC4559])已经违反了这一要求,导致了安全性和互操作性问题。

HTTP是无状态协议是指协议要求【服务端组件】只依赖当前请求中提供的信息来理解请求,而【不依赖于】从其他请求中保存的【会话状态】来理解请求。当服务端组件做到了这一点时,会产生如下效果:每个请求都是独立的,请求之间没有上下文关系。为了能让服务端组件做到这一点,需要客户端组件的配合,即客户端组件必须在请求中提供服务端组件理解该请求所需的全部信息。

1.2 为什么将HTTP设计为无状态协议?

HTTP协议定义了组件在Web上交互的通用接口,而REST是Web架构的设计原则,将HTTP设计为无状态协议是为了满足REST对于无状态交互的约束。

1.3 REST的无状态约束

Roy Fielding 在REST论文(中文翻译版)5.1.3 节中的定义:

我们接下来再为客户-服务器交互添加一个架构约束:交互必须在本质上是无状态的。如3.4.3小结中客户-无状态-服务器(CSS)风格那样,从客户到服务器的每个请求都必须包含理解该请求所必须的所有信息,不能利用任何存储在服务器端的上下文,会话状态因此要全部保存在客户端。

REST的无状态约束是指组件的交互必须在本质上是无状态的,其含义是:组件【交互】时,客户端组件【不能利用】任何【服务端组件保存的会话状态】。客户端组件为了满足此要求,必须把对方理解本次交互所需的全部信息都在本次交互中一起提供给对方。因为需要提供全部信息,客户端组件就必须保存所有会话状态。

1.4 为什么REST要包含无状态约束?

(一)Web的需求

REST是Web架构的设计原则,无状态约束作为设计原则之一,其存在的原因首先是基于Web的需求。根据Roy Fielding 的REST论文(中文翻译版)的4.1 节 ,与无状态约束相关的Web需求是:互联网规模 > 无法控制的可伸缩性,原文如下:

Web旨在成为一个互联网规模的分布式超媒体系统,而互联网是跨越组织边界互相连接的信息网络,这就使得信息服务的提供商必须有能力满足无法控制的可伸缩性、组件的独立部署这两方面要求。
其中,无法控制的可伸缩性是指架构元素可能会于其组织边界之外的元素进行通信,当它们遇到以下的情况时仍能正常运行:意料之外的负载、收到错误或恶意的数据等等时。这一点适用于所有的架构元素(数据、组件、连接器):
(1)不能期望作为客户方的架构元素(组件、连接器)保存所有服务信息。
(2)不能期望作为服务方的架构元素(组件、连接器)跨越多个请求保持状态信息。
(3)超媒体数据这一架构元素不能保存“回退指针”。

其中,无状态约束具体来自于第(2)点:不能期望作为服务方的架构元素(组件、连接器)跨越多个请求保持状态信息。 其含义是:
由于服务端组件随时可能遭遇意料之外的访问高峰/低谷,因此它必须具备迅速扩大/缩小服务规模的能力,即服务端组件的架构必须具备较好的可伸缩性。

  • 当服务端组件不保存任何会话状态时,伸缩将比较容易,直接增加/减少物理服务器的台数即可。
  • 当服务端保存了会话状态时,伸缩将比较困难,必须先解决会话共享问题(例如,把会话状态集中保存到中间服务器上,会增加架构的复杂性),才能考虑增加/减少物理服务器的台数。

【结论】为了让Web架构可以同时具有简单性、可伸缩性两个架构属性,服务端组件不能保存任何会话状态。实现这一点需要客户端组件的配合,即交互时,客户端组件不能利用任何保存在服务端组件上的会话状态,即交互必须在本质上是无状态的(无状态约束)。

(二)利大于弊

无状态约束在给Web架构带来好处的同时也需要付出代价,与大多数架构决策一样,REST包含无状态约束也是一种权衡后的选择。

根据Roy Fielding 的REST论文(中文翻译版)的5.1.3 节 、5.2.2节、5.3.1节,总结如下:
采用无状态约束给Web架构带来的好处:

  • 改善了可见性,服务端组件不必为了确定一个请求的完整意图而去查看该请求之外的其他请求。
  • 改善了可靠性,各个请求相互独立,没有依赖关系,如果某个请求失败了,只需重发这一个请求即可,从而减轻了从局部故障中恢复的任务量。
  • 改善了可伸缩性,服务端组件不必在多个请求之间保存状态,从而能更快释放资源并简化其实现。

采用无状态约束给Web架构造成的代价:

  • 在一系列相关的请求中发送了重复数据,增加了每次交互的开销,可能会降低网络性能。

采用无状态约束能得到以下功能:

  • 改善服务方连接器:连接器无需在请求之间保持状态,降低了连接器的物理资源消耗,并改善了连接器的可伸缩性。
  • 允许并行交互:允许连接器并行地完成交互,连接器无需理解交互的语义。
  • 允许负载均衡:使得中间组件只需根据本次请求提供的信息,就足以理解该请求的意图,而无需查看其他请求。组件要想实现负载均衡,必需满足此条件。
  • 改善缓存连接器:由于无状态约束强制了每个请求都必须包含理解该请求所需的全部信息,包括是否能够重用已缓存响应的信息,因此,缓存连接器能够相对合理地发挥作用,即在以下两个互斥的问题上尽量取得平衡:减少网络交互次数带来的用户感知性能提升,减少缓存错配。

采用无状态约束的其他好处:

  • 允许每个交互独立于其他交互,使得交互的两个组件只需关注对方即可,无需了解Web整体的拓扑结构(这对于互联网规模的Web架构来说是不可能完成的)。
  • 允许组件根据每个请求的意图来动态决定自己的角色,要么作为终点的服务端组件,要么作为中间组件。

1.5 违背无状态约束的典型例子:基于session的会话管理机制

  • 对于中间组件来说,当它们充当服务端组件的角色时,确实不需要查看其他请求就能完成它的处理工作,然后将该请求继续交给下一环节的组件来处理。即客户端组件向中间组件提供了中间组件所需的全部信息,中间组件没有保存任何会话状态。
  • 对于来源服务器这个终点服务端组件来说,它先将登录请求中提供的用户信息保存在session对象中,作为后续请求的上下文(即会话状态)。当收到后续请求时,必须先获取该上下文才能理解后续请求的完整意图。即客户端组件向来源服务器提供的信息是不全的,来源服务器保存了会话状态。

【结论】基于session的会话管理机制违背了REST的无状态约束,其代价是造成来源服务器无法同时获得简单性、可伸缩性这两个架构属性,为了可伸缩,必须增加来源服务器架构的复杂性。

1.6 错误说法:Cookie的作用是弥补HTTP协议的无状态缺陷

网上存在一种广为流传的说法:Cookie的作用是弥补HTTP协议的无状态缺陷。这种说法是错误的,无状态不是HTTP的缺陷,原因如下:

2 应用软件使用层次的“状态”

应用软件是直接向用户提供业务功能的系统,是由客户端组件、中间组件、服务端组件、连接器、数据动态构成的。

2.1 应用状态

根据Roy Fielding 的REST论文(中文翻译版)的5.33节,应用状态由以下几方面来定义:

悬而未决的请求(pending requests)
相连接组件的拓扑结构
连接器上活跃的请求(the acitve requests on those connectors)
在请求响应中的表述数据流
当用户代理接收到这些表述时对表述的处理

通俗的理解是:当没有未完成的请求时,应用软件所达到的一种稳定的状态。例如:浏览器加载完了一个“网页”中的所有请求(页面的表述–HTML、数据的表述–json、辅助的表述–图片、CSS、按需代码JavaScript等),对其渲染后所呈现的出的“网页”就是一个应用状态。

2.2 应用状态与会话状态的联系、区别

会话状态:组件在先后多次交互之间维护的上下文信息。

区别:层次不同

  • 应用状态是在业务层次上存在的概念,是用户使用应用软件产生的“网页”,用户是能够直观感受到的。
  • 会话状态是在实现层次上存在的概念,是组件交互过程中产生的临时数据,用户是感知不到的。

联系:存储位置

  • REST的无状态约束要求客户端组件(用户代理、以及充当客户端角色的中间组件)负责保存所有会话状态,服务端组件(来源服务器、以及充当服务端角色的中间组件)不保存会话状态。
  • REST的应用状态模型要求用户代理负责控制和保存应用状态,来源服务器不保存应用状态。

2.3 REST的含义

根据Roy Fielding 的REST论文(中文翻译版)的6.1节:

REST(Representational State Transfer),“表述性状态移交”这个名称是有意唤起人们对于一个良好设计的 Web 应用如何运转的印象:一个由网页组成的网络(一个虚拟状态机),用户通过选择链接(状态迁移)在应用中前进,导致下一个页面(代表应用的下一个状态)被移交给用户,并且呈现给他们,以便他们来使用。”

Web应用是一个由网页组成的网络(即一个虚拟状态机),用户通过选择链接在应用中前进(即应用状态迁移),导致系统将下一个页面(即下一个应用状态)的相关表述移交给用户,并且为用户呈现出来,以便他们使用。

表述性状态移交这个词可以粗略地理解为:通过移交表述,实现应用状态的迁移。

2.4 REST关于应用状态的模型

根据Roy Fielding 的REST论文(中文翻译版)的5.33节:

REST的应用模型是一个引擎,它通过检查、选择当前表述集合中的状态迁移选项,从一个状态迁移到下一个状态。毫不奇怪,这与一个超媒体浏览器的用户接口完全匹配。然而,REST风格并不假设所有应用都是浏览器。事实上,通用的连接器接口对服务器隐藏了应用的细节,因此各种形式的用户代理都是等价的,无论是为一个索引服务执行信息获取任务的自动化机器人,还是查找匹配特定查询标准的数据的私人代理,或者是忙于巡视破损的引用或被修改的内容的维护爬虫。

REST的应用模型是一个引擎,它通过检查、选择当前表述集合中的状态迁移选项,从一个状态迁移到下一个状态。符合REST的Web应用,应该既能被人类用户使用,也能被计算机程序使用。

为了实现这个应用模型,需要做到以下两点:
1、在组件交互方面:在交互用的统一接口中,使用超媒体来驱动应用状态的迁移。即【统一接口约束】中的第4个约束:将超媒体作为应用状态的引擎(Hypermedia As The Engine Of Application State,缩写为HATEOAS)。

例如:人类用户使用浏览器作为用户代理,浏览器与服务器通过HTTP请求/响应这个统一接口完成交互,服务器在响应中通过HTML的a、form、link、img、input等超媒体控件提供链接(即状态迁移选项),使得用户能够通过选择这些超媒体控件提供的链接在应用中前进,即从一个应用状态迁移到另一个应用状态。在这个过程中,超媒体(HTML)起到了驱动应用状态迁移的作用,称之为引擎。

注意:当用户是计算机程序时,很少有Web应用能做到HATEOAS。

2、在应用状态的存储位置方面:由用户代理负责控制和保存应用状态。

2.5 为什么应用状态应该存储在用户代理上?

(一)Web的需求

本文在1.4节中提到了Web的需求:互联网规模 > 无法控制的可伸缩性 > (3)超媒体数据这一架构元素不能保存“回退指针”。

其含义是:不能为了方便用户回退到上一个应用状态(之前访问的页面),就将该用户的所有应用状态(浏览历史)作为数据元素保存在服务器上。因为每个应用状态都是对其相关资源的一次引用,一千万个用户浏览同一个页面,就意味着服务器要保存一千万个引用。当用户量增长时,引用量将指数级增长。特别是用户量突然激增时(即无法控制的可伸缩性),服务器会很容易崩溃。

因此,服务器不能保存应用状态,应用状态必须在用户代理之间分摊,即每个用户代理保存自己用户的应用状态。

(二)利大于弊

好处

  • 应用状态可以由来自多个服务器的表述组成。
  • 服务器免除了存储应用状态所带来的可伸缩性问题。
  • 能够向用户提供更加丰富的功能:操作应用状态的功能(清除浏览历史)、预测应用状态变化的功能(超链接关系图、网页预加载),从一个应用跳转到另一个应用的功能(通过书签、URI输入栏直接跳转至其他网站)。

代价

  • 降低了服务器对于一致的应用行为的控制能力,控制将依赖于各个用户代理的正确实现。

2.6 违背REST应用状态模型的典型例子:通过Cookie引入站点范围的状态信息

根据Roy Fielding 的 REST论文(中文翻译版)的6.3.4.2节:

对协议作出不适当扩展的例子之一,是以HTTP Cookie的形式引入站点范围的状态信息,它所支持的功能与通用接口所期待的架构属性相矛盾。

Cookie原本只是浏览器在本地存储数据的技术,浏览器可以用Cookie控制和保存应用状态。但是,由于HTTP协议的不当扩展(【RFC 6265】HTTP State Management Mechanism),Cookie被用于引入站点范围的状态信息,即服务器通过Set-Cookie不加解释地强制浏览器保存给特定站点使用的信息。例如:

REST为了改善可见性,要求组件在Web上交互时都采用统一接口。而通过Cookie引入站点范围的状态信息,降低了可见性,与统一接口所期待的架构属性相矛盾。

2.7 哪些Cookie使用方法不符合REST,哪些符合?

根据Cookie的发送规则,判断是否符合REST的应用状态模型

  • 不符合的使用方法:将Cookie与特定的站点相关联,即在对特定站点的未来请求中都发送该Cookie。即使有些页面不需要该Cookie也会发送,这种情况下会使浏览器、服务器两端都产生混淆。例如:使用浏览器的“后退”功能回退到设置Cookie前的页面,该页面不需要Cookie,但Cookie仍然会被发送。
  • 符合的使用方法: 将Cookie与浏览器中特定的应用状态相关联,即在对特定页面的未来请求中才发送该Cookie。

根据Cookie值的决定方,判断是否符合REST对于可见性的要求

  • 不符合的使用方法:Cookie值由服务器生成,强制浏览器使用,Cookie值对于浏览器来说是不透明的,即允许数据在没有充分表明其语义的情况下进行传递,导致难以监视某个Cookie是否恶意,造成了安全和隐私方面的风险点。例如:广告商使用第三方Cookie追踪用户行为。
  • 符合的使用方法:Cookie值由浏览器生成,或服务器生成能被浏览器理解的建议值,由浏览器决定是否使用该建议值作为Cookie值。

2.8 哪些会话管理机制不符合REST,哪些符合?

详解Web应用中4类登录会话管理机制(基于session、基于cookie、基于token、基于认证)

不符合REST

  • 基于session的会话管理机制,存在以下三个问题,不符合REST:
    (1)利用了在服务端保存的会话状态,违背了REST的无状态约束;
    (2)将Cookie与特定的站点相关联,违背了REST的应用状态模型;
    (3)Cookie值不透明,违背了REST对于可见性的要求。

  • 基于cookie的会话管理机制,存在(2)、(3)两个问题,也不符合REST。

  • 基于token的会话管理机制,存在类似(2)、(3)的两个问题(在对特定站点的未来请求中都发送该token、token值不透明),也不符合REST。

符合REST

  • 基于认证的会话管理机制,其特点是客户端不传递登录凭证,而是对每个请求都传递账密编码值,服务器对每个请求都做一次认证。当它与HTTP标准认证机制(Basic、Digest、Mutual等)结合使用时,是符合REST的:
  • 会话状态保存在客户端,登录登出逻辑由客户端实现,符合REST的无状态约束。
  • 账密编码值与客户端中特定的应用状态相关联,即客户端只对需要认证的URI发送账密编码值,符合REST的应用状态模型。
  • 客户端负责按照认证机制的规则生成账密编码值,符合REST对于可见性的要求。

3 应用软件存储数据层次的“状态”

3.1 举例:购物车

对服务器来说,购物车中保存的商品数据只有在关联到具体用户的情况下才有意义。

  • 用户登录后,向购物车中添加的数据都能关联到该用户,这些数据对服务器来说是有意义的,客户端需要将这些数据发送给服务器,服务器将其持久化地存储在数据库中。称这些持久化存储在服务端的数据为资源状态,无论用户在哪个客户端登录,都能看到和操作自己购物车中的数据。
  • 用户登录前,向购物车中添加的数据无法关联到具体用户,这些数据对服务器来说没有意义。但是为了更好的用户体验,允许这些暂时没有关联到具体用户的数据存在,客户端将其存储在本地内存或文件中。称这些临时存储在客户端的数据为客户端状态。如果用户登录了,客户端需要将这些数据发送给服务器,转换为资源状态。如果用户一直未登录,并切换到其他客户端,则他将看不到这些保存在原客户端中的购物车数据。

4 网络传输层次的“状态”

4.1 TCP是有状态协议、UDP是无状态协议

根据 【RFC 793】Transmission Control Protocol(TCP) 的1.5节:

Connections 连接:
The reliability and flow control mechanisms described above require that TCPs initialize and maintain certain status information for each data stream. The combination of this information, including sockets, sequence numbers, and window sizes, is called a connection. Each connection is uniquely specified by a pair of sockets identifying its two sides.
上面描述的可靠性和流控制机制要求 TCPs 初始化并维护每个数据流的某些状态信息。这些信息的组合,包括套接字、序列号和窗口大小,称为连接。每个连接都由标识其两侧的一对套接字惟一指定。
When two processes wish to communicate, their TCP’s must first establish a connection (initialize the status information on each side). When their communication is complete, the connection is terminated or closed to free the resources for other uses.
当两个进程希望通信时,它们的 TCP 必须首先建立连接(初始化每一端的状态信息)。当它们的通信完成时,连接被终止或关闭,以释放资源用于其他用途。
Since connections must be established between unreliable hosts and over the unreliable internet communication system, a handshake mechanism with clock-based sequence numbers is used to avoid erroneous initialization of connections.
由于必须在不可靠的主机和不可靠的因特网通信系统之间建立连接,因此采用基于时钟序列号的握手机制来避免错误的连接初始化。

状态:传输两端(源端口、目的端口)在先后多次通信之间维护的上下文。
维护状态:从每次通信中记录某些特定信息作为后续通信的上下文。

TCP 是有状态协议:协议要求传输两端对每个数据流,在传输前【初始化】两端的状态信息(握手),在传输中【维护】两端的【状态信息】。即TCP要求双方都要维护状态,并确保双方记忆同步。因此,一个连接中的每次通信都是有依赖关系的,不独立。

UDP是无状态协议:UDP对传输两端都不要求维护状态。源端口对应用层交下来的报文,既不合并,也不拆分,并且不保证数据包一定能到达目的端口,从而无需维护上下文。因此,每一次通信都是相互独立的,无依赖关系。

4.2 TCP、UDP、HTTP比较

TCPUDPHTTP
要求源端口、目的端口双方都要维护上下文,并确保双方记忆同步对源端口、目的端口双方都不要求维护上下文要求客户端维护上下文,服务端不维护
一个连接中的每次通信都是有依赖关系的,不独立每一次通信都是独立的,无依赖关系每个请求都是独立的,无依赖关系

4.3 为什么HTTP的底层是有状态的TCP,HTTP却是无状态协议?

因为它们分别位于两个独立的协议层,所要求的对象不同,所维护的状态不同,互不影响。

  • 所处的协议层不同:TCP是传输层协议,HTTP是应用层协议。
  • 所要求的对象不同:TCP是对传输的两个端口提要求,要求双方维护状态。HTTP是对交互的两个组件提要求,要求作为客户方的组件维护状态,作为服务方的组件不维护状态。
  • 所维护的状态不同:TCP维护的状态是指握手、数据包的序列号和确认号等与传输相关的信息。HTTP的状态通常是指用户登录凭证、购物车标识等与应用软件相关的信息。

举例
TCP协议双方:源端口(快递站A)、目的端口(快递站B)
HTTP协议双方:浏览器(寄件机器人)、服务器(仓库收件机器人)

【应用层】用户想要在某网站(仓储服务公司)存储一个资源(一件货物),由浏览器替用户发送一个HTTP请求给服务器(寄件机器人把把这件货物寄给仓库收件机器人)。

【应用层 > 传输层】浏览器将这个HTTP请求交给TCP源端口进行传输(寄件机器人向快递站A下单)。

【传输层】源端口(快递站A)、目的端口(快递站B)通过握手在双方之间建立起了一条连接(传送带)。源端口把这个HTTP请求分装成10个数据包并加上序列号(把这件货物按顺序拆分成10个零件,每个快递箱装1个零件),每次通过建立好的连接(传送带)发送一个数据包。目的端口(快递站B)每收到一个数据包就返回一个确认包。源端口收到确认包就知道某序列号的数据包已传送成功。如果某个序列号的数据包在一段时间内一直没有收到对应的确认包,源端口就默认它已中途丢失,将重新发一个一样的数据包。这样一来,目的端口一定能够收到10个数据包(丢弃重复编号的数据包),从而按编号顺序组装成一个完整的HTTP请求(快递站B把10个零件组装成一个完整的货物)。

【传输层 > 应用层】TCP目的端口把这个HTTP请求交给应用层的服务器(快递站B把这件货物交给仓库收件机器人)。

【应用层】服务器收到请求后,将资源存入数据库,返回一个HTTP响应(仓库收件机器人返回一封信告诉用户货物已入库储存)。

【应用层 > 传输层】服务器将这个HTTP响应交给目的端口进行传输(仓库收件机器人向快递站B下单)。

【传输层】目的端口利用已建立好的连接传输该HTTP响应。一个TCP连接可以传输多个HTTP请求/响应。当TCP端口发现某个连接超过一定时间未被使用时,才会关闭该连接。(快递站A、B会重复使用已建立的传送带传输其他货物)

TCP是有状态协议:为了传输一个请求而进行的10次通信之间是有依赖关系的,不独立。
HTTP是无状态协议:每个请求之间是相互独立的,没有依赖关系。

比喻:把一件货物拆分,装进10个快递箱,这10个快递箱之间是有依赖关系的,不独立。而每件货物相互之间是独立的。

参考文档

  1. Roy Fielding 的 REST论文(英文原版)
  2. Roy Fielding 的 REST论文(中文翻译版)
  3. 介绍 Web 基础架构设计原则的经典论文《架构风格与基于网络的软件架构设计》导读
  4. 理解本真的 REST 架构风格
  5. 解读REST论文系列文章
  6. RESTful Web Services中文版
  7. 【RFC 7230】Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
  8. 【RFC 793】Transmission Control Protocol(TCP)
  9. 【RFC 6265】HTTP State Management Mechanism
  10. Web应用中4类登录会话管理机制(基于session、基于cookie、基于token、基于认证)
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
状态应用和无状态应用是两种不同的应用程序架构模式,它们在处理数据和维护状态方面有所区别。 有状态应用: 1. 数据持久性:有状态应用会维护和依赖于持久性数据存储,通常使用数据库或文件系统来存储和检索数据。 2. 会话状态:有状态应用会跟踪用户会话状态,例如用户登录信息、购物车内容等,以保持用户体验的连续性。 3. 扩展性挑战:由于需要维护和同步状态信息,有状态应用在水平扩展时面临更大的挑战。需要使用共享存储或数据库复制等技术来确保一致性。 4. 高可用性要求:由于数据的持久性和会话状态的存在,有状态应用在故障恢复和高可用性方面可能需要更多的关注。 无状态应用: 1. 数据无状态:无状态应用不维护持久性数据存储,通常使用外部服务或数据库来存储和检索数据。 2. 无会话状态:无状态应用不跟踪用户会话状态,每个请求都是独立的,不依赖于之前的请求。 3. 易于扩展:由于没有维护状态信息,无状态应用可以更容易地进行水平扩展,通过将请求路由到多个实例来实现负载均衡。 4. 高可用性:无状态应用更容易实现高可用性,因为每个请求都是独立处理的。如果一个实例失败,其他实例可以继续处理请求。 总结来说,有状态应用在处理数据和维护用户会话状态方面更复杂,需要更多的资源和关注。无状态应用更简单、易于扩展和实现高可用性,但可能需要依赖外部服务或数据库来存储和检索数据。选择适合的应用架构取决于应用程序的特性、要求和预期的规模。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值