Todos los productos
Search
Centro de documentos

ApsaraMQ for RocketMQ:Envío y recepción de mensajes ordenados

Última actualización: Sep 04, 2026

Los mensajes ordenados se entregan y consumen en un orden estricto de primero en entrar, primero en salir (FIFO). Este tema proporciona código de ejemplo en Java para enviar y recibir mensajes ordenados mediante TCP con el SDK de Apache RocketMQ para Java.

Funcionamiento de los mensajes ordenados

Los mensajes ordenados se dividen en particiones mediante una sharding key. Cada sharding key se asigna a una partición dedicada, y los mensajes dentro de esa partición se entregan en el mismo orden en que se enviaron.

Tres reglas rigen este comportamiento:

  1. Orden dentro de una partición: los mensajes que comparten la misma sharding key siempre se entregan en orden FIFO.

  2. Sin orden entre particiones: los mensajes con distintas sharding keys pueden llegar en cualquier orden relativo entre sí.

  3. La sharding key es obligatoria: todo mensaje ordenado debe incluir una sharding key. Esta clave es independiente de la clave general del mensaje que se usa para búsquedas.

Utilice las sharding keys para modelar los requisitos de orden de su negocio. Por ejemplo, establezca la sharding key como un ID de pedido para que todos los mensajes del mismo pedido se procesen de forma secuencial, mientras que los mensajes de distintos pedidos se procesen en paralelo.

Para obtener más información sobre la semántica y las restricciones de ordenamiento, consulte Ordered messages.

Requisitos previos

Antes de empezar, asegúrese de contar con lo siguiente:

Nota

Si es nuevo en ApsaraMQ for RocketMQ, comience con el demo project para configurar un proyecto funcional antes de enviar y recibir mensajes.

Envío de mensajes ordenados

Garantía de orden

El broker determina el orden de los mensajes según la secuencia en la que el remitente utiliza un único producer o hilo para enviarlos. Si varios producers o hilos envían mensajes de forma concurrente, el broker los ordena por hora de llegada, lo cual puede diferir del orden de negocio previsto.

Código de ejemplo

Reemplace los siguientes marcadores de posición con sus valores reales:

Marcador de posición

Descripción

Ejemplo

<your-group-id>

Group ID creado en la consola de ApsaraMQ for RocketMQ

GID_order_group

<your-access-key>

AccessKey ID para autenticación

LTAI5tXxx

<your-secret-key>

AccessKey secret para autenticación

xXxXxXx

<your-tcp-endpoint>

Endpoint TCP de la sección TCP Endpoint en la página Instance Details

http://MQ_INST_xxx.mq-internet-access.mq-internet.aliyuncs.com:80

Para ver el código completo, consulte el repositorio de código de ApsaraMQ for RocketMQ.

package com.aliyun.openservices.ons.example.order;

import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.ONSFactory;
import com.aliyun.openservices.ons.api.PropertyKeyConst;
import com.aliyun.openservices.ons.api.SendResult;
import com.aliyun.openservices.ons.api.order.OrderProducer;

import java.util.Date;
import java.util.Properties;

public class ProducerClient {

    public static void main(String[] args) {
        Properties properties = new Properties();
        // Group ID created in the ApsaraMQ for RocketMQ console.
        properties.put(PropertyKeyConst.GROUP_ID, "<your-group-id>");
        // AccessKey ID for authentication.
        properties.put(PropertyKeyConst.AccessKey, "<your-access-key>");
        // AccessKey secret for authentication.
        properties.put(PropertyKeyConst.SecretKey, "<your-secret-key>");
        // TCP endpoint from the Instance Details page in the ApsaraMQ for RocketMQ console.
        properties.put(PropertyKeyConst.NAMESRV_ADDR, "<your-tcp-endpoint>");

        OrderProducer producer = ONSFactory.createOrderProducer(properties);
        // Call start() once before sending any messages.
        producer.start();

        for (int i = 0; i < 1000; i++) {
            String orderId = "biz_" + i % 10;
            Message msg = new Message(
                    // Topic for ordered messages.
                    "Order_global_topic",
                    // Tag for filtering on the broker side.
                    "TagA",
                    // Message body in binary format.
                    // Producer and consumer must agree on serialization and deserialization.
                    "send order global msg".getBytes()
            );
            // Message key -- a business identifier, ideally globally unique.
            // Use this key to look up the message in the ApsaraMQ for RocketMQ console.
            msg.setKey(orderId);

            // Sharding key -- determines the partition for ordered delivery.
            // Messages with the same sharding key are delivered in FIFO order.
            String shardingKey = String.valueOf(orderId);
            try {
                SendResult sendResult = producer.send(msg, shardingKey);
                if (sendResult != null) {
                    System.out.println(new Date() + " Send mq message success. Topic is:" + msg.getTopic() + " msgId is: " + sendResult.getMessageId());
                }
            } catch (Exception e) {
                // Handle failure: retry or persist the message for later resend.
                System.out.println(new Date() + " Send mq message failed. Topic is:" + msg.getTopic());
                e.printStackTrace();
            }
        }
        // Shut down the producer before exiting.
        // Skip this if the producer sends messages frequently.
        producer.shutdown();
    }

}

Recepción de mensajes ordenados

Comportamiento de reintentos

Cuando falla el consumo de un mensaje ordenado, el broker bloquea todos los mensajes subsiguientes en la misma partición hasta que el mensaje actual se procese correctamente o alcance el número máximo de reintentos. Este comportamiento de bloqueo preserva el orden FIFO, pero puede retrasar el procesamiento de otros mensajes en la partición.

Dos parámetros controlan el comportamiento de los reintentos:

Parámetro

Descripción

Valores válidos

SuspendTimeMillis

Tiempo de espera en milisegundos entre reintentos para un mensaje ordenado fallido

10 -- 30,000

MaxReconsumeTimes

Número máximo de intentos de reintento antes de omitir el mensaje

Entero (por ejemplo, 20)

Establezca estos valores según su tolerancia a los retrasos en el procesamiento. Un valor menor de SuspendTimeMillis permite reintentar más rápido, pero incrementa la carga del broker. Un valor menor de MaxReconsumeTimes desbloquea la partición antes, pero podría omitir mensajes que habrían tenido éxito con más reintentos.

Código de ejemplo

El siguiente código de ejemplo utiliza los mismos marcadores de posición que el ejemplo del producer. Reemplácelos con sus valores reales antes de ejecutar el código.

package com.aliyun.openservices.ons.example.order;

import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.ONSFactory;
import com.aliyun.openservices.ons.api.PropertyKeyConst;
import com.aliyun.openservices.ons.api.order.ConsumeOrderContext;
import com.aliyun.openservices.ons.api.order.MessageOrderListener;
import com.aliyun.openservices.ons.api.order.OrderAction;
import com.aliyun.openservices.ons.api.order.OrderConsumer;

import java.util.Properties;

public class ConsumerClient {

    public static void main(String[] args) {
        Properties properties = new Properties();
        // Consumer group ID created in the ApsaraMQ for RocketMQ console.
        properties.put(PropertyKeyConst.GROUP_ID, "<your-group-id>");
        // AccessKey ID for authentication.
        properties.put(PropertyKeyConst.AccessKey, "<your-access-key>");
        // AccessKey secret for authentication.
        properties.put(PropertyKeyConst.SecretKey, "<your-secret-key>");
        // TCP endpoint from the Instance Details page in the ApsaraMQ for RocketMQ console.
        properties.put(PropertyKeyConst.NAMESRV_ADDR, "<your-tcp-endpoint>");
        // Wait time (ms) before retrying a failed ordered message. Valid values: 10 to 30,000.
        properties.put(PropertyKeyConst.SuspendTimeMillis, "100");
        // Maximum retry attempts for a failed message.
        properties.put(PropertyKeyConst.MaxReconsumeTimes, "20");

        OrderConsumer consumer = ONSFactory.createOrderedConsumer(properties);

        consumer.subscribe(
                // Topic to subscribe to.
                "Order_global_topic",
                // Tag filter expression:
                //   "*"                       -- subscribe to all tags
                //   "TagA || TagB || TagC"     -- subscribe to TagA, TagB, or TagC only
                "*",
                new MessageOrderListener() {
                    /**
                     * Return OrderAction.Success after processing the message.
                     * Return OrderAction.Suspend if processing fails or throws
                     * an exception -- the broker will retry after SuspendTimeMillis.
                     */
                    @Override
                    public OrderAction consume(Message message, ConsumeOrderContext context) {
                        System.out.println(message);
                        return OrderAction.Success;
                    }
                });

        // Call start() once to begin consuming.
        consumer.start();
    }
}

Siguientes pasos