Bu konuda, Go için ApsaraMQ for RocketMQ HTTP istemci SDK'sını kullanarak zamanlanmış ve gecikmeli mesajların nasıl gönderileceği ve alınacağına ilişkin örnek kodlar sunulmaktadır.
Zamanlanmış ve gecikmeli mesajlar
Zamanlanmış ve gecikmeli mesajlar, bir mesajın tüketicilere ne zaman teslim edileceğini belirler:
Gecikmeli mesaj: Gönderildikten sonra belirtilen süre kadar bekletilip teslim edilir. Örneğin, bir mesajı şimdi gönderin ve 30 saniye sonra teslim edilmesini sağlayın.
Zamanlanmış mesaj: Belirli bir saatte teslim edilir. Örneğin, bir mesajı şimdi gönderin ve yarın saat 14:00'te teslim edilmesini sağlayın.
HTTP üzerinden her iki tür de aynı mekanizmayı kullanır: StartDeliverTime alanını milisaniye cinsinden gelecekteki bir Unix zaman damgasına ayarlayın. Broker, bu zaman damgasına gelene kadar mesajı bekletir ve ardından teslim eder.
Daha fazla bilgi için bkz. Zamanlanmış mesajlar ve gecikmeli mesajlar.
Ön koşullar
Başlamadan önce aşağıdakileri tamamladığınızdan emin olun:
Go HTTP SDK'sının yüklenmesi. Ayrıntılar için bkz. Ortamı hazırlama
ApsaraMQ for RocketMQ konsolu içinde bir ApsaraMQ for RocketMQ örneği, bir konu ve bir tüketici grubu oluşturulması
Alibaba Cloud hesabınız için bir AccessKey çifti. Ayrıntılar için bkz. AccessKey çifti oluşturma
Çalışma biçimi
Hem zamanlanmış hem de gecikmeli mesajlar, teslim zamanlamasını kontrol etmek için StartDeliverTime alanını kullanır. Bu alanı, broker'ın mesajı teslim etmesi gereken zamanı temsil eden milisaniye cinsinden bir Unix zaman damgasına ayarlayın.
-
Gecikmeli teslim: İstenen gecikme süresini (milisaniye cinsinden) geçerli saate ekleyin.
// Deliver 10 seconds from now msg.StartDeliverTime = time.Now().UTC().Unix() * 1000 + 10 * 1000 -
Zamanlanmış teslim: Hedef teslim saatini milisaniye cinsinden bir Unix zaman damgasına dönüştürün.
// Deliver at a specific time msg.StartDeliverTime = targetTime.UTC().Unix() * 1000
Eğer StartDeliverTime geçerli zamandan daha eski bir zaman damgasına ayarlanırsa mesaj hemen teslim edilir.
Zamanlanmış ve gecikmeli mesajları gönderme
Aşağıdaki örnek, her biri gönderildikten 10 saniye sonra teslim edilmek üzere planlanmış dört gecikmeli mesaj gönderir.
Aşağıdaki yer tutucuları gerçek değerlerinizle değiştirin:
| Yer Tutucu | Açıklama | Örnek |
|---|---|---|
${HTTP_ENDPOINT} |
Instance Details sayfasındaki HTTP Endpoint bölümünden alınan HTTP uç noktası | http://1234567890.mqrest.cn-hangzhou.aliyuncs.com |
${TOPIC} |
ApsaraMQ for RocketMQ konsolunda oluşturulan konu adı | delayed-msg-topic |
${INSTANCE_ID} |
Örnek Kimliği. Örneğin bir ad alanı varsa kimliği belirtin. Yoksa null veya boş bir dize olarak ayarlayın | 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)
}
}
Zamanlanmış ve gecikmeli mesajları alma
Aşağıdaki örnek, uzun oylama kullanarak zamanlanmış ve gecikmeli mesajları tüketir. Tüketici, yeni mesajlar için en fazla 3 saniye bekler ve toplu iş başına en fazla 3 mesajı işler.
Aşağıdaki yer tutucuları gerçek değerlerinizle değiştirin:
| Yer Tutucu | Açıklama | Örnek |
|---|---|---|
${HTTP_ENDPOINT} |
Instance Details sayfasındaki HTTP Endpoint bölümünden alınan HTTP uç noktası | http://1234567890.mqrest.cn-hangzhou.aliyuncs.com |
${TOPIC} |
ApsaraMQ for RocketMQ konsolunda oluşturulan konu adı | delayed-msg-topic |
${INSTANCE_ID} |
Örnek Kimliği. Örneğin bir ad alanı varsa kimliği belirtin. Yoksa null veya boş bir dize olarak ayarlayın | MQ_INST_1234567890_ABCDEF |
${GROUP_ID} |
ApsaraMQ for RocketMQ konsolunda oluşturulan tüketici grubu kimliği | GID_delayed_consumer |
Her konu yalnızca bir mesaj türünü destekler. Zamanlanmış veya gecikmeli mesajlar için kullanılan bir konu, diğer mesaj türlerini gönderemez veya alamaz.
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
}
}
Sonraki adımlar
Zamanlanmış mesajlar ve gecikmeli mesajlar kavramları ve kısıtlamaları hakkında bilgi edinin
Örnekler, konular ve tüketici grupları gibi kaynakları Oluşturun