Todos os produtos
Search
Central de documentação

ApsaraMQ for RocketMQ:Send and consume scheduled or delayed messages

Última atualização: Jun 27, 2026

Este tópico fornece exemplos de código Java para enviar e consumir mensagens agendadas ou atrasadas usando o SDK de cliente HTTP do ApsaraMQ for RocketMQ.

Mensagens agendadas versus atrasadas

No nível da API, mensagens agendadas e atrasadas são o mesmo recurso. Ambas usam o método setStartDeliverTime para adiar a entrega. A única diferença reside no cálculo do timestamp:

Tipo

Como definir o horário de entrega

Exemplo

Mensagem atrasada

Hora atual + deslocamento

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

Mensagem agendada

Timestamp Unix absoluto em milissegundos

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

O broker retém cada mensagem até o horário de entrega especificado e depois a libera para consumo. Essa configuração é por mensagem, portanto cada uma pode ter seu próprio horário de entrega.

Para mais informações, consulte Mensagens agendadas e mensagens atrasadas.

Pré-requisitos

Antes de começar, verifique se você já:

Importante

Cada tópico aceita apenas um tipo de mensagem. Não reutilize um tópico configurado para mensagens normais no envio de mensagens agendadas ou atrasadas.

Enviar mensagens agendadas ou atrasadas

Neste exemplo, todas as mensagens usam setStartDeliverTime para adiar a entrega em 10 segundos. Para enviar uma mensagem agendada, substitua o deslocamento relativo por um timestamp Unix absoluto em milissegundos (por exemplo, 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();
    }
}

Substitua os espaços reservados abaixo pelos valores reais:

Espaço reservado

Descrição

Onde encontrar

<your-http-endpoint>

Endpoint HTTP

Página Instance Details > aba Endpoints > HTTP Endpoint

<your-topic>

Nome do tópico

Console do ApsaraMQ for RocketMQ > Topics

<your-instance-id>

ID da instância ou null se a instância não tiver namespace

Página Instance Details > Basic Information

Consumir mensagens agendadas ou atrasadas

Consuma mensagens agendadas e atrasadas da mesma forma que as mensagens normais. O broker as retém até o horário de entrega e depois as libera para consumo.

O exemplo a seguir usa long polling para consumir mensagens e enviar confirmações (ACKs) ao 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);
    }
}

Preencha os espaços reservados abaixo com os valores correspondentes:

Espaço reservado

Descrição

Onde encontrar

<your-http-endpoint>

Endpoint HTTP

Página Instance Details > aba Endpoints > HTTP Endpoint

${ACCESS_KEY}

AccessKey ID para autenticação

Consulte Criar um par de AccessKey

${SECRET_KEY}

AccessKey secret para autenticação

Consulte Criar um par de AccessKey

<your-topic>

Nome do tópico

Console do ApsaraMQ for RocketMQ > Topics

<your-group-id>

ID do grupo de consumidores

Console do ApsaraMQ for RocketMQ > Groups

<your-instance-id>

ID da instância ou null caso a instância não tenha namespace

Página Instance Details > Basic Information

Próximos passos