指南:服务的状态管理
在本指南中,将从有状态服务和无状态服务对性能和健壮性的影响的角度,以及交互何时需要事务方法的角度对这两类服务的使用加以探讨。可以认为 SOA 环境中状态管理的概念分为三个主要类别:事务状态、安全性状态和功能状态。
关系
相关元素
主要描述

简介

有状态组件和无状态组件的概念在开发分布式应用程序和系统时尤其重要,虽然它最近有变为通用词汇的趋势。 从本质上看,此概念就是:如果两个组件或服务正在进行通信,并且在与客户机进行对话期间,某些状态由服务器组件管理,则服务器组件发生崩溃(或网络故障)意味着客户机无法完成对话而必须重新启动。 另外,它使将客户机请求重定向到组件集内某个组件变得更困难,除非该组件集共享用于存放对话状态的某些公共库。 这已成为 Web 应用程序开发中的一个公认问题,在这种情况下,需小心管理会话的状态以尽可能避免被客户机、对话本身(负责在每个消息中传递状态)或仔细设计的有状态服务器端组件改变其状态。 例如,最常见的有状态 Web 交互例子就是购物车。 用户希望在自己暂时离开计算机时保留其购物车,但是当有 100,000 个并发用户时,如何实现这一要求呢?

现在,并不能说有状态组件天生就很糟糕,而只是表示它们在性能和灵活性方面可能存在不足之处,除非小心地对它们进行管理和开发以提高健壮性。 实际上,所有的业务应用程序都包含天生就用于管理或代表实体的服务,且这些实体与生俱来就有状态或包含必须按特定逻辑顺序访问的服务。 实际上,J2EE 体系结构定义了独立的无状态会话 bean 和有状态会话 bean,这是为了明确地表示这类问题,并对有状态组件定义了特定的限制。 因此我们对有状态服务以及无法从一开始就避免它们的原因进行简单的分类。 由于以下原因之一,服务可能必须是有状态的:

服务持有的状态代表客户机;购物车就是这种情况的例子。由于某些原因,某些数据在调用之间、客户机和服务之间必须保留,这些数据是对话的一部分,因此无论在何种情况下,它都能将客户机绑定到指定的服务器资源。

服务管理有状态的资源;在此情况下,服务将管理一组资源或实体,其中每一个都有状态。 例如,客户订单有状态,网络交换机有状态等。 因此,用于管理该对象(通过结束或延迟订单,或重新引导交换机)的服务接口所更改的是特定实体的状态。

服务具备有状态协议,在此情况下,服务对自己提供的操作具有某些逻辑排序。 例如,它具有 login()、dostuff() 和 logoff() 操作,我们能够推断您不能在未调用 login() 操作的情况下调用 dostuff() 或 logoff() 操作。

另一种存在于许多组件体系结构中,但并不适用于服务体系结构的状态形式是事务状态这一概念。 在组件体系结构中,它可以表示组件上的 get() 和 update() 方法,这些方法可由客户机在其创建和维护的事务范围内调用。 假设该 update() 方法会更改某些底层事务存储库。这几乎始终需要中间件平台的干预才能协调事务并确保要求事务的方法由客户机通过打开的事务调用。 服务并不需要遵循以下模式:许多服务调用使用传统的两阶段落实中的事务。虽然现在正在为服务调用之间的事务开发标准,但它们遵循一个完全不同的范例(补偿)并且由中间件平台分别支持。

前面已提示过,对于成功的有状态服务开发而言,最明显的技术就是将服务状态具体化(externalize),从而不仅明确地确定服务具有状态,还明确地确定该状态可指定为服务规范的组成部分。 下面会就此问题对两类有状态服务进行讨论。

因为将在现有中间件平台(例如 J2EE 或 Microsoft .NET)上开发大多数软件服务,所以那些平台体系结构内所述的实施技术有助于状态管理。 因此,本指南的重点在于针对有状态服务的特定类的设计技术。还有一点值得注意,就是这决不是一个新的问题领域。 许多年来,在大型机开发中,带有绿屏(实际上是 3270 终端)客户机的 CICS(IBM 客户信息控制系统)中会话式和非会话式事务的开发已被开发人员,设计人员和架构设计师了解和描述。

持久对话状态

最简单的建议就是首先避免这种情况。如果设计需要对服务和其使用者之间进行对话时的状态进行管理,则最好尝试确定是否可采用其他方法。 如果没有,请通过传递服务和其使用者之间所有需要的状态数据,以及组成整个对话的所有消息将此状态具体化。 此方法可能意味着消息的大小显著增加,但现在服务本身则完全是无状态的。 另一种方法是在每个消息中包含一个对话标识,并将所有的对话状态保存在诸如数据库之类的永久存储库中。 虽然这会对服务器端的性能带来了明显的影响,但这是为了用较少的消息来提高网络和客户机性能。

使这些服务无状态的一个主要目的是为了能够提供一组一致的服务,这些服务能够使用负载均衡技术分配客户机,以此为任何请求提供服务。 如果所有的状态都完全具体化或保存在通用存储库中,则可实现此负载均衡。

管理有状态资源

在此情况下,我们着眼于对具有显式状态的资源本身进行管理。实际上,该状态是资源本身的一个重要方面。 可能我们可以使用状态机来描述上述的资源、客户订单或网络交换机的状态,不仅描述有效状态,还描述服务所提供的操作如何影响底层资源的状态。

无论我们如何完成此描述,此状态都是资源的一个内在部分,这一点很重要。 但是,它可能不在代表它的信息模型中显式地表达。当我们管理任何一组实体时,都必须能够确定所操作的任何个别资源,无论它们是否也具有显式标识,这一点也非常重要。

请注意,当服务代表对物理实体(例如网络交换机或流程控制元素)状态的访问或查询时,不能考虑将该实体的状态具体化。 阀门的状态只能通过查询该阀门才能获知。 虽然我们可以构造并回复一个描述阀门当前状态的消息,但是阀门的状态并非一成不变。 阀门的状态在传输或处理此消息时可能就已改变。

在 Web service 领域,有一组称为“Web 服务资源框架”(WSRF)的新兴标准,这组标准讨论了有状态服务的模式和状态编码方法,尤其是在服务代表有状态资源的管理时。 关于更多信息,请参阅 IBM WS-ResourceFramework 站点

有状态服务规范

上面提到的例子涉及了一个服务,该服务对自己提供的操作进行了特定的逻辑排序。许多服务将提供这种形式的接口。 在某些情况下,这与有状态资源相关,但操作顺序基于受管资源状态的情况除外。 在后一种情况下,操作顺序基于对话本身。 以下例子展示了一个具有某些关联协议的服务规范,首先展示结构规范,然后展示描述行为规范的状态机。

文本内容中所述的图。

采购订单的状态可以是以下状态中的一种:{打开, 已取消,已实现,已关闭},并且该状态会根据上述规范提供的操作而变更。 我们还指出当自我移交处于“打开”状态时,我们执行“订单变更”操作,该操作会发送变更通知。

文本内容中所述的图。

许多情况下,在单一的业务和技术范围内开发所有服务,此时可能不会开发详细的行为规范,或者将以文本形式进行不太正式的描述。 如果服务显现在此范围之外,例如显现在分区之间,则此类服务代表分区间交互的逻辑规范,且应当更加详细地进行开发。 另外,当希望频繁复用服务时,详细的规范可使服务使用者能够更有效和高效地复用这些服务。