Todos los productos
Search
Centro de documentos

ApsaraMQ for RocketMQ:Envío y consumo de mensajes programados o diferidos

Última actualización: Sep 04, 2026

Este tema proporciona código de ejemplo en Java para enviar y consumir mensajes programados o diferidos mediante el SDK de cliente HTTP de ApsaraMQ for RocketMQ.

Diferencias entre mensajes programados y diferidos

Los mensajes programados y los mensajes diferidos son la misma función en la API. Ambos utilizan el método setStartDeliverTime para aplazar la entrega. La única diferencia radica en cómo se calcula la marca de tiempo:

Tipo

Cómo establecer la hora de entrega

Ejemplo

Mensaje diferido

Hora actual + desplazamiento

System.currentTimeMillis() + 10 * 1000 (retraso de 10 segundos)

Mensaje programado

Marca de tiempo Unix absoluta en milisegundos

1654770600000 (2022-06-09 18:30:00)

El broker retiene cada mensaje hasta su hora de entrega especificada y luego lo libera para su consumo. Esta es una configuración por mensaje, por lo que cada uno puede tener su propia hora de entrega.

Para obtener más información, consulte Mensajes programados y mensajes diferidos.

Requisitos previos

Antes de empezar, asegúrese de cumplir con a continuación:

Importante

Cada topic admite solo un tipo de mensaje. No reutilice un topic configurado para mensajes normales si desea enviar mensajes programados o diferidos.

Envío de mensajes programados o diferidos

Todos los mensajes de este ejemplo usan setStartDeliverTime para aplazar la entrega durante 10 segundos. Para enviar un mensaje programado, reemplace el desplazamiento relativo con una marca de tiempo Unix absoluta en milisegundos (por ejemplo, 1654770600000 para 2022-06-09 18:30:00).

import com.aliyun.mq.http.MQClient;
import com.aliyun.mq.http.MQProducer;
import com.aliyun.mq.http.model.TopicMessage;

import java.util.Date;

public class Producer {

    public static void main(String[] args) {
        MQClient mqClient = new MQClient(
                // HTTP endpoint. Find this on the Instance Details page, in the
                // Endpoints tab under Basic Information.
                "<your-http-endpoint>",
                // Load credentials from environment variables to avoid hardcoding secrets.
                System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),
                System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")
        );

        final String topic = "<your-topic>";
        // If the instance has a namespace, specify the instance ID.
        // If it does not have a namespace, set this to null or "".
        final String instanceId = "<your-instance-id>";

        MQProducer producer;
        if (instanceId != null && instanceId != "") {
            producer = mqClient.getProducer(instanceId, topic);
        } else {
            producer = mqClient.getProducer(topic);
        }

        try {
            for (int i = 0; i < 4; i++) {
                TopicMessage pubMsg = new TopicMessage(
                        "hello mq!".getBytes(),   // Message body
                        "A"                        // Message tag
                );
                pubMsg.getProperties().put("a", String.valueOf(i));  // Custom property
                pubMsg.setMessageKey("MessageKey");

                // Defer delivery by 10 seconds.
                // For a scheduled message, use an absolute timestamp instead,
                // e.g., pubMsg.setStartDeliverTime(1654770600000L);
                pubMsg.setStartDeliverTime(System.currentTimeMillis() + 10 * 1000);

                TopicMessage pubResultMsg = producer.publishMessage(pubMsg);

                System.out.println(new Date() + " Send mq message success."
                        + " Topic is:" + topic
                        + ", msgId is: " + pubResultMsg.getMessageId()
                        + ", bodyMD5 is: " + pubResultMsg.getMessageBodyMD5());
            }
        } catch (Throwable e) {
            System.out.println(new Date() + " Send mq message failed. Topic is:" + topic);
            e.printStackTrace();
        }

        mqClient.close();
    }
}

Reemplace a continuación marcadores de posición con sus valores reales:

Marcador de posición

Descripción

Dónde encontrarlo

<your-http-endpoint>

Endpoint HTTP

Página Instance Details > pestaña Endpoints > HTTP Endpoint

<your-topic>

Nombre del topic

Consola de ApsaraMQ for RocketMQ > Topics

<your-instance-id>

ID de instancia, o null si la instancia no tiene namespace

Página Instance Details > Basic Information

Consumo de mensajes programados o diferidos

Consuma los mensajes programados y diferidos de la misma manera que los mensajes normales. El broker los retiene hasta la hora de entrega y luego los libera para su consumo.

El siguiente ejemplo utiliza sondeo largo (long polling) para consumir mensajes y enviar confirmaciones (ACK) al broker.

import com.aliyun.mq.http.MQClient;
import com.aliyun.mq.http.MQConsumer;
import com.aliyun.mq.http.common.AckMessageException;
import com.aliyun.mq.http.model.Message;

import java.util.ArrayList;
import java.util.List;

public class Consumer {

    public static void main(String[] args) {
        MQClient mqClient = new MQClient(
                // HTTP endpoint. Find this on the Instance Details page, in the
                // Endpoints tab under Basic Information.
                "<your-http-endpoint>",
                // The AccessKey ID for authentication.
                "${ACCESS_KEY}",
                // The AccessKey secret for authentication.
                "${SECRET_KEY}"
        );

        final String topic = "<your-topic>";
        final String groupId = "<your-group-id>";
        // If the instance has a namespace, specify the instance ID.
        // If it does not have a namespace, set this to null or "".
        final String instanceId = "<your-instance-id>";

        final MQConsumer consumer;
        if (instanceId != null && instanceId != "") {
            consumer = mqClient.getConsumer(instanceId, topic, groupId, null);
        } else {
            consumer = mqClient.getConsumer(topic, groupId);
        }

        // Consume messages in a loop. For production use, run multiple threads
        // to consume messages concurrently.
        do {
            List<Message> messages = null;

            try {
                // Long polling: wait up to 3 seconds for new messages.
                // - First parameter: max messages per batch (max: 16).
                // - Second parameter: long polling timeout in seconds (max: 30).
                messages = consumer.consumeMessage(3, 3);
            } catch (Throwable e) {
                e.printStackTrace();
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            }

            if (messages == null || messages.isEmpty()) {
                System.out.println(Thread.currentThread().getName()
                        + ": no new message, continue!");
                continue;
            }

            // Process messages
            for (Message message : messages) {
                System.out.println("Receive message: " + message);
            }

            // ACK consumed messages. If the broker does not receive an ACK
            // before the retry interval elapses, the message is redelivered.
            {
                List<String> handles = new ArrayList<String>();
                for (Message message : messages) {
                    handles.add(message.getReceiptHandle());
                }

                try {
                    consumer.ackMessage(handles);
                } catch (Throwable e) {
                    if (e instanceof AckMessageException) {
                        AckMessageException errors = (AckMessageException) e;
                        System.out.println("Ack message fail, requestId is:"
                                + errors.getRequestId() + ", fail handles:");
                        if (errors.getErrorMessages() != null) {
                            for (String errorHandle : errors.getErrorMessages().keySet()) {
                                System.out.println("Handle:" + errorHandle
                                        + ", ErrorCode:" + errors.getErrorMessages().get(errorHandle).getErrorCode()
                                        + ", ErrorMsg:" + errors.getErrorMessages().get(errorHandle).getErrorMessage());
                            }
                        }
                        continue;
                    }
                    e.printStackTrace();
                }
            }
        } while (true);
    }
}

Reemplace a continuación marcadores de posición con sus valores reales:

Marcador de posición

Descripción

Dónde encontrarlo

<your-http-endpoint>

Endpoint HTTP

Página Instance Details > pestaña Endpoints > HTTP Endpoint

${ACCESS_KEY}

AccessKey ID para autenticación

Consulte Crear un par de AccessKey

${SECRET_KEY}

AccessKey secret para autenticación

Consulte Crear un par de AccessKey

<your-topic>

Nombre del topic

Consola de ApsaraMQ for RocketMQ > Topics

<your-group-id>

ID del grupo de consumidores

Consola de ApsaraMQ for RocketMQ > Groups

<your-instance-id>

ID de instancia, o null si la instancia no tiene namespace

Página Instance Details > Basic Information

Pasos siguientes