Use o SDK do cliente HTTP Python para enviar e receber mensagens agendadas e atrasadas no ApsaraMQ for RocketMQ. Este tópico apresenta exemplos completos de código para produtor e consumidor.
Funcionamento das mensagens agendadas e atrasadas
Mensagens agendadas e atrasadas adiam a entrega aos consumidores até um momento específico:
Mensagem atrasada: entregue após um intervalo fixo. Por exemplo, uma mensagem com atraso de 10 segundos fica disponível para consumo 10 segundos após o envio.
Mensagem agendada: entregue em um ponto exato no tempo. Por exemplo, uma mensagem agendada para 2024-01-15 15:00:00 é entregue exatamente nesse horário.
Via HTTP, ambos os tipos usam a mesma API. Defina start_deliver_time como um timestamp Unix futuro em milissegundos:
Para mensagem atrasada, calcule o timestamp como
current_time + delay_duration.Para mensagem agendada, defina o timestamp diretamente como o horário de entrega desejado.
Para mais informações, consulte Scheduled messages and delayed messages.
Pré-requisitos
Antes de começar, verifique se você tem:
SDK do cliente HTTP Python instalado. Para detalhes, consulte Prepare the environment
Instância, tópico e grupo de consumidores do ApsaraMQ for RocketMQ criados no console do ApsaraMQ for RocketMQ. Para detalhes, consulte Create resources
Par de AccessKey da sua conta Alibaba Cloud. Para detalhes, consulte Create an AccessKey pair
Enviar mensagens agendadas ou atrasadas
O exemplo a seguir envia quatro mensagens atrasadas, cada uma entregue 10 segundos após o envio. Para enviar uma mensagem agendada, defina start_deliver_time como o horário de entrega alvo em timestamp Unix de milissegundos.
Substitua os espaços reservados a seguir pelos valores reais:
|
Espaço reservado |
Descrição |
Exemplo |
|
|
Endpoint HTTP da instância. Disponível na página Instance Details do console ApsaraMQ for RocketMQ |
|
|
|
Nome do tópico de destino das mensagens |
|
|
|
ID da instância proprietária do tópico. Obrigatório se a instância tiver namespace. Se não tiver, passe uma string vazia. Verifique o status do namespace na página Instance Details |
|
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)
**Parâmetro principal: set_start_deliver_time**
Controla quando o broker entrega a mensagem. Passe um timestamp Unix em milissegundos:
|
Tipo de entrega |
Como definir o timestamp |
Exemplo |
|
Entrega atrasada |
Hora atual mais a duração do atraso |
|
|
Entrega agendada |
Timestamp absoluto do horário de entrega alvo |
|
Receber mensagens agendadas e atrasadas
O broker retém mensagens agendadas e atrasadas até o horário de entrega e as disponibiliza para consumo. Consuma-as como mensagens normais.
O exemplo a seguir usa long polling para receber e confirmar mensagens. Substitua os espaços reservados abaixo pelos valores reais:
|
Espaço reservado |
Descrição |
Exemplo |
|
|
Endpoint HTTP da instância |
|
|
|
Nome do tópico de origem do consumo |
|
|
|
ID do grupo de consumidores |
|
|
|
ID da instância. Passe uma string vazia se a instância não tiver namespace |
|
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"])))
Funcionamento do long polling
consume_message bloqueia a solicitação no broker por até wait_seconds. Se uma mensagem ficar disponível nesse período, o broker responde imediatamente. Caso contrário, a solicitação retorna após o tempo limite.
|
Parâmetro |
Descrição |
Intervalo |
|
|
Tempo limite do long polling em segundos |
Máximo: 30 |
|
|
Quantidade máxima de mensagens retornadas por solicitação |
Máximo: 16 |
Funcionamento da confirmação de mensagens
Após processar uma mensagem, confirme-a enviando o receipt handle de volta ao broker. Se nenhum ACK chegar antes de next_consume_time, o broker reentrega a mensagem com um novo receipt handle. Sempre use o handle da entrega mais recente.
Próximos passos
Scheduled messages and delayed messages -- conceitos e detalhes do recurso
Prepare the environment -- configuração do SDK para outras linguagens