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:
SDK HTTP para Go instalado. Para obter detalhes, consulte Prepare the environment
Instância do ApsaraMQ for RocketMQ, tópico e grupo de consumidores criados no ApsaraMQ for RocketMQ console
Par de AccessKey da sua conta Alibaba Cloud. Para obter detalhes, consulte Create an AccessKey pair
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 |
|
|
Endpoint HTTP disponível na seção HTTP Endpoint da página Instance Details |
|
|
|
Nome do tópico criado no console do ApsaraMQ for RocketMQ |
|
|
|
ID da instância. Se a instância tiver um namespace, especifique o ID. Caso contrário, defina como nulo ou string vazia |
|
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 |
|
|
Endpoint HTTP disponível na seção HTTP Endpoint da página Instance Details |
|
|
|
Nome do tópico criado no console do ApsaraMQ for RocketMQ |
|
|
|
ID da instância. Se a instância tiver um namespace, especifique o ID. Caso contrário, defina como nulo ou string vazia |
|
|
|
ID do grupo de consumidores criado no console do ApsaraMQ for RocketMQ |
|
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
Consulte os conceitos e restrições de scheduled messages and delayed messages
Create resources, como instâncias, tópicos e grupos de consumidores