【仿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;
}
相关推荐
礼拜天没时间.1 分钟前
Docker基础操作——镜像与容器管理
linux·运维·服务器·docker·容器·centos
Jacob程序员3 分钟前
达梦数据库私有服务配置指南
linux·服务器·数据库
卡兰芙的微笑4 分钟前
编译鸿蒙6.0release版本出错
学习
近津薪荼5 分钟前
优选算法——滑动窗口3(子数组)
c++·学习·算法
FPGA小迷弟6 分钟前
基于FPGA实现HDMI接口,选型/核心技术
学习·fpga开发·verilog·fpga·modelsim
方便面不加香菜7 分钟前
c++入门基础
c++
day day day ...10 分钟前
easyExcel和poi分别处理不同标准的excel
java·服务器·excel
Tony Bai13 分钟前
Git 即数据库:Beads (bd) —— 专为 AI Agent 打造的分布式任务追踪引擎
数据库·人工智能·分布式·git
新时代牛马13 分钟前
CANopenNode 接口及 CANopenLinux 完整实现
网络·学习
阿常呓语13 分钟前
ls 命令详解
linux·运维·服务器·ls