【问题标题】:Stateless web application, an urban legend?无状态 Web 应用程序,一个都市传奇?
【发布时间】:2016-04-13 00:24:06
【问题描述】:

这些天我试图理解token-based authentication,它声称是stateless authentication 方法。而且我遇到了stateless web application这个概念。

以下是我读到的一些主题:

起初,我对这个想法很兴奋。但我越来越觉得statelesspseudo-proposition

例如,假设我们使用客户端存储的令牌进行身份验证,我们如何对在线用户进行统计(假设没有日志)?我们应该将令牌存储在数据库中吗?这是否意味着我们将状态信息存储在服务器上?更何况,DB中的姓名、年龄等普通用户信息也是某种状态信息吗?

我认为这里真正的问题不是让网络应用程序无状态,而是让网络应用程序正确处理状态信息,从而不会危及可扩展性

这取决于如何解释stateless这个词:

  1. Web 应用没有状态。
  2. 或者网络应用不存储状态本身

我更喜欢 2,因为总会有一些 inevitable global state(引用自 @deceze 对他的回答的评论)。而且无论我们将状态信息存储为 HTML 5 Web 存储、HTTP 标头、隐藏表单字段或 Cookie,状态仍然存在。只是它存储在服务器以外的其他地方。

我错过了一些很棒的东西吗?任何人都可以对此有所了解,以便我可以从这种精神斗争中解脱出来吗?

添加 1 个

只需阅读Leonard Richardson 的书RESTful Web Services。在第 4 章中,在Statelessness 部分的末尾,它将状态分类为Application StateResource State。所以我之前提到的普通用户信息和数据,比如图片等,可以归类为Resource State。而stateless 指的是Application State。所以在服务器上存储resource state不会破坏无状态的代码。

但是这本书也提到了an application key is used to restrict how many times a user can invoke a web service.它承认这样的信息不能存储在客户端的场景。并且必须将其存储在服务器端会破坏无状态代码并引入会话亲和性问题。 它声称无状态可以避免会话亲和性问题,但没有解释如何。 我真的不明白无状态如何处理这种情况。任何人都可以在这里阐明一下吗?

【问题讨论】:

  • 什么是无状态网络应用?你这个词是从哪里来的?我只知道无状态连接/协议。
  • @freakish 感谢您的回复。我从几个线程中读取它。我在这里总结了一些:stackoverflow.com/questions/34651801/…
  • 我认为,如果你写下 statefull 的缺点列表,你将能够定义什么是无状态的,对吧?但这些缺点是主观的,这就是为什么没有明确的定义。
  • 不,如果您的客户需要状态(“欢迎 X,您已登录”),您的整个堆栈就不可能是无状态的。 应用服务器可以是无状态的,但您的客户端不会,而且很可能在应用服务器后面也有一些共享数据存储。
  • 是的,这也是我的感觉。您想要一个无状态应用程序服务器的主要原因是请求处理是独立的,您可以将它们干净地分布在多台机器上。所有这些仍然会访问数据库(可以自己分发),但实际的请求处理是独立的。以会话为例,这是不可能的 - 您必须在所有请求处理机器上复制会话数据。

标签: http session web token stateless


【解决方案1】:

好的,我认为无状态网络应用程序这个词没有任何意义。有意义的是无状态协议。而无状态协议是一种独立处理每个请求的协议。

因此,在您的情况下,如果您在每个请求中发送一个身份验证令牌,那么它就是无状态的。这就是 HTTP 身份验证的工作方式。

另一方面,如果您只发送一次身份验证令牌并且每个连续的请求都不必发送(例如,因为服务器知道此 TCP 连接已经过身份验证),那么这意味着每个请求都取决于身份验证请求。这使得协议有状态。

无状态协议更易于扩展、更易于代理等。

现在对于 Web 应用程序,该术语可能有意义,也可能没有意义,具体取决于定义。我不知道有什么合理的。

旁注:有状态/无状态与客户端和服务器之间的数据共享无关。

【讨论】:

    【解决方案2】:

    我认为无状态身份验证和无状态应用程序并不像您想象的那样相关;无状态一词在这里用于两种不同的上下文。

    无状态身份验证是一种识别客户端身份的方法,无需携带来自先前客户端请求或交互的任何信息/状态,这与 cookie 不同。

    无状态 Web 应用程序?当然,它们是可能的,但这完全取决于是否必须保留用户数据,也就是说,这实际上取决于相关应用程序。

    【讨论】:

      【解决方案3】:

      “状态”实际上只是指客户端和服务器之间的状态。当然,服务器将存储数据,从技术上讲,您可以将服务器上任何数据的任何修改视为“更改状态”。因此,这种意义上的“无状态”应用程序绝对没有实际意义。

      “无状态”指的是服务器是否在任何特定时间处于允许特定客户端向其发送特定请求的状态。

      考虑:对于传统的基于 cookie 的登录会话,服务器仅在有限的时间窗口内处于接受来自客户端的请求的状态;只要当前会话有效。客户无法预测那是多长时间。在任何时候,来自客户端的请求都可能失败,因为服务器上的某些状态超时。在这种情况下,客户端需要重新登录来重置服务器的状态。

      将此与基于令牌的身份验证进行对比。令牌必须无限期有效。它本质上是用户名和密码的替代品。为了讨论起见,假设客户端在每个请求中都发送了他们的用户名和密码。这意味着每个请求都可以根据自己的优点进行身份验证,而不需要服务器处于某种特定的临时“状态”。

      您使用令牌而不是用户名和密码的原因有两个:

      1. 您可以使用同一个帐户授权多个客户,但每个客户都有自己管理的凭据
      2. 您不希望每次请求都来回发送“主密码”

      当然,服务器需要跟踪创建的令牌,并针对每个请求对某个数据库进行身份验证。这是一个无关紧要的实现细节。这与使用会话 cookie 没有区别;但是,由于令牌无限期有效,因此可以更轻松地缓存请求,而无需复制临时会话存储。

      最后一个需要先发制人反击的潜在论点:无限期会话和无限期令牌之间有什么区别,会话结束与令牌可能被撤销的时间有什么区别?
      当会话结束时,可以使用其他一些“主凭据”(重新登录)重新建立它。令牌只能/应该仅在主动撤销时结束,这类似于完全撤销对主凭据访问服务的授权,而不是常规应用程序流程的一部分。


      更笼统地说:将无状态 HTTP 协议与 FTP 等有状态协议进行对比。在 FTP 中,服务器和客户端需要保持同步的共享状态。例如,FTP 协议除许多其他功能外,还具有用于更改当前工作目录CWD 命令。即,在任何给定时间,都有一个客户“在”哪个目录的概念。后续命令的行为会有所不同,具体取决于某个目录所在的目录。这是有状态的。您不能在不知道该状态的情况下随意发送命令,否则您将无法预测结果。


      无状态客户端/服务器通信首先简化了客户端,因为客户端可以随时假设能够请求服务器的任何内容,而无需知道服务器的状态 (“我的会话是否仍然处于活动状态?”、“此操作会影响什么目录?”)。 它可以帮助扩展服务器实施,因为只需要在所有服务器之间复制静态信息,而不是不断变化的有效会话池及其相关数据。


      在架构上,您的目标应该是拥有尽可能多的无状态组件。这将简化横向扩展。例如,如果您的 Web 服务器保留本地会话存储,则很难将您的 Web 服务器扩展到负载均衡器/CDN 后面的多个实例。一项改进是将会话存储集中到一个独立的数据库中;现在您可以拥有多个 无状态 Web 服务器,它们知道如何从某个地方获取数据(包括会话数据)并可以呈现模板,但在其他方面完全可以互换。

      但是,会话存储必须在每个尝试访问它的人之间保持完美同步,这使得扩展变得困难。 令牌通过减少数据更改(仅在添加或删除令牌时)来改善这一点,这意味着如果您希望在可能的多个位置有多个令牌存储,您可以使用分布式数据库或其他更简单的复制机制,并且/或使该数据可缓存。

      【讨论】:

      • 感谢您的回复。到目前为止,我认为可扩展性存在一些不可避免的代价。无国籍只能降价,不能去掉。如果应用程序设计为无状态(令牌部分除外),则在横向扩展时只需要处理令牌信息,这比复制瞬态会话数据要简单得多。 (顺便说一句,我强调了你答案的一部分)。
      • 对,任何“全局状态”通常都是可扩展性的瓶颈。这意味着需要全局一致的数据存储。该存储中的数据更改得越频繁,就越难在所有实例中保持最新。因此,请尽可能多地删除这些内容,以保留尽可能多的无状态组件。
      猜你喜欢
      • 2015-10-30
      • 1970-01-01
      • 2011-03-26
      • 2011-07-29
      • 2012-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多