消息排序
消息排序对某些异步消息传递应用程序很重要;即,按生产者发送消息的顺序使用消息很重要。如果此类型的消息排序对您的应用程序很重要,那么您的设计必须考虑这一点。
例如,处理座位预订的消息传递应用程序必须具有生产者组件和使用者组件。使用者预订座位时,生产者组件向使用者组件发送消息。如果使用者取消预订,那么生产者(或者可能是另一生产者)发送第二个消息。通常,使用者组件必须先处理第一个消息(该消息预订座位),然后才处理第二个消息(该消息取消预订)。
某些应用程序使用同步(请求/响应)模式,在此模式下,生产者等待每个消息响应后才发送下一条消息。在此类型的应用程序中,使用者控制接收消息的顺序,并且可确保此顺序与生产者发送消息的顺序相同。其他应用程序使用异步(发后不理)模式,在此模式下,生产者不必等待响应就发送消息。即使是对于此类型的应用程序,通常也会保留顺序;即,使用者可能期望按生产者发送消息的顺序接收消息,特别是在发送连续消息之间的时间很长时。但是,您的设计必须考虑可能破坏此顺序的因素。
如果应用程序发送具有不同优先级的消息(高优先级消息可能超前于低优先级消息),或者应用程序通过指定消息选择器来显式接收第一个消息以外的消息,那么消息顺序将被破坏。并行处理和错误或异常处理也会影响消息排序。
并行处理
- 多目标
- 如果生产者向一个目标发送一个消息,然后向另一目标发送第二个消息,那么第二个消息可能会比第一个消息先到达其目标。即使生产者在同一事务中发送两个消息时也有可能发生这种情况(该事务确保两个消息全部发送失败或全部完成;但它不会确保传送顺序)。如果应用程序将这种情况视为问题,那么应避免对该应用程序使用多个目标。
- 多个生产者
- 如果一个生产者向一个目标发送一个消息,然后第二个生产者向同一目标发送第二个消息,那么第二个消息可能会比第一个消息先到达目标。即使第二个生产者与第一个生产者同步,例如,等待第一个生产者在发送其消息前发出信号(第二个消息),也可能会发生此情况。即使生产者是事务性的(事务完成并不意味着消息在目标上 - 服务集成可先完成事务,稍后再传送消息),也可能会发生此情况。如果这应用程序将这种情况视为问题,那么应避免对该应用程序使用多个生产者。同样,应避免使用运行多个并行线程的单个生产者。
- 多个使用者
- 两个消息到达有多个使用者的队列类型目标时,可能会出现以下情况:一个使用者接收第一个消息,另一个使用者接收第二个消息。如果使用者可以并行方式运行,那么接收第二个消息的使用者可能会比接收第一个消息的使用者先处理其消息。而且,如果一个使用者通过事务接收消息,然后回滚该事务,那么消息会返回至目标,该目标中的另一使用者可接收该消息;同时,另一使用者可能已接收并处理其他(以后的)消息。如果应用程序将其中任一情况视为问题,那么应避免对该应用程序使用多个使用者。同样,不应允许对每个端点使用多个并行消息驱动的 Bean (MDB) 调用(请参阅 为缺省消息传递提供程序配置 MDB 调速)。或者,考虑使用严格的消息排序,请参阅总线目标的严格消息排序。
- 集群和分区目标
- 对带有多个消息传递引擎的集群总线成员指定队列类型目标时,每个消息传递引擎都包含该目标的一个分区(即,其中一个目标队列点);服务集成可将该目标的不同消息传送至不同分区。此队列类型目标配置可提供高级可用性、可伸缩性和负载均衡,但它通常不适用于消息排序很重要的应用程序。服务集成不会保证发送至同一目标的不同分区的消息排序。而且,消息传递引擎可能会在它所包含的目标分区上有多个消息时失效;直到该消息传递引擎重新启动,这些消息才对使用者可用。但是,服务集成可继续将较新消息传送至其他分区(在其他消息传递引擎中),并且使用者可先接收并处理这些较新消息,然后再处理失效消息传递引擎分区上的较旧消息。与队列目标分摊工作负载给出有关此类型配置的更多详细信息,同时说明如何使用“消息亲缘关系”选项,此选项可帮助在集群中的单个生产者和单个使用者之间保持消息排序(但是集群在另一服务集成总线中时不会保持消息排序)。
- 发布和预订
- 对于发布/预订消息传递,服务集成不会保证预订的不同实例接收到的消息的排序,包括“共享持久预订”属性设置为允许共享时创建的持久预订的不同实例。
错误和异常情况
- 服务质量
- 消息的服务质量确定错误和异常情况如何影响消息传送(请参阅消息可靠性级别 - JMS 传送方式及服务集成服务质量)。根据服务质量,错误或异常情况可能导致服务集成以可靠方式(正好传送一次)或以不太可靠的方式(传送多次,或完全不传送)传送消息。例如,对于快速非持久服务质量,消息序列可能会在发生故障后重新传送;但是,它们的底层顺序始终不变,以便这些消息可按以下顺序到达:1,2,3,2,3,4。更普遍的是,服务集成不会保证使用不同服务质量发送的不同消息的排序。如果应用程序将这种情况视为问题,那么一定要选择适当的服务质量并避免将不同的消息服务质量混合到一起发送至同一目标。
- 异常目标
- 在某些故障方案中,服务集成可将消息传送至异常目标,或者将消息传送至某个目标,然后将该消息传输至异常目标。服务集成不会保证它发送或传输至异常目标的消息的排序。如果应用程序将这种情况视为问题,那么可配置目标以使它不使用异常目标(请参阅异常目标)。如果生产者和目标位于不同总线中,那么可在这些总线之间配置链路,以便没有异常目标(请参阅外部总线和为外部总线链路配置异常目标处理)。
- 事务回滚
- 消息驱动的 Bean (MDB) 的激活规范可指定失败消息重试之间的延迟。此延迟给出时间以便让回滚在同一消息再次驱动 MDB 之前进行恢复。但是,虽然消息以此方式延迟,但另一(以后的)消息可能会驱动 MDB(请参阅防止 MDB 应用程序发生系统资源问题)。如果应用程序将这种情况视为问题,那么应考虑将最大连续失败次数限制为 1(请参阅JMS 激活规范 [设置])或者考虑使用严格的消息排序(请参阅总线目标的严格消息排序)。
- 解决不确定事务
- 在进行两阶段落实处理期间,当 JMS 发送或接收操作处于不确定状态时,应用程序可能会失败。如果发生这种情况,那么应用程序可能会在解决不确定状态之前重新启动,因此,在应用程序重新启动时会有一条或多条消息“不可视”,但稍后变得“可视”。目标上的其他消息不受影响。消费应用程序可接收消息(称为消息 2),此消息在逻辑上位于“不可视”消息(称为消息 1)之后;稍后,解决不确定事务后,应用程序会接收到先前“不可视”的消息(消息 1)。这样一来,应用程序可能会按错误顺序接收和处理消息。如果这应用程序将这种情况视为问题,那么请考虑使用严格的消息排序,请参阅总线目标的严格消息排序。