【仿RabbitMQ的发布订阅式消息队列】 ---- 功能测试联调

Welcome to 9ilk's Code World

(๑•́ ₃ •̀๑) 个人主页: 9ilk

(๑•́ ₃ •̀๑) 文章专栏: 项目


本篇博客主要是对消息队列项目组件的功能的一个测试,主要测试点在于在不同模式下的交换机,客户端是否能正确收到订阅队列的消息,这里我们测试的是广播交换、直接交换和主题交换。

广播交换模式测试

主要测试方案是:

  • 声明一个交换机,且为广播模式
  • 声明两个队列queue1和queue2,设置好binding_key然后和交换机进行绑定。
  • 前面两个操作,为了以防万一,消费者客户端和生产者客户端都做一遍这个工作。
  • 然后订阅客户端就可以订阅queue1,发布客户端发布的消息,订阅客户端应该都能收到

发布客户端:

cpp 复制代码
#include "asyncWorker.hpp"
#include "channel.hpp"
#include"connection.hpp"
#include <google/protobuf/map.h>
#include <memory>
#include <string>

int main()
{
    //1.实例化异步工作线程对现场
    zmq::AsyncWorker::ptr awp = make_shared<zmq::AsyncWorker>();
    //2.实例化连接对象
    zmq::Connection::ptr conn = make_shared<zmq::Connection>("127.0.0.1",8085,awp);
    //3.通过连接创建信道
    zmq::Channel::ptr channel = conn->openChannel();
    //4.通过信道提供的服务完成所需
    //4.1声明一个交换机 exchange1,交换机类型为广播模式
    google::protobuf::Map<string,string> tmp_map;
    channel->declareExchange("exchange1",zmq::ExchangeType::FANOUT,true,false,tmp_map);
    //4.2声明两个队列
    channel->declareQueue("queue1",true,false,false,tmp_map);

    channel->declareQueue("queue2",true,false,false,tmp_map);
    //4.3绑定 queue1-exchange1 且bing_key设置为queue1
    channel->queueBind("exchange1","queue1","queue1");
    channel->queueBind("exchange1","queue2","news.music.#");
    //5. 循环向交换机发布消息
    for(int i = 0 ; i < 10 ; i++)
    {
        //广播
        channel->basicPublish("exchange1",nullptr,"Hello Queue-"+to_string(i));
    }
    //6.关闭信道
    conn->closeChannel(channel);
    return 0;
}

订阅客户端:

cpp 复制代码
#include "asyncWorker.hpp"
#include "channel.hpp"
#include"connection.hpp"
#include <functional>
#include <google/protobuf/map.h>
#include <memory>
#include<thread>
#include <string>
#include<iostream>
#include "../mqcommon/logger.hpp"
using namespace std;

void callBack(zmq::Channel::ptr channel,const string& tag,const zmq::BasicProperties* bp,const string& body)
{
   cout << tag << "消费了消息:" << body << endl;
   //应答
   channel->basicAck(bp->id());
}

int main(int argc,char* argv[])
{
    if(argc!=2)
    {
        DBG_LOG("Usage: ./consume_client queue_anme");
        exit(1);
    }
    //1.实例化异步工作线程对现场
    zmq::AsyncWorker::ptr awp = make_shared<zmq::AsyncWorker>();
    //2.实例化连接对象
    zmq::Connection::ptr conn = make_shared<zmq::Connection>("127.0.0.1",8085,awp);
    //3.通过连接创建信道
    zmq::Channel::ptr channel = conn->openChannel();
    //4.通过信道提供的服务完成所需
    //4.1声明一个交换机 exchange1,交换机类型为广播模式
    google::protobuf::Map<string,string> tmp_map;
    channel->declareExchange("exchange1",zmq::ExchangeType::FANOUT,true,false,tmp_map);

    //4.2声明两个队列
    channel->declareQueue("queue1",true,false,false,tmp_map);
    channel->declareQueue("queue2",true,false,false,tmp_map);

    //4.3绑定 queue1-exchange1 且bing_key设置为queue1
    channel->queueBind("exchange1","queue1","queue1");
    channel->queueBind("exchange1","queue2","news.music.#");
    //6.订阅队列消息
    auto functor = std::bind(callBack,channel,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3);
    channel->basicConsume("consumer1",argv[1],false,functor);
    //7.关闭信道
    while(1)
    {
        std::this_thread::sleep_for(std::chrono::seconds(3));
    }
    conn->closeChannel(channel);
 
    return 0;
}

直接交换模式测试

主要测试方案:

  • 同样声明一个交换机和两个队列,交换机是直接交换模式
  • 直接交换模式下,直接比较routing_key和binding_key是否相同
  • 我们将消息设置为跟queue2的binding_key相同
  • 因此分别启动两个订阅客户端分别订阅queue1、queue2,发布客户端发布消息之后应该是只有订阅了queue2的客户端能收到消息。

发布客户端:

cpp 复制代码
#include "asyncWorker.hpp"
#include "channel.hpp"
#include"connection.hpp"
#include <google/protobuf/map.h>
#include <memory>
#include <string>

int main()
{
    //1.实例化异步工作线程对现场
    zmq::AsyncWorker::ptr awp = make_shared<zmq::AsyncWorker>();
    //2.实例化连接对象
    zmq::Connection::ptr conn = make_shared<zmq::Connection>("127.0.0.1",8085,awp);
    //3.通过连接创建信道
    zmq::Channel::ptr channel = conn->openChannel();
    //4.通过信道提供的服务完成所需
    //4.1声明一个交换机 exchange1,交换机类型为直接模式
    google::protobuf::Map<string,string> tmp_map;
    channel->declareExchange("exchange1",zmq::ExchangeType::DIRECT,true,false,tmp_map);
    //4.2声明两个队列
    channel->declareQueue("queue1",true,false,false,tmp_map);

    channel->declareQueue("queue2",true,false,false,tmp_map);
    //4.3绑定 queue1-exchange1 且bing_key设置为queue1
    channel->queueBind("exchange1","queue1","queue1");
    channel->queueBind("exchange1","queue2","news.music.#");
    //5. 循环向交换机发布消息
    for(int i = 0 ; i < 10 ; i++)
    {
        //直接
        zmq::BasicProperties bp;
        bp.set_id(zmq::uuidHelper::uuid());
        bp.set_delivery_mode(zmq::DeliveryMode::DURABLE);
        bp.set_routing_key("news.music.#");
        channel->basicPublish("exchange1",&bp,"Hello Queue-"+to_string(i));
    }

    //6.关闭信道
    conn->closeChannel(channel);
    return 0;
}

消费客户端:

cpp 复制代码
#include "asyncWorker.hpp"
#include "channel.hpp"
#include"connection.hpp"
#include <functional>
#include <google/protobuf/map.h>
#include <memory>
#include<thread>
#include <string>
#include<iostream>
#include "../mqcommon/logger.hpp"
using namespace std;

void callBack(zmq::Channel::ptr channel,const string& tag,const zmq::BasicProperties* bp,const string& body)
{
   cout << tag << "消费了消息:" << body << endl;
   //应答
   channel->basicAck(bp->id());
}

int main(int argc,char* argv[])
{
    if(argc!=2)
    {
        DBG_LOG("Usage: ./consume_client queue_anme");
        exit(1);
    }
    //1.实例化异步工作线程对现场
    zmq::AsyncWorker::ptr awp = make_shared<zmq::AsyncWorker>();
    //2.实例化连接对象
    zmq::Connection::ptr conn = make_shared<zmq::Connection>("127.0.0.1",8085,awp);
    //3.通过连接创建信道
    zmq::Channel::ptr channel = conn->openChannel();
    //4.通过信道提供的服务完成所需
    //4.1声明一个交换机 exchange1,交换机类型为广播模式
    google::protobuf::Map<string,string> tmp_map;
    channel->declareExchange("exchange1",zmq::ExchangeType::FANOUT,true,false,tmp_map);

    //4.2声明两个队列
    channel->declareQueue("queue1",true,false,false,tmp_map);
    channel->declareQueue("queue2",true,false,false,tmp_map);

    //4.3绑定 queue1-exchange1 且bing_key设置为queue1
    channel->queueBind("exchange1","queue1","queue1");
    channel->queueBind("exchange1","queue2","news.music.#");
    //6.订阅队列消息
    auto functor = std::bind(callBack,channel,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3);
    channel->basicConsume("consumer1",argv[1],false,functor);
    //7.关闭信道
    while(1)
    {
        std::this_thread::sleep_for(std::chrono::seconds(3));
    }
    conn->closeChannel(channel);
 
    return 0;
}

主题交换模式测试

  • 发布三种routing_key消息,分别是news.music.queue、news.music.pop、news.sport
  • 因此订阅queue1的收不到任何消息,订阅queue2的只能收到前两种

发布客户端:

cpp 复制代码
#include "asyncWorker.hpp"
#include "channel.hpp"
#include"connection.hpp"
#include <google/protobuf/map.h>
#include <memory>
#include <string>

int main()
{
    //1.实例化异步工作线程对现场
    zmq::AsyncWorker::ptr awp = make_shared<zmq::AsyncWorker>();
    //2.实例化连接对象
    zmq::Connection::ptr conn = make_shared<zmq::Connection>("127.0.0.1",8085,awp);
    //3.通过连接创建信道
    zmq::Channel::ptr channel = conn->openChannel();
    //4.通过信道提供的服务完成所需
    //4.1声明一个交换机 exchange1,交换机类型为广播模式
    google::protobuf::Map<string,string> tmp_map;
    channel->declareExchange("exchange1",zmq::ExchangeType::FANOUT,true,false,tmp_map);
    //4.2声明两个队列
    channel->declareQueue("queue1",true,false,false,tmp_map);

    channel->declareQueue("queue2",true,false,false,tmp_map);
    //4.3绑定 queue1-exchange1 且bing_key设置为queue1
    channel->queueBind("exchange1","queue1","queue1");
    channel->queueBind("exchange1","queue2","news.music.#");
    //5. 循环向交换机发布消息
    for(int i = 0 ; i < 10 ; i++)
    {
        //直接
        zmq::BasicProperties bp;
        bp.set_id(zmq::uuidHelper::uuid());
        bp.set_delivery_mode(zmq::DeliveryMode::DURABLE);
        bp.set_routing_key("news.music.queue");
        channel->basicPublish("exchange1",&bp,"Hello Queue-"+to_string(i));
    }
    zmq::BasicProperties bp;
    bp.set_id(zmq::uuidHelper::uuid());
    bp.set_delivery_mode(zmq::DeliveryMode::DURABLE);
    bp.set_routing_key("news.music.pop");
    channel->basicPublish("exchange1",&bp,"Hello pop");

    bp.set_id(zmq::uuidHelper::uuid());
    bp.set_delivery_mode(zmq::DeliveryMode::DURABLE);
    bp.set_routing_key("news.sport");
    channel->basicPublish("exchange1",&bp,"Hello sport");
    //6.关闭信道
    conn->closeChannel(channel);
    return 0;
}

消费客户端:

cpp 复制代码
#include "asyncWorker.hpp"
#include "channel.hpp"
#include"connection.hpp"
#include <functional>
#include <google/protobuf/map.h>
#include <memory>
#include<thread>
#include <string>
#include<iostream>
#include "../mqcommon/logger.hpp"
using namespace std;

void callBack(zmq::Channel::ptr channel,const string& tag,const zmq::BasicProperties* bp,const string& body)
{
   cout << tag << "消费了消息:" << body << endl;
   //应答
   channel->basicAck(bp->id());
}

int main(int argc,char* argv[])
{
    if(argc!=2)
    {
        DBG_LOG("Usage: ./consume_client queue_anme");
        exit(1);
    }
    //1.实例化异步工作线程对现场
    zmq::AsyncWorker::ptr awp = make_shared<zmq::AsyncWorker>();
    //2.实例化连接对象
    zmq::Connection::ptr conn = make_shared<zmq::Connection>("127.0.0.1",8085,awp);
    //3.通过连接创建信道
    zmq::Channel::ptr channel = conn->openChannel();
    //4.通过信道提供的服务完成所需
    //4.1声明一个交换机 exchange1,交换机类型为广播模式
    google::protobuf::Map<string,string> tmp_map;
    channel->declareExchange("exchange1",zmq::ExchangeType::TOPIC,true,false,tmp_map);

    //4.2声明两个队列
    channel->declareQueue("queue1",true,false,false,tmp_map);
    channel->declareQueue("queue2",true,false,false,tmp_map);

    //4.3绑定 queue1-exchange1 且bing_key设置为queue1
    channel->queueBind("exchange1","queue1","queue1");
    channel->queueBind("exchange1","queue2","news.music.#");
    //6.订阅队列消息
    auto functor = std::bind(callBack,channel,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3);
    channel->basicConsume("consumer1",argv[1],false,functor);
    //7.关闭信道
    while(1)
    {
        std::this_thread::sleep_for(std::chrono::seconds(3));
    }
    conn->closeChannel(channel);
 
    return 0;
}
相关推荐
G31135422731 小时前
深度学习中适合长期租用的高性价比便宜的GPU云服务器有哪些?
服务器·人工智能·深度学习
北冥湖畔的燕雀1 小时前
std之list
数据结构·c++·list
('-')1 小时前
《从根上理解MySQL》第一章学习笔记
笔记·学习·mysql
q***7481 小时前
在Linux系统上使用nmcli命令配置各种网络(有线、无线、vlan、vxlan、路由、网桥等)
linux·服务器·网络
周杰伦_Jay2 小时前
【RPC:分布式跨节点透明通信协议】【Raft:简单易实现的分布式共识算法】
分布式·rpc·共识算法
我也要当昏君2 小时前
4.1.8 【2022 统考真题】
运维·服务器·网络
d111111111d2 小时前
STM32外设学习-串口发送数据-接收数据(笔记)
笔记·stm32·学习
2301_807583232 小时前
zabbix监控ES集群健康状态并触发钉钉告警
linux·zabbix
Elias不吃糖2 小时前
eventfd 初认识Reactor/多线程服务器的关键唤醒机制
linux·服务器·c++·学习