+

Search Tips   |   Advanced Search

Message ordering

Message ordering is important to some asynchronous messaging applications; that is, it is important to consume messages in the same order that the producer sends them. If this type of message ordering is important to the application, your design must take it into account.

For example, a messaging application that processes seat reservations might have producer components and a consumer component. A producer component sends a message to the consumer component when a customer reserves a seat. If the customer cancels the reservation then the producer (or possibly a different producer) sends a second message. Typically, the consumer component must process the first message (which reserves the seat) before it processes the second message (which cancels the reservation).

Some applications use a synchronous (request-response) pattern where the producer waits for a response to each message before it sends the next message. In this type of application, the consumer controls the order in which it receives the messages and can ensure that this is the same order as the producer or producers send them. Other applications use an asynchronous (fire and forget) pattern where the producer sends messages without waiting for responses. Even for this type of application, order is usually preserved; that is, a consumer can expect to receive messages in the same order as the producer or producers send them, especially when there is a significant time between sending consecutive messages. However your design must consider factors that can disrupt this order.

The order of messages is disrupted if the application sends messages with different priorities (higher priority messages can overtake lower priority messages) or if the application explicitly receives a message other than the first by specifying message selectors. Parallel processing and error or exception processing can also affect message ordering.


Parallel processing

Multiple destinations

When a producer sends a message to one destination and then sends a second message to a different destination, it is possible that the second message arrives at its destination before the first message arrives at its destination. This can happen even if the producer sends both messages within the same transaction (the transaction ensures that either both sends fail or both complete; it does not ensure the delivery order). If this is a problem for the application then avoid using more than one destination for that application.

Multiple producers

When one producer sends a message to a destination and then a second producer sends a second message to the same destination, it is possible that the second message arrives at the destination before the first message. This can happen even if the second producer synchronizes with the first producer, for example by waiting for a signal from the first producer before sending its message (the second message). It can also happen even if the producers are transactional (the fact that a transaction is complete does not mean that the message or messages are at the destination - service integration can complete a transaction first and deliver the message or messages later). If this is a problem for the application then avoid using more than one producer for that application. Similarly, avoid using a single producer which runs multiple parallel threads.

Multiple consumers

When two messages arrive at a queue-type destination where there are multiple consumers, it is possible that one consumer receives the first message and another receives the second. If the consumers can run in parallel then the consumer which receives the second message might process it before the consumer which receives the first message. Also, if one consumer receives a message transactionally and then rolls-back the transaction, the message returns to the destination where another consumer can receive it; meanwhile, that other consumer might already have received and processed other (later) messages. If either of these are a problem for the application then avoid using more than one consumer for that application. Similarly, do not allow multiple concurrent message-driven bean (MDB) invocations per endpoint (see Configure MDB throttling for the default messaging provider). Alternatively, consider using strict message ordering, see Strict message ordering for bus destinations.

Clustering and partitioned destinations

When a queue-type destination is assigned to a cluster bus member with more than one messaging engine then each messaging engine contains a partition of the destination (that is, one of the destination queue points); service integration can deliver different messages for that destination to different partitions. This queue-type destination configuration can provide advanced availability, scalability, and load balancing but it is not usually suitable for applications where message ordering is important. Service integration does not guarantee the ordering of messages sent to different partitions of the same destination. Also, a messaging engine can fail while there are messages on the destination partition that it contains; these messages are not available to consumers until the messaging engine restarts. However, service integration can continue delivering newer messages to other partitions (in other messaging engines) and consumers can receive and process these newer messages before the older messages on the failed messaging engine partition. Workload sharing with queue destinations gives more detail on this type of configuration, and also explains how we can use the Message affinity option which can help maintain message ordering between a single producer and a single consumer in a cluster (though not if the cluster is in a different service integration bus).

Publish and subscribe

For publish-subscribe messaging, service integration does not guarantee the ordering of messages received by different instances of a subscription, including separate instances of a durable subscription created with the Share Durable Subscriptions property set to permit sharing.


Errors and exception conditions

Quality of service

The quality of service for a message determines how error and exception conditions can affect the delivery of the message (see Message reliability levels - JMS delivery mode and service integration quality of service. Depending on the quality of service, an error or exception condition can cause service integration to deliver the message reliably (exactly once) or less reliably (more than once, or not at all). For example, with the express nonpersistent quality of service, it is possible for sequences of messages to be re-delivered after a failure; however, their underlying order is always maintained so that messages might arrive in the sequence: 1, 2, 3, 2, 3, 4. More generally, service integration does not guarantee the ordering of different messages sent with different qualities of service. If this is a problem for the application then be sure to select an appropriate quality of service and avoid mixing different qualities of service for messages to the same destination.

Exception destinations

Under certain failure scenarios, service integration can deliver a message to an exception destination or deliver a message to a destination and subsequently transfer the message to an exception destination. Service integration does not guarantee the ordering of messages it sends to or transfers to an exception destination. If this is a problem for the application then we can configure the destination so that it does not use an exception destination (see Exception destinations). If the producer and the destination are in different buses then we can configure the link or links between those buses to have no exception destination (see Foreign buses and Configure exception destination processing for a link to a foreign bus.

Transaction roll-back

The activation specification for a message-driven bean (MDB) can specify a delay between failing message retries. This delay allows time for the condition which causes the roll-back to recover before the same message drives the MDB again. However, while a message is delayed in this way, another (later) message can drive the MDB (see Protecting an MDB application from system resource problems). If this is a problem for the application then consider limiting the maximum sequential failures to one (see JMS activation specification [Settings] or consider using strict message ordering, see Strict message ordering for bus destinations.

Resolving indoubt transactions

During two-phase commit processing, an application can fail while a JMS send or receive operation is in an indoubt state. When this happens, it is possible for the application to restart before the indoubt state is resolved so that one or more messages are "invisible" when the application restarts but become "visible" later. Other messages on the destination are not affected. A consuming application can receive a message (say message 2) which is logically after an "invisible" message (say message 1); later, after the indoubt transaction is resolved, the application receives the previously "invisible" message (message 1). In this way, the application might receive and process messages in the wrong order. If this is a problem for the application then consider using strict message ordering, see Strict message ordering for bus destinations.


Related:

  • Strict message ordering for bus destinations
  • Workload sharing with queue destinations
  • Foreign buses
  • Message points