有状态的 Web 服务有多好和/或有多必要?

Posted

技术标签:

【中文标题】有状态的 Web 服务有多好和/或有多必要?【英文标题】:How good and/or necessary are Stateful Web Services? 【发布时间】:2010-11-03 20:05:09 【问题描述】:

你们在实际项目中看到什么样的服务器?

1) Web 服务必须是无状态的:基本上,您必须在每个请求中发送用户名/密码,每个请求都必须使用 HTTPS,如果需要,我将每次都进行身份验证并加载用户对象。

2) 用于 Web 服务的会话:就像在 Web 容器中一样,因此我至少可以保存经过身份验证的用户对象并具有类似于会话 ID 的内容,因此我不需要对每个用户进行身份验证、加载和检查请求。

3)Sticky Service(跨请求的持久服务):https://jax-ws.dev.java.net/nonav/2.1/docs/statefulWebservice.html

我了解有状态服务(以及 Web 应用程序会话)的可伸缩性问题,但有时您必须拥有某种状态,例如购物车。但是您也可以将此状态放入数据库(将后端用作一种会话 argh)或将整个状态传递给客户端(客户端负责重新发送整个购物车) .

事实上,至少对于 Web 应用程序而言,会话在许多情况下都有很大帮助。如果您的系统接受“如果他的网络服务器发生故障,用户必须重新开始他正在做的任何事情”,或者如果这是不可接受的,您可以尝试会话集群,则可以忽略可伸缩性问题。

Web 服务如何?我倾向于得出结论,Web 服务与 Web 应用程序有很大不同,并且接受选项 1)(始终无状态),但很高兴听到基于实际项目经验的其他意见。

【问题讨论】:

【参考方案1】:

虽然只是很小的区别,但仍应提及:

不是 Web 服务中的状态 会扼杀可扩展性,而是 应用服务器上的状态 托管 Web 服务会扼杀可扩展性。当您说此用户需要访问此服务器时(就像在粘性会话中所做的那样),您实际上是在限制您的可伸缩性选项。您想要达到的一点是“您的任何免费负载平衡应用服务器”都可以处理此 Web 服务请求,如果我 再添加 1 个应用服务器,我应该能够处理 % 更多的用户 .

如果您想保持状态以传递身份验证令牌并在每个请求中获取服务以从数据存储中检索您的“状态”(最好是冗余和分区的,例如分布式的),这完全可以(并且个人推荐) +复制的键/值数据存储)。这就是 Amazon 使用 SimpleDb 和 Google 使用 BigTable 的方式。

Ebay 采用了一种稍微不同的方法,并将大多数客户端状态存储在一个 cookie 中,以便在每个请求中传递它。尽管它产生了更多的流量,但它仍然具有可扩展性,因为它们的任何服务器仍然可以处理请求。

如果您想要一个可扩展的数据存储,我建议您查看redis,它具有键/值数据存储无法比拟的速度和功能。

如果您想获得有关如何构建快速且可扩展的服务的好资料,还应该查看highscalability.com。

【讨论】:

这是一个非常好的点,在设计Web服务时不应该忽视。【参考方案2】:

您似乎将状态和身份验证等同起来。也许您习惯于在会话状态中存储用户名和密码?

这不是必需的,即使使用旧的 ASMX Web 服务也是如此。只需将您需要的任何信息传递给“登录”操作即可。该操作将被定义为返回一个“Authentication Ticket”标头。

所有其他需要身份验证的操作都需要这个“Authentication Ticket”标头。他们每个人都将检查标头以查看它是否代表一个有效的、经过身份验证的用户。如果是这样,那么他们将执行他们的任务。如果不是,那么它们将返回一个 SOAP 错误,指示需要进行身份验证。

不需要状态。只需确保可以在运行您的服务的任何服务器上验证身份验证票证(例如,在网络场中),就可以了。

【讨论】:

身份验证票的工作方式类似于会话 ID。那么我可以从这张票中获取经过身份验证的用户对象,还是必须在每次服务调用时发送执行服务的 user_id?我可能在这里弄错了,但我会认为这张票是一种状态,不是吗? 这将是您的门票 - 随心所欲。如果需要,您可以在票证中包含用户 ID ,或者在内存中保存一个完整的 Dictionary,从数据库中加载,并在每次调用时为您的票证编制索引。 您所说的这个票证系统似乎不存在于 JAX-WS 上。看起来他们建议您获取底层 HttpSession,这在概念上与此票证系统相同。但是您必须假设(足够公平)您将使用 HTTP 来提供服务。 @Sergio:他们建议您获取特定于平台的东西?他们是否计划让您通过网络发送它?为什么要限制自己使用 HTTP? JAX-WS 的其他选项是什么?自己实施票务系统?一点也不难,但如果我确定我会像大多数 WS 那样使用 HTTP,为什么还要重新实现 HttpSession? (随意提出你的论点,这场辩论对我来说是一个学习过程,而不是竞争)【参考方案3】:

我认为对于 Flex 客户端,状态会从服务中移出并进入客户端层。保持服务无状态,让客户端维护所需的状态。服务保持简单,客户可以随意将它们混合在一起。

【讨论】:

【参考方案4】:

理想的网络服务(和网站)应该是无状态的。

不幸的是,这需要经过深思熟虑的问题域和清晰的关注点分离。

我发现在实践中大多数现实世界的网站依赖于状态,即使这限制了它们的可扩展性。

我还发现许多现实世界的网络服务也依赖于状态。

最终,“正确”的决定是针对特定问题的决定,因此编写一个依赖于状态的 Web 服务并在以后如果可伸缩性成为问题时对其进行重构可能是可以的。

【讨论】:

感谢 John 提供的真实体验反馈。所以我的问题是:如果你决定你需要状态,你应该使用什么。 1) 数据库,2) 客户端状态,3) 会话,4) 持久服务。有没有简单的方法来使用 3 ??? 4 工作吗???我开始同意 Jason 的观点,即数据库是最佳选择。 :-)【参考方案5】:

高度依赖于服务是面向单一事务的(比如获取股票报价),还是服务的输出依赖于特定客户端跨多个事务提供的数据(在这种情况下,必须保持状态。)

就可扩展性问题而言,将状态存储在数据库中实际上并不是一个糟糕的方法(事实上,如果您要跨服务器场对服务进行负载平衡,这可能是唯一的方法。)

【讨论】:

您必须不时清理数据库,但您可能是对的。看起来很丑,但实际上并没有那么糟糕。 :-) 如果您有一个会话,另一个选择是会话集群,或者您可以接受这样一个事实,即如果您的服务器出现故障,您必须重新开始(假设您有一个智能负载均衡器,可以将来自用户的请求发送到同一台服务器,现在我认为这并不难)

以上是关于有状态的 Web 服务有多好和/或有多必要?的主要内容,如果未能解决你的问题,请参考以下文章

HTTP2.0:小鲜肉,你到底有多好?

有状态与无状态 Web 服务

对于无状态的前端客户端,这个 JWT 逻辑有多安全?

保护有状态的 Web 服务

REST Web 服务是有状态的吗?

为啥使用有状态的 Web 服务是不好的编程,为啥会被允许?