ApsaraMQ for RocketMQ'de zamanlanmış ve gecikmeli mesajları göndermek ve almak için Python HTTP istemci SDK'sını kullanın. Bu konu, eksiksiz üretici ve tüketici kod örnekleri sunar.
Zamanlanmış ve gecikmeli mesajların çalışma mantığı
Zamanlanmış ve gecikmeli mesajlar, belirtilen bir zamana kadar tüketicilere teslim edilmeyi erteler:
Gecikmeli mesaj: Sabit bir gecikme süresinden sonra teslim edilir. Örneğin, 10 saniyelik gecikmeye sahip bir mesaj, gönderildikten 10 saniye sonra tüketiciler tarafından kullanılabilir hale gelir.
Zamanlanmış mesaj: Belirli bir anda teslim edilir. Örneğin, 2024-01-15 15:00:00 olarak zamanlanan bir mesaj, bu saatte teslim edilir.
HTTP üzerinden her iki tür de aynı API'yi kullanır. start_deliver_time parametresini milisaniye cinsinden gelecekteki bir Unix zaman damgasına ayarlayın:
Gecikmeli mesaj için zaman damgasını
current_time + delay_durationolarak hesaplayın.Zamanlanmış mesaj için zaman damgasını doğrudan hedef teslim zamanına ayarlayın.
Daha fazla bilgi için bkz. Zamanlanmış mesajlar ve gecikmeli mesajlar.
Ön koşullar
Başlamadan önce şunlara sahip olduğunuzdan emin olun:
Python HTTP istemci SDK'sı yüklü olmalıdır. Ayrıntılar için bkz. Ortamı hazırlama
ApsaraMQ for RocketMQ konsolunda bir ApsaraMQ for RocketMQ örneği, konu ve tüketici grubu oluşturulmuş olmalıdır. Ayrıntılar için bkz. Kaynakları oluşturma
Alibaba Cloud hesabınız için bir AccessKey çiftiniz olmalıdır. Ayrıntılar için bkz. AccessKey çifti oluşturma
Zamanlanmış veya gecikmeli mesaj gönderme
Aşağıdaki örnek, her biri gönderildikten 10 saniye sonra teslim edilen dört gecikmeli mesaj gönderir. Bunun yerine zamanlanmış bir mesaj göndermek için start_deliver_time değerini milisaniye cinsinden Unix zaman damgası olarak hedef teslim zamanına ayarlayın.
Aşağıdaki yer tutucuları gerçek değerlerinizle değiştirin:
| Yer Tutucu | Açıklama | Örnek |
|---|---|---|
<http-endpoint> |
Örneğinizin HTTP uç noktası. Bunu ApsaraMQ for RocketMQ konsolundaki Instance Details sayfasında bulabilirsiniz | http://xxxxx.mqrest.cn-hangzhou.aliyuncs.com |
<topic> |
Mesajların gönderileceği konunun adı | scheduled-msg-topic |
<instance-id> |
Konuya ait örneğin ID'si. Örnek bir ad alanına sahipse gereklidir. Örnek bir ad alanına sahip değilse boş bir dize girin. Ad alanı durumunu kontrol etmek için Instance Details sayfasına bakın | MQ_INST_xxxxx |
import sys
import os
import time
from mq_http_sdk.mq_exception import MQExceptionBase
from mq_http_sdk.mq_producer import *
from mq_http_sdk.mq_client import *
# Initialize the producer client
mq_client = MQClient(
# HTTP endpoint. Find it in the HTTP Endpoint section
# of the Instance Details page in the ApsaraMQ for RocketMQ console.
"<http-endpoint>",
# AccessKey ID and AccessKey secret for authentication.
# Store credentials in environment variables instead of hardcoding them.
os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID'],
os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET']
)
topic_name = "<topic>"
instance_id = "<instance-id>"
producer = mq_client.get_producer(instance_id, topic_name)
# Send four messages
msg_count = 4
print("%sPublish Message To %s\nTopicName:%s\nMessageCount:%s\n" % (10 * "=", 10 * "=", topic_name, msg_count))
try:
for i in range(msg_count):
msg = TopicMessage(
"I am test message %s.hello" % i, # Message content
"tag1" # Message tag
)
# Set a custom message attribute
msg.put_property("a", "i")
# Set the message key for tracing
msg.set_message_key("MessageKey")
# Deliver this message after a 10-second delay.
# The value is a Unix timestamp in milliseconds.
# For a scheduled message, replace the calculation below
# with the target delivery time in milliseconds.
msg.set_start_deliver_time(int(round(time.time() * 1000)) + 10 * 1000)
re_msg = producer.publish_message(msg)
print("Publish Timer Message Succeed. MessageID:%s, BodyMD5:%s" % (re_msg.message_id, re_msg.message_body_md5))
except MQExceptionBase as e:
if e.type == "TopicNotExist":
print("Topic not exist, please create it.")
sys.exit(1)
print("Publish Message Fail. Exception:%s" % e)
**Anahtar parametre: set_start_deliver_time**
Aracının mesajı ne zaman teslim edeceğini kontrol eder. Milisaniye cinsinden bir Unix zaman damgası girin:
| Teslimat türü | Zaman damgasının nasıl ayarlanacağı | Örnek |
|---|---|---|
| Gecikmeli teslimat | Geçerli saat artı gecikme süresi | int(round(time.time() * 1000)) + 10 * 1000 |
| Zamanlanmış teslimat | Hedef teslim zamanının mutlak zaman damgası | 1700000000000 |
Zamanlanmış ve gecikmeli mesajları alma
Aracı, zamanlanmış ve gecikmeli mesajları teslim zamanı gelene kadar tutar ve ardından bunları tüketim için kullanılabilir hale getirir. Bunları normal mesajlarla aynı şekilde tüketin.
Aşağıdaki örnek, mesajları almak ve onaylamak için uzun anketlemeyi (long polling) kullanır. Aşağıdaki yer tutucuları gerçek değerlerinizle değiştirin:
| Yer Tutucu | Açıklama | Örnek |
|---|---|---|
<http-endpoint> |
Örneğinizin HTTP uç noktası | http://xxxxx.mqrest.cn-hangzhou.aliyuncs.com |
<topic> |
Tüketilecek konunun adı | scheduled-msg-topic |
<group-id> |
Tüketici grubunun ID'si | GID_scheduled_msg |
<instance-id> |
Örneğin ID'si. Örnek ad alanına sahip değilse boş bir dize girin | MQ_INST_xxxxx |
import os
import time
from mq_http_sdk.mq_exception import MQExceptionBase
from mq_http_sdk.mq_consumer import *
from mq_http_sdk.mq_client import *
# Initialize the consumer client
mq_client = MQClient(
"<http-endpoint>",
os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID'],
os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET']
)
topic_name = "<topic>"
group_id = "<group-id>"
instance_id = "<instance-id>"
consumer = mq_client.get_consumer(instance_id, topic_name, group_id)
# Long polling timeout in seconds (max: 30)
wait_seconds = 3
# Maximum messages per request (max: 16)
batch = 3
print(("%sConsume And Ak Message From Topic%s\nTopicName:%s\nMQConsumer:%s\nWaitSeconds:%s\n" \
% (10 * "=", 10 * "=", topic_name, group_id, wait_seconds)))
while True:
try:
# Long polling: the request blocks on the broker until a message
# arrives or wait_seconds elapses, whichever comes first.
recv_msgs = consumer.consume_message(batch, wait_seconds)
for msg in recv_msgs:
print(("Receive, MessageId: %s\nMessageBodyMD5: %s \
\nMessageTag: %s\nConsumedTimes: %s \
\nPublishTime: %s\nBody: %s \
\nNextConsumeTime: %s \
\nReceiptHandle: %s \
\nProperties: %s\n" % \
(msg.message_id, msg.message_body_md5,
msg.message_tag, msg.consumed_times,
msg.publish_time, msg.message_body,
msg.next_consume_time, msg.receipt_handle, msg.properties)))
except MQExceptionBase as e:
if e.type == "MessageNotExist":
print(("No new message! RequestId: %s" % e.req_id))
continue
print(("Consume Message Fail! Exception:%s\n" % e))
time.sleep(2)
continue
# Acknowledge consumed messages.
# If the broker does not receive an ACK before msg.next_consume_time,
# it redelivers the message. Each delivery generates a new receipt handle.
try:
receipt_handle_list = [msg.receipt_handle for msg in recv_msgs]
consumer.ack_message(receipt_handle_list)
print(("Ak %s Message Succeed.\n\n" % len(receipt_handle_list)))
except MQExceptionBase as e:
print(("\nAk Message Fail! Exception:%s" % e))
if e.sub_errors:
for sub_error in e.sub_errors:
print(("\tErrorHandle:%s,ErrorCode:%s,ErrorMsg:%s" % \
(sub_error["ReceiptHandle"], sub_error["ErrorCode"], sub_error["ErrorMessage"])))
Uzun anketlemenin çalışma mantığı
consume_message çağrısı, aracıda en fazla wait_seconds süre boyunca bloke olur. Bu süre içinde bir mesaj kullanılabilir hale gelirse aracı hemen yanıt verir. Aksi takdirde istek zaman aşımından sonra döner.
| Parametre | Açıklama | Aralık |
|---|---|---|
wait_seconds |
Uzun anketleme zaman aşımı (saniye) | Maksimum: 30 |
batch |
İstek başına döndürülen maksimum mesaj sayısı | Maksimum: 16 |
Mesaj onaylamanın çalışma mantığı
Bir mesajı işledikten sonra makbuz tanıtıcısını (receipt handle) aracıya geri göndererek onaylayın. next_consume_time öncesinde bir ACK alınmazsa aracı mesajı yeni bir makbuz tanıtıcısıyla yeniden teslim eder. Her zaman en son teslimattan gelen tanıtıcıyı kullanın.
Sonraki adımlar
Zamanlanmış mesajlar ve gecikmeli mesajlar -- kavramlar ve özellik ayrıntıları
Ortamı hazırlama -- diğer diller için SDK kurulumu