Todos os produtos
Search
Central de documentação

ApsaraMQ for RocketMQ:Send and receive scheduled and delayed messages

Última atualização: Jun 27, 2026

Este tópico fornece exemplos de código para enviar e receber mensagens agendadas e atrasadas com o SDK cliente HTTP do ApsaraMQ for RocketMQ para Go.

Mensagens agendadas e atrasadas

Mensagens agendadas e atrasadas controlam o momento da entrega aos consumidores:

  • Mensagem atrasada: entregue após um intervalo específico a partir do envio. Por exemplo, envie uma mensagem agora para entregá-la 30 segundos depois.

  • Mensagem agendada: entregue em um horário específico. Por exemplo, envie uma mensagem agora para entregá-la amanhã às 14:00.

Via HTTP, ambos os tipos usam o mesmo mecanismo: defina o campo StartDeliverTime com um timestamp Unix futuro em milissegundos. O broker retém a mensagem até esse timestamp e a entrega em seguida.

Para mais informações, consulte Scheduled messages and delayed messages.

Pré-requisitos

Antes de começar, verifique se você tem:

Como funciona

Mensagens agendadas e atrasadas usam o campo StartDeliverTime para controlar o tempo de entrega. Defina esse campo com um timestamp Unix em milissegundos correspondente ao momento em que o broker deve entregar a mensagem.

  • Entrega atrasada: adicione o atraso desejado (em milissegundos) ao horário atual.

      // Deliver 10 seconds from now
      msg.StartDeliverTime = time.Now().UTC().Unix() * 1000 + 10 * 1000
  • Entrega agendada: converta o horário-alvo de entrega para um timestamp Unix em milissegundos.

      // Deliver at a specific time
      msg.StartDeliverTime = targetTime.UTC().Unix() * 1000
Se StartDeliverTime tiver um timestamp anterior ao horário atual, a mensagem será entregue imediatamente.

Enviar mensagens agendadas e atrasadas

O exemplo a seguir envia quatro mensagens atrasadas, cada uma programada para entrega 10 segundos após o envio.

Substitua os seguintes espaços reservados pelos valores reais:

Espaço reservado

Descrição

Exemplo

${HTTP_ENDPOINT}

Endpoint HTTP disponível na seção HTTP Endpoint da página Instance Details

http://1234567890.mqrest.cn-hangzhou.aliyuncs.com

${TOPIC}

Nome do tópico criado no console do ApsaraMQ for RocketMQ

delayed-msg-topic

${INSTANCE_ID}

ID da instância. Se a instância tiver um namespace, especifique o ID. Caso contrário, defina como nulo ou string vazia

MQ_INST_1234567890_ABCDEF

package main

import (
    "fmt"
    "time"
    "strconv"
    "os"

    "github.com/aliyunmq/mq-http-go-sdk"
)

func main() {
    // HTTP endpoint from the HTTP Endpoint section of the Instance Details page in the ApsaraMQ for RocketMQ console.
    endpoint := "${HTTP_ENDPOINT}"
    // AccessKey pair from environment variables.
    accessKey := os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")
    secretKey := os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")
    // Topic created in the ApsaraMQ for RocketMQ console.
    topic := "${TOPIC}"
    // Instance ID. If the instance has a namespace, specify the ID.
    // If the instance does not have a namespace, set this to null or an empty string.
    // You can check the namespace on the Instance Details page in the ApsaraMQ for RocketMQ console.
    instanceId := "${INSTANCE_ID}"

    client := mq_http_sdk.NewAliyunMQClient(endpoint, accessKey, secretKey, "")

    mqProducer := client.GetProducer(instanceId, topic)
    // Cyclically send four messages.
    for i := 0; i < 4; i++ {
        var msg mq_http_sdk.PublishMessageRequest

            msg = mq_http_sdk.PublishMessageRequest{
            MessageBody: "hello mq!",         // The message content.
            MessageTag:  "",                  // The message tag.
            Properties:  map[string]string{}, // The message properties.
            }
        // The message key.
            msg.MessageKey = "MessageKey"
            // The custom properties of the message.
            msg.Properties["a"] = strconv.Itoa(i)
            // Deliver 10 seconds from now. Set to a Unix timestamp in milliseconds.
            // For scheduled delivery, set this to the time difference between the scheduled point and the current time.
            msg.StartDeliverTime = time.Now().UTC().Unix() * 1000 + 10 * 1000

        ret, err := mqProducer.PublishMessage(msg)

        if err != nil {
            fmt.Println(err)
            return
        } else {
            fmt.Printf("Publish ---->\n\tMessageId:%s, BodyMD5:%s, \n", ret.MessageId, ret.MessageBodyMD5)
        }
        time.Sleep(time.Duration(100) * time.Millisecond)
    }
}

Receber mensagens agendadas e atrasadas

O exemplo a seguir consome mensagens agendadas e atrasadas com long polling. O consumidor aguarda até 3 segundos por novas mensagens e processa até 3 mensagens por lote.

Substitua os seguintes espaços reservados pelos valores reais:

Espaço reservado

Descrição

Exemplo

${HTTP_ENDPOINT}

Endpoint HTTP disponível na seção HTTP Endpoint da página Instance Details

http://1234567890.mqrest.cn-hangzhou.aliyuncs.com

${TOPIC}

Nome do tópico criado no console do ApsaraMQ for RocketMQ

delayed-msg-topic

${INSTANCE_ID}

ID da instância. Se a instância tiver um namespace, especifique o ID. Caso contrário, defina como nulo ou string vazia

MQ_INST_1234567890_ABCDEF

${GROUP_ID}

ID do grupo de consumidores criado no console do ApsaraMQ for RocketMQ

GID_delayed_consumer

Cada tópico aceita apenas um tipo de mensagem. Tópicos usados para mensagens agendadas ou atrasadas não podem enviar ou receber outros tipos.
package main

import (
    "fmt"
    "github.com/gogap/errors"
    "strings"
    "time"
    "os"

    "github.com/aliyunmq/mq-http-go-sdk"
)

func main() {
    // HTTP endpoint from the HTTP Endpoint section of the Instance Details page in the ApsaraMQ for RocketMQ console.
    endpoint := "${HTTP_ENDPOINT}"
    // AccessKey pair from environment variables.
    accessKey := os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")
    secretKey := os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")
    // Topic created in the ApsaraMQ for RocketMQ console.
    // Each topic can only send and receive messages of a specific type.
    topic := "${TOPIC}"
    // Instance ID. If the instance has a namespace, specify the ID.
    // If the instance does not have a namespace, set this to null or an empty string.
    // You can check the namespace on the Instance Details page in the ApsaraMQ for RocketMQ console.
    instanceId := "${INSTANCE_ID}"
    // Consumer group ID created in the ApsaraMQ for RocketMQ console.
    groupId := "${GROUP_ID}"

    client := mq_http_sdk.NewAliyunMQClient(endpoint, accessKey, secretKey, "")

    mqConsumer := client.GetConsumer(instanceId, topic, groupId, "")

    for {
        endChan := make(chan int)
        respChan := make(chan mq_http_sdk.ConsumeMessageResponse)
        errChan := make(chan error)
        go func() {
            select {
            case resp := <-respChan:
                {
                    // The message consumption logic.
                    var handles []string
                    fmt.Printf("Consume %d messages---->\n", len(resp.Messages))
                    for _, v := range resp.Messages {
                        handles = append(handles, v.ReceiptHandle)
                        fmt.Printf("\tMessageID: %s, PublishTime: %d, MessageTag: %s\n"+
                            "\tConsumedTimes: %d, FirstConsumeTime: %d, NextConsumeTime: %d\n"+
                            "\tBody: %s\n"+
                            "\tProps: %s\n",
                            v.MessageId, v.PublishTime, v.MessageTag, v.ConsumedTimes,
                            v.FirstConsumeTime, v.NextConsumeTime, v.MessageBody, v.Properties)
                    }

                    // If the broker does not receive an acknowledgment (ACK) before the NextConsumeTime
                    // elapses, the message is redelivered to the consumer.
                    // A unique timestamp is specified for the handle each time the message is consumed.
                    ackerr := mqConsumer.AckMessage(handles)
                    if ackerr != nil {
                        // If the handle times out, the broker fails to receive an ACK from the consumer.
                        fmt.Println(ackerr)
                        if errAckItems, ok := ackerr.(errors.ErrCode).Context()["Detail"].([]mq_http_sdk.ErrAckItem); ok {
                           for _, errAckItem := range errAckItems {
                             fmt.Printf("\tErrorHandle:%s, ErrorCode:%s, ErrorMsg:%s\n",
                               errAckItem.ErrorHandle, errAckItem.ErrorCode, errAckItem.ErrorMsg)
                           }
                        } else {
                           fmt.Println("ack err =", ackerr)
                        }
                        time.Sleep(time.Duration(3) * time.Second)
                    } else {
                        fmt.Printf("Ack ---->\n\t%s\n", handles)
                    }

                    endChan <- 1
                }
            case err := <-errChan:
                {
                    // No message is available for consumption in the topic.
                    if strings.Contains(err.(errors.ErrCode).Error(), "MessageNotExist") {
                        fmt.Println("\nNo new message, continue!")
                    } else {
                        fmt.Println(err)
                        time.Sleep(time.Duration(3) * time.Second)
                    }
                    endChan <- 1
                }
            case <-time.After(35 * time.Second):
                {
                    fmt.Println("Timeout of consumer message ??")
                    endChan <- 1
                }
            }
        }()

        // Long polling: the default network timeout is 35 seconds.
        // If no message is available, the request is suspended on the broker for the specified period.
        // If a message becomes available during the wait, the broker responds immediately.
        mqConsumer.ConsumeMessage(respChan, errChan,
            3, // Maximum number of messages per batch (max: 16).
            3, // Long polling wait time in seconds (max: 30).
        )
        <-endChan
    }
}

Próximos passos