If you want messages to be consumed in a specified period of time, you can use the delayed message feature provided by ApsaraMQ for RabbitMQ. ApsaraMQ for RabbitMQ natively supports the delayed message feature. Compared with open source RabbitMQ, ApsaraMQ for RabbitMQ provides a delayed message feature that is easier to use.
What is a delayed message?
A delayed message is a message that is consumed in a specific period of time after it is sent by a producer.
Common scenarios
Delayed messages can be used in the following scenarios:
A time window between message production and consumption is required. For example, when an order is created on an e-commerce platform, a producer sends a delayed message to the ApsaraMQ for RabbitMQ broker. The message is used to confirm with a consumer whether the order is paid within a required period of time. The ApsaraMQ for RabbitMQ broker delivers the message to the consumer 30 minutes after the broker receives the message. After the consumer receives the message, the consumer checks whether the payment is complete. If the payment is not complete, the order is closed. Otherwise, the consumer ignores the message.
Messages are used to trigger scheduled tasks. For example, you can use a delayed message to trigger a scheduled task that sends notifications to users.
Rules for specifying delay periods
The value of the delay period for a message must be a non-negative integer. Unit: milliseconds.
If the delayed period that you specify for a delayed message is longer than the maximum delay period allowed for the message, the message is processed as a normal message and immediately delivered to the consumer. The maximum delay periods vary based on instance types. For more information, see Limits on clusters.
If you have specified time-to-live (TTL) for delayed messages, the actual message TTL is calculated by using the following formula:
Actual message TTL = min {Message-level TTL or queue-level TTL} + Delay period
. For more information, see Message TTL.
Comparison between delay message solutions
You can use ApsaraMQ for RabbitMQ to implement all delayed message solutions provided by open source RabbitMQ without the need to modify the code. The following table compares the delayed message solutions of ApsaraMQ for RabbitMQ and open source RabbitMQ.
Solution | Open source RabbitMQ | ApsaraMQ for RabbitMQ |
Dead-letter exchange + Queue-level TTL | Supported | Supported |
Dead-letter exchange + Message-level TTL | Supported | Supported |
Supported | Supported | |
Not supported | Supported |
Open source delayed message plug-in
To align with open source RabbitMQ, ApsaraMQ for RabbitMQ is compatible with the open source delayed message plug-in. You can use the plug-in to send and receive delayed messages without the need to install the plug-in. To use the open source delayed message plug-in, perform the following operations:
Declare an exchange of the
x-delayed-message
type and configure the x-delayed-type extended argument of the exchange to specify the routing rule. Sample code:Map<String, Object> args = new HashMap<String, Object>(); args.put("x-delayed-type", "direct"); channel.exchangeDeclare("ExchangeName", "x-delayed-message", true, false, args);
The following table describes the parameters in the previous code.
Parameter
Description
x-delayed-type
The exchange type. This parameter is used to specify the routing rule. Valid values:
direct
fanout
topic
headers
ExchangeName
The exchange name.
NoteMake sure that the declared exchange is created. For more information, see Manage exchanges.
x-delayed-message
The type of the exchange that is used to route delayed messages.
Send the delayed message. Add a key-value pair to the headers attribute of the message and specify that the message is sent to the exchange that is declared in the previous step. The key of the key-value pair is x-delay and the value is the number of milliseconds. Sample code:
byte[] messageBodyBytes = "delayed payload".getBytes("UTF-8"); Map<String, Object> headers = new HashMap<String, Object>(); headers.put("x-delay", 5000);// Specifies that the delay period for the message is 5,000 milliseconds. AMQP.BasicProperties.Builder props = new AMQP.BasicProperties.Builder().headers(headers); channel.basicPublish("ExchangeName", "", props.build(), messageBodyBytes);
Native delayed message solution
ApsaraMQ for RabbitMQ allows you to configure the delay attribute for a message to delay the message. The following section describes the data forwarding process of a native delayed message in ApsaraMQ for RabbitMQ:
A producer sends a message that is configured with the delay attribute to an exchange.
The exchange routes the message to a queue.
A consumer can consume the message from the queue only after the period of time that is specified by the delay attribute elapses.
Best practices of the native delayed message solution
Producer client
The native delayed message solution of ApsaraMQ for RabbitMQ is easy to use. You need only to configure the delay attribute for a message that is sent from the producer client.
The following sample code provides an example on how to send a delayed message in Java:
Map<String, Object> headers = new HashMap<>(); headers.put("delay", "5000");// Specifies that the delay period for the message is 5,000 milliseconds. AMQP.BasicProperties props = new AMQP.BasicProperties.Builder().messageId(UUID.randomUUID().toString()).headers(headers).build();
For information about sample code in other programming languages, see AMQP Demos.
Consumer client
To ensure that delayed messages can be immediately delivered to a consumer after the specified delay period is reached, we recommend that you use the
basic.consume
method in push mode instead of thebasic.get
method in pull mode to consume messages. ApsaraMQ for RabbitMQ stores messages in distributed mode. If you use thebasic.get
method in pull mode to obtain messages, you may not reach the node in which the messages are stored.
FAQ
Why is the actual delay period longer than the specified delay value?
The consumer client uses the basic.get method in pull mode to consume messages. Messages in ApsaraMQ for RabbitMQ are stored in clusters. When messages are routed to an ApsaraMQ for RabbitMQ broker by using the basic.get method in pull mode, the consumer may not pull messages from other brokers immediately after the specified delay period.