我需要一些澄清。我一直在阅读关于REST和构建基于REST的应用程序的书籍。根据维基百科,REST本身被定义为具象状态传输。因此,我不理解所有这些无国籍的官样文章,每个人都在不停地吐出来。

从维基百科:

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

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

我知道REST的一个目标是使URI访问一致且可用,例如,不是在帖子中隐藏分页请求,而是使请求的页码成为get URI的一部分。对我来说很有道理。但是,说每个客户端数据(会话数据)都不应该存储在服务器端似乎有点过头了。

如果我有一个消息队列,而我的用户想要读取消息,但在读取消息时,又想在会话期间阻止某些发送者的消息通过,该怎么办?将其存储在服务器端的某个位置,并让服务器只发送未被用户阻止的消息(或消息ID),这难道不合理吗?

每次请求新的消息列表时,我真的必须发送整个消息发送者列表来阻止吗?与我相关的消息列表在一开始就不应该是公开可用的资源。

我只是想理解一下。谁来澄清一下。


更新:

我发现了一个堆栈溢出的问题,它的答案并不能让我一直走到那里: 如何在REST中管理状态 这说明客户端状态很重要,应该在每个请求上都传输....Ugg . .看起来开销很大…这样对吗??


当前回答

The whole concept is different... You don't need to manage sessions if you are trying to implement RESTFul protocol. In that case it is better to do authentication procedure on every request (whereas there is an extra cost to it in terms of performance - hashing password would be a good example. not a big deal...). If you use sessions - how can you distribute load across multiple servers? I bet RESTFul protocol is meant to eliminate sessions whatsoever - you don't really need them... That's why it is called "stateless". Sessions are only required when you cannot store anything other than Cookie on a client side after a reqest has been made (take old, non Javascript/HTML5-supporting browser as an example). In case of "full-featured" RESTFul client it is usually safe to store base64(login:password) on a client side (in memory) until the applictation is still loaded - the application is used to access to the only host and the cookie cannot be compromised by the third party scripts...

我强烈建议禁用RESTFul服务的cookie认证…检查Basic/Digest Auth -这对于基于rest的服务应该足够了。

其他回答

Stateless means the state of the service doesn’t persist between subsequent requests and response. Each request carries its own user credentials and is individually authenticated. But in stateful each request is known from any prior request. All stateful requests are session-oriented i.e. each request need to know and retain changes made in previous requests. Banking application is an example of stateful application. Where user first login then make transaction and logs out. If after logout user will try to make the transaction, he will not be able to do so. Yes, http protocol is essentially a stateless protocol but to make it stateful we make us of HTTP cookies. So, is SOAP by default. But it can be make stateful likewise, depends upon framework you are using. HTTP is stateless but still we can maintain session in our java application by using different session tracking mechanism. Yes, We can also maintain session in webservice whether it is REST or SOAP. It can be implemented by using any third party library or you can implement by our own.

摘自http://gopaldas.org/webservices/soap/webservice-is-stateful-or-stateless-rest-soap

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

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

这是一种权衡。

没有勺子。

不要把无状态想象成“一次又一次地把你所有的东西发送到服务器”。不可能。总会有状态——数据库本身也是一种状态,毕竟你是注册用户,所以没有服务器端,任何客户端信息都是无效的。从技术上讲,您从来都不是真正无状态的。

关于登录的争论

不保持会话并每次都登录是什么意思? 有些意思是“每次都发送密码”,这太愚蠢了。有些人说“不,当然不是,而是发送一个令牌”——你瞧,PHP会话就是这么做的。它发送一个会话id,这是一种令牌,它可以帮助你到达你的个人物品,而不必每次都重发u/pw。它也非常可靠,并且经过了良好的测试。是的,方便也会变成缺点,见下一段。

减少碳足迹

What you should do, instead, and what makes real sense, is thin your webserver footprint to the minimum. Languages like PHP make it very easy to just stuff everything in the session storage - but sessions have a price tag. If you have several webservers, they need to share session info, because they share the load too - any of them may have to serve the next request. A shared storage is a must. Server needs to know at least if someone's logged in or not. (And if you bother the database every time you need to decide this, you're practically doomed.) Shared storages need to be a lot faster than the database. This brings the temptation: okay, I have a very fast storage, why not do everything there? - and that's where things go nasty in the other way.

你的意思是,保持会话存储最小?

Again, it's your decision. You can store stuff there for performance reasons (database is almost always slower than Redis), you can store information redundantly, implement your own caching, whatever - just keep in mind that web servers will have a bigger load if you store a lot of rubbish on them. Also, if they break under heavy loads (and they will), you lose valuable information; with the REST way of thinking, all that happens in this case is the client sends the same (!) request again and it gets served this time.

那该怎么做呢?

No one-fits-all solution here. I'd say choose a level of statelessness and go with that. Sessions may be loved by some and hated by others but they're not going anywhere. With every request, send as much information as makes sense, a bit more perhaps; but don't interpret statelessness as not having a session, nor as logging in every time. Somehow the server must know it's you; PHP session ids are one good way, manually generated tokens are another. Think and decide - don't let design trends think for you.

您必须在客户端管理客户端会话。这意味着您必须在每个请求中发送身份验证数据,并且您可能(但不一定)在服务器上有一个内存缓存,它将身份验证数据与用户信息(如身份、权限等)配对。

这种REST无状态约束非常重要。如果不应用此约束,您的服务器端应用程序将不能很好地扩展,因为维护每个客户机会话将是它的阿喀琉斯之踵。

我知道这里的基本问题是混淆了会议和国家。虽然REST指定不应该在服务器上存储状态,但没有什么可以阻止您存储用户会话。

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

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

有人可能会说,客户端应该更好地生成令牌。我说它是双向工作的,这取决于应用程序,以及谁将使用API。

在服务器上保留一些敏感的会话数据也是正确的做法。例如,您不能相信客户端会保留包含名为“isFreeGift”字段的购物车。这些信息应该保存在服务器上。

Santanu Dey在回答中提供的视频链接很有帮助。如果你还没看过,就看看吧。

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

虽然这个问题是几年前的事了,但我希望我的回答仍然会有帮助。