Todos los productos
Search
Centro de documentos

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

Última actualización: Sep 04, 2026

Este tema proporciona código de ejemplo para enviar y recibir mensajes programados y diferidos mediante el SDK cliente HTTP de ApsaraMQ for RocketMQ para Go.

Mensajes programados y diferidos

Los mensajes programados y diferidos controlan el momento en que se entrega un mensaje a los consumidores:

  • Mensaje diferido: Se entrega después de un retraso especificado desde el momento de su envío. Por ejemplo, envíe un mensaje ahora y programe su entrega para 30 segundos después.

  • Mensaje programado: Se entrega en un momento específico. Por ejemplo, envíe un mensaje ahora y programe su entrega para las 14:00 del día siguiente.

Mediante HTTP, ambos tipos utilizan el mismo mecanismo: establezca el campo StartDeliverTime con una marca de tiempo Unix futura en milisegundos. El broker retiene el mensaje hasta que se alcanza dicha marca de tiempo y luego lo entrega.

Para obtener más información, consulte Scheduled messages and delayed messages.

Requisitos previos

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

Funcionamiento

Tanto los mensajes programados como los diferidos utilizan el campo StartDeliverTime para controlar el momento de la entrega. Establezca este campo con una marca de tiempo Unix en milisegundos que indique cuándo debe entregar el mensaje el broker.

  • Entrega diferida: Sume el retraso deseado (en milisegundos) a la hora actual.

      // Deliver 10 seconds from now
      msg.StartDeliverTime = time.Now().UTC().Unix() * 1000 + 10 * 1000
  • Entrega programada: Convierta la hora de entrega objetivo a una marca de tiempo Unix en milisegundos.

      // Deliver at a specific time
      msg.StartDeliverTime = targetTime.UTC().Unix() * 1000
Si StartDeliverTime se establece con una marca de tiempo anterior a la hora actual, el mensaje se entrega de inmediato.

Envío de mensajes programados y diferidos

A continuación, el ejemplo envía cuatro mensajes diferidos, cada uno programado para entregarse 10 segundos después de su envío.

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

Marcador de posición

Descripción

Ejemplo

${HTTP_ENDPOINT}

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

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

${TOPIC}

Nombre del topic creado en la consola de ApsaraMQ for RocketMQ

delayed-msg-topic

${INSTANCE_ID}

ID de la instancia. Si la instancia tiene un namespace, especifique el ID. De lo contrario, establézcalo como null o una cadena vacía

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)
    }
}

Recepción de mensajes programados y diferidos

A continuación, el ejemplo consume mensajes programados y diferidos mediante sondeo largo. El consumidor espera hasta 3 segundos por nuevos mensajes y procesa hasta 3 mensajes por lote.

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

Marcador de posición

Descripción

Ejemplo

${HTTP_ENDPOINT}

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

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

${TOPIC}

Nombre del topic creado en la consola de ApsaraMQ for RocketMQ

delayed-msg-topic

${INSTANCE_ID}

ID de la instancia. Si la instancia tiene un namespace, especifique el ID. De lo contrario, establézcalo como null o una cadena vacía

MQ_INST_1234567890_ABCDEF

${GROUP_ID}

ID del grupo de consumidores creado en la consola de ApsaraMQ for RocketMQ

GID_delayed_consumer

Cada topic admite solo un tipo de mensaje. Un topic utilizado para mensajes programados o diferidos no puede enviar ni recibir otros tipos de mensajes.
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
    }
}

Pasos siguientes