Mensagens ordenadas são um tipo de mensagem do ApsaraMQ for RocketMQ. Essas mensagens são publicadas e consumidas em ordem estrita FIFO (first-in-first-out). Este tópico fornece exemplos de código para enviar e receber mensagens ordenadas com o SDK de cliente TCP para C ou C++.
Informações básicas
As mensagens ordenadas dividem-se nos seguintes tipos:
Mensagens globalmente ordenadas: todas as mensagens de um tópico especificado são publicadas e consumidas em ordem FIFO.
Mensagens ordenadas por partição: todas as mensagens de um tópico especificado são distribuídas em diferentes partições por meio de chaves de fragmentação. As mensagens de cada partição seguem a ordem FIFO na publicação e no consumo. A chave de fragmentação é um campo usado pelas mensagens ordenadas para identificar partições distintas, diferindo da chave de uma mensagem normal.
Para mais informações, consulte Ordered messages.
Pré-requisitos
Certifique-se de concluir as seguintes operações:
Baixe o SDK para C ou C++. Para mais informações, consulte Release notes for the TCP client SDK for C++.
Prepare o ambiente. Para mais informações, consulte Prepare the environment (v1.x.x).
Crie no console do ApsaraMQ for RocketMQ os recursos que você pretende especificar no código, incluindo instâncias, tópicos e grupos de consumidores. Para mais informações, consulte Create resources.
Obtenha o par de AccessKey da sua conta Alibaba Cloud. Para mais informações, consulte Create an AccessKey.
Enviar mensagens ordenadas
Um broker do ApsaraMQ for RocketMQ determina a ordem de geração das mensagens com base na sequência em que o remetente utiliza um único producer ou thread para enviá-las. Caso o remetente utilize múltiplos producers ou threads para envio simultâneo, a ordem das mensagens corresponderá à sequência de recebimento pelo broker do ApsaraMQ for RocketMQ. Essa ordem pode divergir da sequência de envio definida pela aplicação.
O exemplo de código a seguir demonstra como enviar mensagens ordenadas com o SDK de cliente TCP para C ou C++:
#include "ONSFactory.h"
#include "ONSClientException.h"
#include <iostream>
using namespace ons;
int main()
{
// The parameter that is required to create and use a producer.
ONSFactoryProperty factoryInfo;
// The ID of the consumer group that you created in the ApsaraMQ for RocketMQ console.
factoryInfo.setFactoryProperty(ONSFactoryProperty::ProducerId, "XXX");
// The TCP endpoint. You can obtain the endpoint in the TCP Endpoint section of the Instance Details page in the ApsaraMQ for RocketMQ console.
factoryInfo.setFactoryProperty(ONSFactoryProperty::NAMESRV_ADDR, "XXX");
// The topic that you created in the ApsaraMQ for RocketMQ console.
factoryInfo.setFactoryProperty(ONSFactoryProperty::PublishTopics,"XXX" );
// The message content.
factoryInfo.setFactoryProperty(ONSFactoryProperty::MsgContent, "XXX");
// Make sure that the environment variables ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET are configured.
// The AccessKey ID that is used for authentication.
factoryInfo.setFactoryProperty(ONSFactoryProperty::AccessKey, getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"));
// The AccessKey secret that is used for authentication.
factoryInfo.setFactoryProperty(ONSFactoryProperty::SecretKey, getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
// Create the producer.
OrderProducer *pProducer = ONSFactory::getInstance()->createOrderProducer(factoryInfo);
// Before you send the message, call the start() method only once to start the producer.
pProducer->start();
Message msg(
//Message Topic
factoryInfo.getPublishTopics(),
//Message Tag
"TagA",
//Message Key. Set a key to uniquely identify the message. We recommend that the key be globally unique so that if a message cannot be received, you can query it in the ApsaraMQ for RocketMQ console using the key and resend it. Note: Not setting a key does not affect message sending or receiving.
"ORDERID_100",
//Message Body
factoryInfo.getMessageContent()
);
// The key field that is used to identify partitions for partitionally ordered messages.
// This field can be set to a non-empty string for globally ordered messages.
std::string shardingKey = "abc";
// Messages that have the same sharding key are sent in order.
try
{
// Send the message. If no exception is thrown, the message is sent.
SendResultONS sendResult = pProducer->send(msg, shardingKey);
std::cout << "send success" << std::endl;
}
catch(ONSClientException & e)
{
// Specify the logic to handle errors.
}
// Before you exit your application, destroy the producer. If you do not destroy the producer, issues such as memory leaks may occur.
pProducer->shutdown();
return 0;
}
No SDK C++ v1.1.1, o construtor de três parâmetros Message(topic, tag, body) apresenta um bug conhecido em que o parâmetro body é mapeado incorretamente para o campo keys internamente. Isso resulta em um corpo de mensagem vazio, gerando o erro 'the message body is empty' ao chamar send(). Utilize o construtor de quatro parâmetros Message(topic, tag, key, body), conforme demonstrado no exemplo acima, para evitar esse problema.
Inscrever-se em mensagens ordenadas
O exemplo de código a seguir demonstra como se inscrever em mensagens ordenadas com o SDK de cliente TCP para C ou C++:
#include "ONSFactory.h"
using namespace std;
using namespace ons;
// Create the consumer instance.
//After the push consumer pulls the message, the push consumer calls the consumeMessage function of the instance.
class ONSCLIENT_API MyMsgListener : public MessageOrderListener
{
public:
MyMsgListener()
{
}
virtual ~MyMsgListener()
{
}
virtual OrderAction consume(Message &message, ConsumeOrderContext &context)
{
// Consume messages based on your business requirements.
return Success; //CONSUME_SUCCESS;
}
};
int main(int argc, char* argv[])
{
// The parameter that is required to create and use the consumer.
ONSFactoryProperty factoryInfo;
// The ID of the consumer group that you created in the ApsaraMQ for RocketMQ console.
factoryInfo.setFactoryProperty(ONSFactoryProperty::ConsumerId, "XXX");
// The topic that you created in the ApsaraMQ for RocketMQ console.
factoryInfo.setFactoryProperty(ONSFactoryProperty::PublishTopics,"XXX" );
// Make sure that the environment variables ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET are configured.
// The AccessKey ID that is used for authentication.
factoryInfo.setFactoryProperty(ONSFactoryProperty::AccessKey, getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"));
// The AccessKey secret that is used for authentication.
factoryInfo.setFactoryProperty(ONSFactoryProperty::SecretKey, getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
// The TCP endpoint. You can obtain the endpoint in the TCP Endpoint section of the Instance Details page in the ApsaraMQ for RocketMQ console.
factoryInfo.setFactoryProperty(ONSFactoryProperty::NAMESRV_ADDR, "XXX");
// Create the consumer.
OrderConsumer* orderConsumer = ONSFactory::getInstance()->createOrderConsumer(factoryInfo);
MyMsgListener msglistener;
// The message topic and tag to which the consumer subscribes.
orderConsumer->subscribe(factoryInfo.getPublishTopics(), "*",&msglistener );
// Register the instance to listen to messages. After the consumer pulls the messages, the consumer calls the consumeMessage function of the message listening class.
//Start the consumer.
orderConsumer->start();
for(volatile int i = 0; i < 1000000000; ++i) {
//wait
}
// Destroy the consumer. Before you exit the application, destroy the consumer. Otherwise, issues such as memory leaks may occur.
orderConsumer->shutdown();
return 0;
}