Tous les produits
Search
Centre de documentation

ApsaraMQ for RocketMQ:Send and receive scheduled and delayed messages

Dernière mise à jour :Aug 09, 2026

Exemples de code pour l'envoi et la réception de messages planifiés et différés avec le SDK client TCP pour C++ (édition communautaire).

Différence entre messages planifiés et messages différés

ApsaraMQ for RocketMQ prend en charge deux types de livraison temporelle :

  • Messages planifiés : livrés aux consommateurs à un instant précis. Par exemple, envoyer une notification demain à 9 h 00.

  • Messages différés : livrés aux consommateurs après un délai spécifié. Par exemple, envoyer un rappel dans 30 minutes.

Ces deux types utilisent la propriété de message __STARTDELIVERTIME. La différence réside dans le calcul de l'horodatage :

Type Valeur de l'horodatage Exemple
Planifié Heure absolue en millisecondes (époque Unix) 1583568060000 (7 mars 2020, 16:21:00)
Différé Heure actuelle + délai en millisecondes currentTimeMillis + 10000 (délai de 10 secondes)

Pour plus d'informations, consultez la rubrique Messages planifiés et messages différés.

Différences par rapport à Apache RocketMQ

Fonctionnalité ApsaraMQ for RocketMQ Apache RocketMQ
Messages planifiés Pris en charge Non pris en charge
Messages différés Pris en charge Pris en charge
Précision temporelle Précision à la seconde N/A
API dédiée Propriété __STARTDELIVERTIME Aucune interface dédiée pour les messages planifiés
Important

Apache RocketMQ prend en charge les messages différés, mais pas les messages planifiés. Le SDK open source ne propose aucune interface dédiée pour les messages planifiés. ApsaraMQ for RocketMQ prend en charge les messages planifiés et différés, avec une précision à la seconde pour l'heure de planification et les délais, ainsi qu'une concurrence plus élevée.

Règles de définition de l'heure

  • La valeur __STARTDELIVERTIME est un horodatage Unix en millisecondes.

  • Définissez un horodatage absolu pour les messages planifiés, ou définissez currentTimeMillis + delayMillis pour les messages différés.

  • Si l'horodatage est antérieur à l'heure actuelle, le message est livré immédiatement.

Prérequis

Avant de commencer, assurez-vous d'avoir :

Envoyer des messages planifiés ou différés

Pour planifier la livraison, définissez la propriété __STARTDELIVERTIME sur le message :

msg.setProperty("__STARTDELIVERTIME", to_string(deliverTimestamp));

Définissez deliverTimestamp sur un horodatage Unix en millisecondes. Pour un délai de 10 secondes, calculez-le comme suit :

long deliverTimestamp = currentTimeMillis + 10000;

Exemple complet de producteur

  1. Enregistrez le code suivant sous le nom DelayProducerDemo.cpp.

  2. Compilez :

g++ -o delay_producer_demo -std=c++11 -lz -lrocketmq DelayProducerDemo.cpp
  1. Exécutez le binaire compilé.

Remplacez les espaces réservés dans le code par vos valeurs réelles :

Espace réservé Description Exemple
<group-id> ID de groupe provenant de la console ApsaraMQ for RocketMQ GID_delay_demo
<endpoint> Endpoint TCP provenant de la page Instance Details http://MQ_INST_xxx.mq-internet-access.mq-internet.aliyuncs.com:80
<topic> Topic provenant de la console ApsaraMQ for RocketMQ delay_topic
#include <iostream>
#include <chrono>
#include <thread>
#include "DefaultMQProducer.h"

using namespace std;
using namespace rocketmq;

int main() {
    std::cout << "=======Before sending messages=======" << std::endl;
    // Group ID from the ApsaraMQ for RocketMQ console.
    DefaultMQProducer producer("<group-id>");
    // TCP endpoint from the Instance Details page in the ApsaraMQ for RocketMQ console.
    producer.setNamesrvAddr("<endpoint>");
    // Authenticate with your AccessKey ID and AccessKey secret from environment variables.
    // Default user channel: ALIYUN.
    producer.setSessionCredentials(getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"), "ALIYUN");

    // Start the producer.
    producer.start();
    auto start = std::chrono::system_clock::now();
    int count = 32;
    for (int i = 0; i < count; ++i) {
        // Topic from the ApsaraMQ for RocketMQ console.
        MQMessage msg("<topic>", "HiTAG", "Hello,CPP SDK, Delay Message.");
        chrono::system_clock::duration d = chrono::system_clock::now().time_since_epoch();
        chrono::milliseconds mil = chrono::duration_cast<chrono::milliseconds>(d);
        // Set the delivery time.
        // - Scheduled message: use an absolute timestamp in milliseconds.
        //   For example, 1583568060000 delivers the message at 2020-03-07 16:21:00.
        // - Delayed message: add the delay in milliseconds to the current time.
        //   The following example delays delivery by 10 seconds.
        // If the timestamp is earlier than the current time, the message is delivered immediately.
        long exp = mil.count() + 10000;
        msg.setProperty("__STARTDELIVERTIME", to_string(exp));
        std::cout << "Now: " << mil.count() << " Exp:" << exp << std::endl;
        try {
            SendResult sendResult = producer.send(msg);
            std::cout << "SendResult:" << sendResult.getSendStatus() << ", Message ID: " << sendResult.getMsgId()
                      << std::endl;
            this_thread::sleep_for(chrono::seconds(1));
        } catch (MQException e) {
            std::cout << "ErrorCode: " << e.GetError() << " Exception:" << e.what() << std::endl;
        }
    }
    auto interval = std::chrono::system_clock::now() - start;
    std::cout << "Send " << count << " messages OK, costs "
              << std::chrono::duration_cast<std::chrono::milliseconds>(interval).count() << "ms" << std::endl;

    producer.shutdown();
    std::cout << "=======After sending messages=======" << std::endl;
    return 0;
}

Recevoir des messages planifiés ou différés

La consommation de messages planifiés et différés fonctionne de la même manière que celle des messages normaux. Enregistrez un écouteur MessageListenerConcurrently et abonnez-vous au topic.

Exemple complet de consommateur

  1. Enregistrez le code suivant sous le nom DelayConsumerDemo.cpp.

  2. Compilez :

g++ -o delay_consumer_demo -std=c++11 -lz -lrocketmq DelayConsumerDemo.cpp
  1. Exécutez le binaire compilé.

Remplacez les espaces réservés par vos valeurs réelles (identiques à l'exemple du producteur).

#include <iostream>
#include <thread>
#include <chrono>
#include "DefaultMQPushConsumer.h"

using namespace rocketmq;
using namespace std;

class ExampleDelayMessageListener : public MessageListenerConcurrently {
public:
    ConsumeStatus consumeMessage(const std::vector<MQMessageExt> &msgs) {
        for (auto item = msgs.begin(); item != msgs.end(); item++) {
            chrono::system_clock::duration d = chrono::system_clock::now().time_since_epoch();
            chrono::milliseconds mil = chrono::duration_cast<chrono::milliseconds>(d);
            std::cout << "Now: " << mil.count() << " Received Message Topic:" << item->getTopic() << ", MsgId:"
                      << item->getMsgId() << " DelayTime:" << item->getProperty("__STARTDELIVERTIME") << std::endl;
        }
        return CONSUME_SUCCESS;
    }
};

int main(int argc, char *argv[]) {
    std::cout << "=======Before consuming messages=======" << std::endl;
    // Group ID from the ApsaraMQ for RocketMQ console.
    DefaultMQPushConsumer *consumer = new DefaultMQPushConsumer("<group-id>");
    // TCP endpoint from the Instance Details page in the ApsaraMQ for RocketMQ console.
    consumer->setNamesrvAddr("<endpoint>");
    // Authenticate with your AccessKey ID and AccessKey secret from environment variables.
    // Default user channel: ALIYUN.
    consumer->setSessionCredentials(getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"), "ALIYUN");
    auto start = std::chrono::system_clock::now();

    // Register a message listener.
    ExampleDelayMessageListener *messageListener = new ExampleDelayMessageListener();
    consumer->subscribe("<topic>", "*");
    consumer->registerMessageListener(messageListener);

    // Before starting the consumer:
    // 1. Make sure that the subscription is configured.
    // 2. Make sure that consumers in the same group have consistent subscriptions.
    consumer->start();

    // Keep the thread running. Do not shut down the consumer while messages are being received.
    std::this_thread::sleep_for(std::chrono::seconds(600));
    consumer->shutdown();
    std::cout << "=======After consuming messages======" << std::endl;
    return 0;
}

Bonnes pratiques

  • Stockez les identifiants dans des variables d'environnement. Les deux exemples utilisent les variables d'environnement ALIBABA_CLOUD_ACCESS_KEY_ID et ALIBABA_CLOUD_ACCESS_KEY_SECRET au lieu de valeurs codées en dur.

  • Maintenez la cohérence des abonnements des consommateurs. Tous les consommateurs d'un même groupe doivent s'abonner aux mêmes topics et tags. Des abonnements incohérents entraînent un routage imprévisible des messages.