rabbitmq AmqpClient 使用Topic 交换机同一个channel 同时多个队列 ,多个交换机,C++代码示例

  1 // 消息发送
  2 bool PublishExchangeTopicMulti(const std::string &strUri)
  3 {
  4     AmqpClient::Channel::ptr_t channel = 
  5         AmqpClient::Channel::CreateFromUri(strUri);
  6 
  7     if (channel == nullptr)
  8     {
  9         return false;
 10     }
 11 
 12     // 声明交换机,若不存在则创建 
 13     std::string strTopicExchange1 = "topic_exchange_1";
 14     std::string strTopicExchange2 = "topic_exchange_2";
 15     channel->DeclareExchange(strTopicExchange1, AmqpClient::Channel::EXCHANGE_TYPE_TOPIC);
 16     channel->DeclareExchange(strTopicExchange2, AmqpClient::Channel::EXCHANGE_TYPE_TOPIC);
 17 
 18     while (true)
 19     {
 20         // 可输入例如 "topic_exchange_1 disk.info 666"
 21         // "topic_exchange_2 any.warning 123"
 22         std::cout << "请输入[exchange] [routing_key1.routing_key2] [message]: " << std::endl;
 23     
 24         std::string strExchange;
 25         std::string severity;
 26         std::string message;
 27         std::cin >> strExchange;
 28         std::cin >> severity;
 29         std::cin >> message;
 30 
 31         channel->BasicPublish(strExchange, severity,
 32             AmqpClient::BasicMessage::Create(message));
 33 
 34         std::cout << "[X] to " << strExchange << ", send " 
 35             << severity << ": " << message << std::endl;
 36     }
 37 
 38 }
 39 
 40 
 41 void ReceiveTopicExchangeMulti(const std::string &strUri)
 42 {
 43     AmqpClient::Channel::ptr_t channel = 
 44         AmqpClient::Channel::CreateFromUri(strUri);
 45 
 46     if (channel == nullptr)
 47     {
 48         return ;
 49     }
 50 
 51     // 这里我们声明两个交换机,类型均为topic , 我们将通过不同的队列从两个交换机中取消息。
 52     // 这里交换机的名称需要与发送端的保持一致。
 53     std::string strTopicExchange1 = "topic_exchange_1";
 54     std::string strTopicExchange2 = "topic_exchange_2";
 55     channel->DeclareExchange(strTopicExchange1, AmqpClient::Channel::EXCHANGE_TYPE_TOPIC);
 56     channel->DeclareExchange(strTopicExchange2, AmqpClient::Channel::EXCHANGE_TYPE_TOPIC);
 57 
 58     // 这里我们声明了三个队列,第一个队列从交换机1 取数据第二三个队列从交换机2 取数据;
 59     // 但是第二三个队列所绑定的routing_key 有所不同。
 60     // 当然了,routing_key 也可以相同,这样的话相同routing_key 的消息就会在两个队列中都出现。
 61     std::string strTopicQueue_1 = "topic_queue_1";
 62     std::string strTopicQueue_2 = "topic_queue_2";
 63     std::string strTopicQueue_3 = "topic_queue_3";
 64     // 第一个参数若为空,则系统默认生成随机队列名称
 65     // 第三个参数 表明队列是否持久的。true: 服务器重启将会保留该Exchange,
 66     // 警告,若只设置此项,不代表消息的持久化。即不保证重启后消息还在。
 67     channel->DeclareQueue(strTopicQueue_1, false, true, false, false);
 68     channel->DeclareQueue(strTopicQueue_2, false, true, false, false);
 69     channel->DeclareQueue(strTopicQueue_3, false, true, false, false);
 70 
 71     // 队列绑定我们感兴趣的routing_key, 表示我们只接收这些routing_key 相关的消息。
 72     channel->BindQueue(strTopicQueue_1, strTopicExchange1, "*.info");
 73     channel->BindQueue(strTopicQueue_1, strTopicExchange1, "disk.*");
 74     channel->BindQueue(strTopicQueue_1, strTopicExchange1, "info.error");
 75 
 76     // 在交换机2 上面我们绑定了队列2 和队列3 。但是它们所关心的routing_key 不同。
 77     channel->BindQueue(strTopicQueue_3, strTopicExchange2, "*.info");
 78     channel->BindQueue(strTopicQueue_3, strTopicExchange2, "disk.*");
 79     channel->BindQueue(strTopicQueue_2, strTopicExchange2, "info.error");
 80 
 81     // 创建消费者标志,这个在后面会告诉 channel 我们需要哪些队列中的相关routing_key 的消息。
 82     // BasicConsume() 第五个参数是指该消息是否以独占的方式处理,若是则不允许第二个消费者绑定到该队列 上,
 83     // 若否,则多个消费者同时绑定到该队列,那么 在该队列上的消息将随机分配到某一个消费者。
 84     // 即,同一个消息将不会同时出现 在两个消费者身上。
 85     std::string strFlagConsume_1 = "tab_consume_1";
 86     std::string strFlagConsume_2 = "tab_consume_2";
 87     std::string strFlagConsume_3 = "tab_consume_3";
 88     channel->BasicConsume(strTopicQueue_1, strFlagConsume_1, true, false, true);
 89     channel->BasicConsume(strTopicQueue_2, strFlagConsume_2, true, false, true);
 90     channel->BasicConsume(strTopicQueue_3, strFlagConsume_3, true, false, true);
 91     // BasicConsume() 的第4 个参数为false 表示,我们需要主动ack 服务器才将该消息清除。
 92 
 93     std::vector<std::string> vecFlagConsume;
 94     vecFlagConsume.push_back(strFlagConsume_1);
 95     vecFlagConsume.push_back(strFlagConsume_2);
 96     vecFlagConsume.push_back(strFlagConsume_3);
 97 
 98     while (true)
 99     {
100         AmqpClient::Envelope::ptr_t envelope = channel->BasicConsumeMessage(vecFlagConsume);
101 
102         std::string strExchange = envelope->Exchange();
103         std::string strFlagConsume = envelope->ConsumerTag();
104         std::string severity = envelope->RoutingKey();
105         std::string buffer = envelope->Message()->body();
106 
107         std::cout << "[Y] exchange: " << strExchange << ", flagconsume: " << strflagConsume 
108             << ", receive " << severity << ": " << buffer << std::endl;
109 
110         channel->BasicAck(envelope);
111     }
112 
113     for (size_t i = 0; i < vecFlagConsume.size(); ++i)
114         channel->BasicCancel(vecFlagConsume[i]);
115 }

 

posted on 2018-07-03 10:58  独孤酷酷  阅读(2103)  评论(0编辑  收藏  举报