如果REST应用程序应该是无状态的,那么您如何管理会话?

我需要一些澄清。 我一直在阅读REST,并构建RESTful应用程序。 根据维基百科,REST本身被定义为具象状态传输 。 因此,我不明白所有这些每个人都在不停地喷涌而出的无国界的大杂烩

从维基百科:

在任何特定的时间,客户可以在应用程序状态之间转换或“静止”。 处于休眠状态的客户端能够与其用户进行交互,但不会创建任何负载,也不会消耗服务器组或网络上的每个客户端存储。

他们只是说不使用会话/应用程序级别的数据存储?

我得到REST的一个目标是使URI访问一致和可用,例如,而不是在帖子内部隐藏分页请求,使得请求的页码成为GET URI的一部分。 对我有意义。 但似乎只是过度的说, 每个客户端数据 (会话数据)都不应该存储在服务器端。

如果我有一个消息队列,并且我的用户想要阅读这些消息,但是当他阅读这些消息的时候,想要在会话期间阻止某些发送者消息通过? 将它存储在服务器端的地方是否有意义,并让服务器只发送未被用户阻止的消息(或消息ID)?

每次我请求新的消息列表时,是否真的必须发送整个消息发送者列表来阻塞? 与我相关的消息列表首先不会/甚至不应该是公开可用的资源。

再次,只是想明白这一点。 有人澄清。


更新:

我发现了一个堆栈溢出的问题,有一个答案,不完全让我一路在那里: 如何管理REST的状态,它表示,重要的客户端状态应该在每个请求都转移…. Ugg ..似乎有很多的开销…这是对的吗?

基本的解释是:

服务器上没有客户端会话状态。

无状态意味着服务器不会在服务器 存储有关客户端会话的任何状态。

客户端会话存储在客户端上。 服务器是无状态的,意味着每个服务器可以随时为任何客户端服务,不存在会话关联粘滞会话 。 相关的会话信息存储在客户端,并根据需要传递给服务器。

这并不排除Web服务器与维护有关诸如购物车等业务对象状态的其他服务,而不是关于客户端当前的应用程序/会话状态。

客户端的应用程序状态不应该存储在服务器上,而是从客户端传递到每个需要它的地方。

这就是REST中的ST来自State Transfer 。 你转移状态而不是让服务器存储它。 这是扩展到数百万并发用户的唯一方法。 如果没有其他原因,而不是因为数百万的会议是数百万的会议。

会话管理的负载在所有客户端之间分摊,客户端存储他们的会话状态,服务器可以以无状态的方式为多个数量级或更多的客户端服务。

即使对于一个您认为只会在数千个并发用户中需要的服务,您仍然应该使您的服务处于无状态。 成千上万的人仍然有成千上万,而且会有与时间和空间有关的成本。

无状态是HTTP协议和一般的Web设计是如何操作的,并且是一个整体上更简单的实现,并且你有一个代码路径而不是一堆服务器端逻辑来维持一堆会话状态。

有一些非常基本的实施原则:

这些原则不是实现,你如何符合这些原则可能会有所不同。

总之, 五个关键原则是:

  1. 给每个“东西”一个ID
  2. 把事情联系起来
  3. 使用标准方法
  4. 具有多个表示的资源
  5. 沟通无国界

在REST 论文中没有关于认证或授权的内容。

因为与从非RESTful请求进行身份验证相比,没有任何区别。 认证与RESTful讨论无关。

解释如何为您的特定需求创建一个无状态的应用程序,对于StackOverflow来说太广泛了。

与REST相关的实现身份验证和授权更为广泛 ,在各种因特网上对各种实现方法进行了详细解释。

有关此问题的意见征求/意见将被标记为“ 不建设”

无状态意味着每个HTTP请求都完全隔离。 当客户端发出HTTP请求时,它包含服务器完成该请求所需的所有信息。 服务器从不依赖于以前请求的信息。 如果这个信息很重要,那么客户会在这个请求中再次发送这个信息。 无状态也带来了新的特点。 在负载平衡的服务器上分发无状态应用程序更容易。 无状态应用程序也很容易缓存。

实际上有两种状态。 生活在服务器上的客户端和资源状态的应用程序状态。

当您实际发出请求时,Web服务只需要关心您的应用程序状态。 其余的时间,它甚至不知道你的存在。 这意味着每当客户端发出请求时,都必须包含服务器需要处理的所有应用程序状态。

每个客户端的资源状态是相同的,并且它的适当位置在服务器上。 当您将图片上传到服务器时,您将创建一个新的资源:新图片具有自己的URI,可以作为未来请求的目标。 您可以通过HTTP获取,修改和删除此资源。

希望这有助于区分什么是无国籍和各国的意思。

他们只是说不使用会话/应用程序级别的数据存储?

不,他们并不是这么说的。

他们说不定义一个“会话”。 不要登录。 不要注销。 提供凭据与请求。 每个请求都是独立的。

你还有数据存储。 你仍然有认证和授权。 你只是不浪费时间建立会议和维护会话状态。

重点是每个请求(a)完全独立,(b)可以被平凡的繁殖到一个巨大的并行服务器场,而不需要任何实际的工作。 Apache或Squid可以盲目成功地传递RESTful请求。

如果我有一个消息队列,并且我的用户想要读取这些消息,但是当他阅读这些消息的时候,想要在会话期间阻止某些发送者消息通过?

如果用户想要过滤器,那么只需在每个请求中提供过滤器即可。

服务器只发送未被用户阻止的消息(或消息ID)吗?

是。 在RESTful URI请求中提供过滤器。

每次我请求新的消息列表时,是否真的必须发送整个消息发送者列表来阻塞?

是。 这个“消息发送者阻止列表”有多大? PK的短名单?

GET请求可能非常大。 如果有必要,你可以尝试一个POST请求,即使它听起来像一种查询。

用户应用程序状态管理的历史视图

传统意义上的会话将用户的状态保存在服务器内的应用程序中。 这可能是流程中的当前页面,或者以前输入的内容,但是尚未保存到主数据库中。

这种需求的原因是缺乏客户端的标准来有效地维护状态而没有使客户端特定(即特定于浏览器)的应用程序或插件。

HTML5和XML Header Request随着时间的推移,标准化了在客户端(即浏览器)端以标准方式存储复杂数据(包括应用程序状态)的概念,而不需要在服务器之间来回切换。

REST服务的一般用法

当需要执行事务或需要检索数据时,通常会调用REST服务。

REST服务意味着由客户端应用程序调用,而不是直接由最终用户调用。

认证

对于对服务器的任何请求,部分请求应包含授权令牌。 它是如何实现的是特定于应用程序的,但通常是BASICCERTIFICATE形式的身份验证。

REST服务不使用基于表单的身份验证。 但是,如上所述,REST服务并不意味着被用户调用,而是被应用程序调用。 应用程序需要管理获取身份验证令牌。 在我的情况下,我使用JASPIC和OAuth 2.0的 cookie 连接到Google进行身份验证,并使用简单的HTTP身份验证进行自动测试。 我也通过JASPIC使用HTTP Header身份验证进行本地测试(尽管在SiteMinder中可以执行相同的方法)

根据这些示例,身份验证在客户端进行管理(尽管SiteMinder或Google会将身份验证会话存储在其终端上),但是该状态没有任何可执行的内容,但它不是REST服务应用程序的一部分。

检索请求

REST中的检索请求是请求特定资源且可缓存的GET操作。 不需要服务器会话,因为请求包含检索数据所需的一切:身份验证和URI。

事务脚本

如上所述,客户端应用程序本身也会调用REST服务以及它在客户端管理的身份验证。

这意味着对于REST服务(如果正确地做),对REST服务器采取单一请求将包含单个用户操作所需的所有事情,这些操作完成单个事务所需的所有事务, 事务脚本就是该模式叫做。

这通常是通过POST请求来完成的,但也可以使用其他的如PUT

REST的很多人为的例子(我自己这样做)试图遵循HTTP协议中定义的那些东西,在经历了这些之后,我决定更加务实,只把它留给GET和POST 。 POST方法甚至不需要实现POST-REDIRECT-GET模式。

尽管如上所述,客户端应用程序将是调用服务的应用程序,它只会在需要时(而不是每次)调用带有所有数据的POST请求。 这可以防止对服务器的持续请求。

轮询

虽然REST也可用于轮询,但我不会推荐它,除非由于浏览器兼容性而必须使用它。 为此我将使用我设计了API合约的 WebSockets。 CometD是旧版浏览器的另一种选择。

你是绝对正确的,支持与服务器完全无状态的交互确实给客户带来了额外的负担。 但是,如果考虑扩展应用程序,则客户端的计算能力与客户端的数量成正比。 因此,扩展到大量的客户更加可行。

只要您在服务器上负责管理与特定客户端交互相关的一些信息,这种负担就会迅速增长,从而消耗服务器。

这是一个权衡。

REST非常抽象。 这有助于获得一些好的,简单的,现实世界的例子。

举例来说,所有主要的社交媒体应用程序 – Tumblr,Instagram,Facebook和Twitter。 他们都有一个永远滚动的视图,你向下滚动得越远,你看到的内容就越多,时间越来越晚。 但是,我们都经历过那个时候你失去了滚动的地方,应用程序重置你回到顶部。 就像如果你退出应用程序,然后当你重新打开它,你又回到了顶端。

之所以这样,是因为服务器没有存储你的会话状态。 不幸的是,你的滚动位置只是存储在客户端的RAM中。

幸运的是,当您重新连接时,您不必重新登录,但这仅仅是因为您的客户端还存储了登录证书尚未过期。 删除并重新安装应用程序,您将不得不重新登录,因为服务器没有将您的IP地址与您的会话相关联。

您在服务器上没有登录会话,因为他们遵守REST。


现在上面的例子根本不涉及Web浏览器,但是在后端,应用程序正在通过HTTPS与其主机服务器进行通信。 我的意思是,REST不必涉及cookie和浏览器等。存储客户端会话状态的方式有很多种。

但让我们谈谈网页浏览器,因为这带来了REST的另一个主要优势,这里没有人谈论。

如果服务器试图存储会话状态,应该如何识别每个客户端?

它不能使用他们的IP地址,因为很多人可能在共享路由器上使用相同的地址。 那么怎么样呢?

它不能使用MAC地址有很多原因,其中最重要的原因是因为您可以在不同的浏览器上同时登录到多个不同的Facebook帐户以及应用程序。 一个浏览器可以很容易地伪装成另一个浏览器,MAC地址也很容易被欺骗。

如果服务器必须存储一些客户端状态来识别您的身份,则必须将其存储在RAM中,而不仅仅是处理请求所需的时间,否则必须缓存该数据。 服务器的RAM和缓存数量有限,更不用说处理器的速度了。 服务器端状态以指数形式增加到所有三个状态。 此外,如果服务器将存储有关会话的任何状态,则必须将其分别存储在当前登录的每个浏览器和应用程序中,也针对您使用的每种不同设备进行存储。


所以…我希望你现在看到为什么REST对于可伸缩性如此重要。 我希望你可以开始明白为什么服务器端的会话状态是服务器可伸缩性的原因。


人们感到困惑的地方是认为“状态”是指存储在数据库中的信息。 不,它指的是在使用服务器时需要在服务器内存中的任何信息。

无状态意味着服务的状态不会在随后的请求和响应之间持续。 每个请求携带自己的用户凭证,并单独进行身份验证。 但是在有状态的情况下,每个请求都可以从以前的任 所有有状态请求都是面向会话的,即每个请求都需要知道并保留以前请求中所做的更改。

银行应用程序是有状态应用程序的一个例子。 用户首先登录然后进行交易并注销。 如果注销后用户将尝试进行交易,他将不能这样做。

是的,http协议基本上是一个无状态的协议,但使它有状态,我们使我们的HTTP Cookie。 所以,默认情况下是SOAP。 但它也可以是有状态的,取决于你正在使用的框架。

HTTP是无状态的,但我们仍然可以通过使用不同的会话跟踪机制来维护我们的Java应用程序中的会话

是的,我们也可以在webservice中维护会话,无论是REST还是SOAP。 它可以通过使用任何第三方库来实现,也可以由我们自己来实现。

采取从http://gopaldas.org/webservices/soap/webservice-is-stateful-or-stateless-rest-soap

我看到这里的基本问题是把会议国家混为一谈 。 虽然REST指定您不应该将状态存储在服务器上,但没有任何东西阻止您存储用户会话

在服务器上管理状态意味着你的服务器确切地知道客户正在做什么(他们正在哪个页面查看应用程序的哪个部分)。 这是你不应该做的。

我同意其他人说,你应该保持会议存储的最小尺寸; 虽然这是常识,但实际上也取决于应用程序。 因此,简而言之,您仍然可以使用缓存数据保持会话,以便在服务器上负载较少的情况下处理请求,并通过为客户端提供临时身份验证/访问令牌来管理身份验证。 每当会话/令牌过期时,生成一个新的请求客户端使用它。

有人可能会争辩说,客户应该更好地生成令牌。 我说这两种方式都有效,这取决于应用程序,以及谁将使用API​​。

同时在服务器上保留一些敏感的会话数据应该是正确的做法。 你不能相信客户保持他们的购物车(例如)包含一个名为“isFreeGift”的字段。 这些信息应该保存在服务器上。

Santanu Dey在他的回答中提供的视频链接是有帮助的。 如果你没有看,请看。

只是一个侧面说明:似乎所有已经给出的答案似乎忽略了一些操作可能会导致服务器负载很重的事实。 这在功耗,硬件消耗和成本(针对CPU周期租用的服务器)方面是相关的。 一个优秀的开发人员不应该懒惰地优化他们的应用程序,即使在一些租用的服务器上的现代CPU上可以很快完成操作,而这些服务器并不支付电费和维护费用。

虽然这个问题已经有几年了,但我希望我的回答仍然有帮助。

看看这个演示文稿。

http://youtu.be/MRxTP-rQ-S8

根据这种模式 – 创建瞬态宁静的资源来管理状态,如果真的需要的话。 避免显式会话。

无状态与有状态之间的主要区别是数据每次都被传回服务器。 在无状态的情况下,客户端必须提供所有信息,因此可能需要在每个请求中传递大量的参数。 在Stateful中,cliet将这些参数传递一次,并由服务器维护,直到客户端再次修改。

国际海事组织,API应该是无国籍的,这使得可以迅速扩大规模。

您必须在客户端管理客户端会话。 这意味着你必须发送每个请求的身份验证数据,而且你可能没有必要在服务器上有一个内存缓存,它将身份验证数据与身份,权限等用户信息配对。

这种REST 无状态约束是非常重要的。 没有应用这个约束,你的服务器端应用程序将不能很好地扩展 ,因为维护每一个客户端会话将是它的致命弱点 。

整个概念是不同的…如果您正在尝试实现RESTFul协议,则不需要管理会话。 在这种情况下,最好对每个请求执行身份验证过程(而在性能方面则需要额外的成本 – 哈希密码就是一个很好的例子,不是什么大问题)。 如果您使用会话 – 如何分配负载跨多个服务器? 我敢打赌RESTFul协议是为了消除任何会议 – 你并不真正需要他们…这就是为什么它被称为“无国籍”。 会话只有在客户端没有存储Cookie之外的任何东西时才需要(请以老的,非Javascript /支持HTML5的浏览器为例)。 对于“全功能”的RESTFul客户端来说,在客户端(内存中)存储base64(login:password)通常是安全的,直到应用程序仍然被加载 – 应用程序被用来访问唯一的主机和cookie不能由第三方脚本妥协…

我会强烈建议为RESTFul服务禁用cookie身份验证…检查基本/摘要身份验证 – 这应该是足够的基于RESTFul的服务。