Todos os produtos
Search
Central de documentação

ApsaraMQ for RocketMQ:Send and receive normal messages by using the C++ HTTP SDK

Última atualização: Sep 21, 2026

Este tópico fornece código de exemplo em C++ para enviar e receber mensagens normais usando o SDK HTTP do ApsaraMQ for RocketMQ. Mensagens normais são mensagens sem características especiais oferecidas pelo ApsaraMQ for RocketMQ — diferentemente de mensagens agendadas, atrasadas, ordenadas e transacionais, elas não possuem semântica de entrega especial. Utilize mensagens normais para cenários de uso geral em que garantias de ordenação, temporização e transação não são necessárias.

Pré-requisitos

Antes de começar, certifique-se de que as seguintes operações foram concluídas:

  • Instale o SDK para C++. Para mais informações, consulte Prepare the environment.

  • Crie os recursos que você especificará no código pelo console do ApsaraMQ for RocketMQ. Os recursos incluem 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 normais

Inicialize um MQClient com seu endpoint HTTP e par de AccessKey e, em seguida, publique mensagens em um tópico.

Substitua os seguintes placeholders pelos seus valores reais:

Placeholder

Descrição

Onde encontrar

${HTTP_ENDPOINT}

Endpoint de acesso HTTP

Seção HTTP Endpoint na página Instance Details

${TOPIC}

Nome do tópico de destino

Criado no console do ApsaraMQ for RocketMQ

${INSTANCE_ID}

ID da instância. Defina como string vazia se a instância não possuir namespace

Página Instance Details no console

#include <fstream>
#include <time.h>
#include "mq_http_sdk/mq_client.h"

using namespace std;
using namespace mq::http::sdk;

int main() {

    MQClient mqClient(
            // The HTTP endpoint, found in the HTTP Endpoint section
            // of the Instance Details page in the ApsaraMQ for RocketMQ console.
            "${HTTP_ENDPOINT}",
            // The AccessKey ID and AccessKey secret for authentication.
            // Read from environment variables to avoid hardcoding credentials.
            System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),
            System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")
            );

    // The topic to publish messages to. Create the topic in the ApsaraMQ for RocketMQ console.
    string topic = "${TOPIC}";
    // The instance ID. If the instance has no namespace, set this to an empty string.
    // Check the namespace on the Instance Details page in the console.
    string instanceId = "${INSTANCE_ID}";

    MQProducerPtr producer;
    if (instanceId == "") {
        producer = mqClient.getProducerRef(topic);
    } else {
        producer = mqClient.getProducerRef(instanceId, topic);
    }

    try {
        // Send four messages in a loop.
        for (int i = 0; i < 4; i++)
        {
            PublishMessageResponse pmResp;

            // The message body.
            TopicMessage pubMsg("Hello, mq!have key!");
            // Set a custom property on the message.
            pubMsg.putProperty("a",std::to_string(i));
            // The message key.
            pubMsg.setMessageKey("MessageKey" + std::to_string(i));
            producer->publishMessage(pubMsg, pmResp);

            cout << "Publish mq message success. Topic is: " << topic
                << ", msgId is:" << pmResp.getMessageId()
                << ", bodyMD5 is:" << pmResp.getMessageBodyMD5() << endl;
        }
    } catch (MQServerException& me) {
        cout << "Request Failed: " + me.GetErrorCode() << ", requestId is:" << me.GetRequestId() << endl;
        return -1;
    } catch (MQExceptionBase& mb) {
        cout << "Request Failed: " + mb.ToString() << endl;
        return -2;
    }

    return 0;
}

Pontos importantes:

  • Defina as variáveis de ambiente ALIBABA_CLOUD_ACCESS_KEY_ID e ALIBABA_CLOUD_ACCESS_KEY_SECRET antes de executar o código.

  • Cada mensagem aceita propriedades personalizadas (putProperty) e uma chave de mensagem (setMessageKey).

  • Se a instância não possuir namespace, passe uma string vazia para instanceId. O sdk seleciona automaticamente a sobrecarga correta de getProducerRef.

Assinar mensagens normais

Como o consumo funciona

O consumidor utiliza HTTP long polling para recuperar mensagens:

  1. O consumidor envia uma requisição ao broker.

  2. Se houver mensagens disponíveis, o broker responde imediatamente.

  3. Caso não existam mensagens disponíveis, o broker mantém a requisição aberta pelo tempo de polling especificado (máximo: 30 segundos) e responde assim que uma mensagem chegar.

  4. Após processar cada lote, o consumidor envia uma confirmação (ACK) ao broker.

  5. Se o broker não receber um ACK antes de NextConsumeTime, ele reenvia a mensagem.

Parâmetros do consumidor

Parâmetro

Descrição

Valor de exemplo

Máximo

Tamanho do lote

Número máximo de mensagens consumidas por requisição

3

16

Duração do polling

Tempo que o broker aguarda por mensagens (segundos)

3

30

Código de exemplo

Substitua os placeholders a seguir, além dos listados na seção Enviar mensagens normais:

Placeholder

Descrição

Onde encontrar

${GROUP_ID}

ID do grupo de consumidores

Criado no console do ApsaraMQ for RocketMQ

#include <vector>
#include <fstream>
#include "mq_http_sdk/mq_client.h"

#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

using namespace std;
using namespace mq::http::sdk;

int main() {

    MQClient mqClient(
            // The HTTP endpoint, found in the HTTP Endpoint section
            // of the Instance Details page in the ApsaraMQ for RocketMQ console.
            "${HTTP_ENDPOINT}",
            // The AccessKey ID and AccessKey secret for authentication.
            // Read from environment variables to avoid hardcoding credentials.
            System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),
            System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")
            );

    // The topic to consume messages from. Create the topic in the ApsaraMQ for RocketMQ console.
    string topic = "${TOPIC}";
    // The consumer group ID. Create the consumer group in the ApsaraMQ for RocketMQ console.
    string groupId = "${GROUP_ID}";
    // The instance ID. If the instance has no namespace, set this to an empty string.
    // Check the namespace on the Instance Details page in the console.
    string instanceId = "${INSTANCE_ID}";

    MQConsumerPtr consumer;
    if (instanceId == "") {
        consumer = mqClient.getConsumerRef(topic, groupId);
    } else {
        consumer = mqClient.getConsumerRef(instanceId, topic, groupId, "");
    }

    do {
        try {
            std::vector<Message> messages;
            // Consume messages in long polling mode.
            // If no messages are available, the broker holds the request for the specified
            // polling duration and responds immediately when a message arrives.
            consumer->consumeMessage(
                    3, // Batch size: max messages per request. Maximum allowed: 16.
                    3, // Polling duration in seconds. Maximum allowed: 30.
                    messages
            );
            cout << "Consume: " << messages.size() << " Messages!" << endl;

            // Process each message and collect receipt handles for acknowledgment.
            std::vector<std::string> receiptHandles;
            for (std::vector<Message>::iterator iter = messages.begin();
                    iter != messages.end(); ++iter)
            {
                cout << "MessageId: " << iter->getMessageId()
                    << " PublishTime: " << iter->getPublishTime()
                    << " Tag: " << iter->getMessageTag()
                    << " Body: " << iter->getMessageBody()
                    << " FirstConsumeTime: " << iter->getFirstConsumeTime()
                    << " NextConsumeTime: " << iter->getNextConsumeTime()
                    << " ConsumedTimes: " << iter->getConsumedTimes()
                    << " Properties: " << iter->getPropertiesAsString()
                    << " Key: " << iter->getMessageKey() << endl;
                receiptHandles.push_back(iter->getReceiptHandle());
            }

            // Send an ACK to the broker. If the broker does not receive an ACK before
            // NextConsumeTime, it redelivers the message. Each receipt handle carries
            // a unique timestamp that expires after the NextConsumeTime window.
            AckMessageResponse bdmResp;
            consumer->ackMessage(receiptHandles, bdmResp);
            if (!bdmResp.isSuccess()) {
                // Log failed ACK items. A handle that has expired causes ACK failure,
                // and the broker redelivers the corresponding message.
                const std::vector<AckMessageFailedItem>& failedItems =
                    bdmResp.getAckMessageFailedItem();
                for (std::vector<AckMessageFailedItem>::const_iterator iter = failedItems.begin();
                        iter != failedItems.end(); ++iter)
                {
                    cout << "AckFailedItem: " << iter->errorCode
                        << "  " << iter->receiptHandle << endl;
                }
            } else {
                cout << "Ack: " << messages.size() << " messages suc!" << endl;
            }
        } catch (MQServerException& me) {
            if (me.GetErrorCode() == "MessageNotExist") {
                cout << "No message to consume! RequestId: " + me.GetRequestId() << endl;
                continue;
            }
            cout << "Request Failed: " + me.GetErrorCode() + ".RequestId: " + me.GetRequestId() << endl;
#ifdef _WIN32
            Sleep(2000);
#else
            usleep(2000 * 1000);
#endif
        } catch (MQExceptionBase& mb) {
            cout << "Request Failed: " + mb.ToString() << endl;
#ifdef _WIN32
            Sleep(2000);
#else
            usleep(2000 * 1000);
#endif
        }

    } while(true);
}

Pontos importantes:

  • O consumidor opera em loop infinito, fazendo polling continuamente. Quando não há mensagens disponíveis, ele captura MessageNotExist e tenta novamente.

  • Após processar um lote, chame ackMessage para confirme o recebimento. Mensagens não confirmadas são reenviadas após NextConsumeTime.

  • Cada receipt handle possui um timestamp exclusivo. Um handle expirado causa falha no ACK, o que aciona o reenvio da mensagem.

  • Em caso de erros diferentes de MessageNotExist, o consumidor aguarda 2 segundos antes de tentar novamente para evitar loops excessivos.