“状态”实际上仅指客户端和服务器之间的状态。当然,服务器将存储数据,从技术上讲,您可以将服务器上任何数据的任何修改视为“改变状态”。因此,这种意义上的“无状态”应用程序绝对没有实际意义。
“无状态”指的是服务器在任何特定时间是否处于允许特定客户端向其发送特定请求的状态。
考虑一下:对于传统的基于 cookie 的登录会话,服务器仅处于接受客户端请求的状态在有限的时间范围内;只要当前会话有效。客户无法预测这会持续多久。任何时候,客户端的请求都可能失败,因为服务器上的某些状态时间到。在这种情况下,客户端需要通过重新登录来重置服务器的状态。
将此与基于令牌的身份验证进行对比。令牌必须无限期有效。它本质上是用户名和密码的替代。为了便于讨论,假设客户端在每次请求时都发送他们的用户名和密码。这意味着每个请求都可以根据其自身的优点进行身份验证,而不要求服务器处于某种特定的临时“状态”。
使用令牌而不是用户名和密码的原因有两个:
- 您可以使用同一帐户授权多个客户端,但每个客户端都具有单独管理的凭据
- 您不想在每个请求中来回发送“主密码”
当然,服务器需要跟踪创建的令牌并针对每个请求针对某个数据库进行身份验证。这是一个不相关的实现细节。这与使用会话 cookie 没有什么不同;但是,由于令牌无限期有效,因此可以更轻松地缓存请求,而无需复制临时会话存储。
最后一个需要先发制人的潜在论点是:无限期会话和无限期令牌之间有什么区别,会话结束时与令牌可以撤销时有什么区别?
当会话结束时,可以使用其他一些“主凭据”(重新登录)重新建立会话。令牌只能/应该仅在主动撤销时结束,这类似于撤销完全针对主凭据访问服务的授权,并且不属于常规应用程序流程的一部分。
更笼统地说:将无状态 HTTP 协议与有状态协议(如 FTP)进行对比。在 FTP 中,服务器和客户端需要保持共享状态同步。例如,FTP 协议具有许多其他特性:CWD
命令到更改当前工作目录。即,存在一个客户端在任何给定时间“位于”哪个目录的概念。后续命令的行为会根据所在目录的不同而有所不同。这是有状态的。您不能在不了解该状态的情况下随意发送命令,否则您将无法预测结果是什么。
无状态客户端/服务器通信首先简化了客户端,因为客户端可以随时假设能够向服务器请求任何内容,而无需知道服务器的信息。state服务器的(“我的会话是否仍然处于活动状态?”,“什么目录此操作会产生影响吗?”)。它可以帮助扩展服务器实现,因为只需要在所有服务器之间复制静态信息,而不是不断变化的有效会话及其关联数据池。
从架构上讲,您的目标应该是拥有尽可能多的无状态组件尽可能。这将简化横向扩展。例如,如果您的 Web 服务器保留本地会话存储,则很难将 Web 服务器扩展到负载均衡器/CDN 后面的多个实例。一项改进是将会话存储集中到一个独立的数据库中;现在你可以有几个无国籍的Web 服务器知道如何从某处获取数据(包括会话数据)并可以呈现模板,但在其他方面是完全可互换的。
然而,一个会话存储必须在尝试访问它的每个人之间保持完美同步,这使得扩展变得困难it. 令牌通过减少数据更改频率(仅当添加或删除令牌时)来改善这一点,这意味着如果您希望在可能的多个位置有多个令牌存储,和/或使您可以使用分布式数据库或其他更简单的复制机制该数据可缓存。