项目第十二弹:功能联调

项目第十二弹:功能联调

  • 一、发布订阅功能测试
    • 1.生产者
    • 2.消费者
    • 3.演示
    • 4.持久化信息查看
      • 1.消息
      • 2.SQLite3数据库
  • 二、持久化恢复测试
    • 1.代码
    • 2.gc
    • 3.演示
  • 三、虚拟机和信道隔离测试
    • 1.责任划分
    • 2.如何测试
    • 3.生产者
    • 4.消费者
    • 5.演示

一、发布订阅功能测试

我们直接上TOPIC交换机类型了,主题交换没事的话,那么DIRECT和FANOUT肯定也没事
路由匹配模块我们也进行过单元测试,不可能有任何问题
服务器代码:

#include "broker.hpp"int main()
{ns_mq::Server server(8888);server.start();return 0;
}

1.生产者

#include "connection.hpp"
using namespace ns_mq;int main()
{AsyncWorker::ptr worker = std::make_shared<AsyncWorker>();// 1. 创建连接和信道Connection::ptr conn = std::make_shared<Connection>("127.0.0.1", 8888, worker);Channel::ptr cp = conn->OpenChannel();// 2. 创建虚拟机,交换机,队列,并进行绑定cp->declareVirtualHost("host1", "./host1/resource.db", "./host1/message");cp->declareExchange("host1", "exchange1", TOPIC, true, false, {});cp->declareMsgQueue("host1", "queue1", true, false, false, {});cp->declareMsgQueue("host1", "queue2", true, false, false, {});cp->bind("host1", "exchange1", "queue1", "news.sport.#");cp->bind("host1", "exchange1", "queue2", "news.*.zhangsan");// 3. 发送10条消息BasicProperities bp;bp.set_mode(DURABLE);bp.set_routing_key("news.sport.basketball");for (int i = 0; i < 10; i++){bp.set_msg_id(UUIDHelper::uuid());cp->BasicPublish("host1", "exchange1", &bp, "Hello -" + std::to_string(i));}bp.set_routing_key("news.singer.zhangsan");bp.set_msg_id(UUIDHelper::uuid());cp->BasicPublish("host1", "exchange1", &bp, "singer zhangsan");bp.set_routing_key("news.sportsman.zhangsan");bp.set_msg_id(UUIDHelper::uuid());cp->BasicPublish("host1", "exchange1", &bp, "sportsman zhangsan");// 4. 关闭信道conn->CloseChannel(cp);return 0;
}

2.消费者

#include "connection.hpp"
using namespace ns_mq;// 因为要拿到信道才能进行确认,所以这里需要把Channel::ptr bind过来
void Callback(const Channel::ptr &cp, const std::string &consumer_tag, const BasicProperities *bp, const std::string &body)
{// 1. 消费消息std::string id;if (bp != nullptr){id = bp->msg_id();}std::cout << consumer_tag << " 消费了消息: " << body << ", 消息ID: " << id << "\n";// 2. 确认消息if (bp != nullptr)cp->BasicAck(id);
}// consumer_tag queue_name
int main(int argc, char *argv[])
{if (argc != 3){std::cout << "Usage: " << argv[0] << " consumer_tag queue_name\n";return 1;}AsyncWorker::ptr worker = std::make_shared<AsyncWorker>();// 1. 创建连接和信道Connection::ptr conn = std::make_shared<Connection>("127.0.0.1", 8888, worker);Channel::ptr cp = conn->OpenChannel();// 2. 创建虚拟机,交换机,队列,并进行绑定cp->declareVirtualHost("host1", "./host1/resource.db", "./host1/message");cp->declareExchange("host1", "exchange1", TOPIC, true, false, {});cp->declareMsgQueue("host1", "queue1", true, false, false, {});cp->declareMsgQueue("host1", "queue2", true, false, false, {});cp->bind("host1", "exchange1", "queue1", "news.sport.#");cp->bind("host1", "exchange1", "queue2", "news.*.zhangsan");// 3. 创建消费者cp->BasicConsume("host1", argv[1], argv[2],std::bind(Callback, cp, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), false);// 4. 等待消息while (true){std::this_thread::sleep_for(std::chrono::seconds(1000));}// 5. 关闭信道conn->CloseChannel(cp);return 0;
}

3.演示

在这里插入图片描述

4.持久化信息查看

1.消息

在这里插入图片描述

2.SQLite3数据库

在这里插入图片描述

二、持久化恢复测试

1.代码

生产者:

#include "connection.hpp"
using namespace ns_mq;int main()
{AsyncWorker::ptr worker = std::make_shared<AsyncWorker>();// 1. 创建连接和信道Connection::ptr conn = std::make_shared<Connection>("127.0.0.1", 8888, worker);Channel::ptr cp = conn->OpenChannel();// 2. 创建虚拟机,交换机,队列,并进行绑定// cp->declareVirtualHost("host1", "./host1/resource.db", "./host1/message");// cp->declareExchange("host1", "exchange1", TOPIC, true, false, {});// cp->declareMsgQueue("host1", "queue1", true, false, false, {});// cp->declareMsgQueue("host1", "queue2", true, false, false, {});// cp->bind("host1", "exchange1", "queue1", "news.sport.#");// cp->bind("host1", "exchange1", "queue2", "news.*.zhangsan");// 3. 发送10条消息BasicProperities bp;bp.set_mode(DURABLE);bp.set_routing_key("news.sport.basketball");for (int i = 0; i < 10; i++){bp.set_msg_id(UUIDHelper::uuid());cp->BasicPublish("host1", "exchange1", &bp, "Hello -" + std::to_string(i));}bp.set_routing_key("news.singer.zhangsan");bp.set_msg_id(UUIDHelper::uuid());cp->BasicPublish("host1", "exchange1", &bp, "singer zhangsan");bp.set_routing_key("news.sportsman.zhangsan");bp.set_msg_id(UUIDHelper::uuid());cp->BasicPublish("host1", "exchange1", &bp, "sportsman zhangsan");// 4. 关闭信道conn->CloseChannel(cp);return 0;
}

消费者:

#include "connection.hpp"
using namespace ns_mq;// 因为要拿到信道才能进行确认,所以这里需要把Channel::ptr bind过来
void Callback(const Channel::ptr &cp, const std::string &consumer_tag, const BasicProperities *bp, const std::string &body)
{// 1. 消费消息std::string id;if (bp != nullptr){id = bp->msg_id();}std::cout << consumer_tag << " 消费了消息: " << body << ", 消息ID: " << id << "\n";// 2. 确认消息if (bp != nullptr)cp->BasicAck(id);
}// consumer_tag queue_name
int main(int argc, char *argv[])
{if (argc != 3){std::cout << "Usage: " << argv[0] << " consumer_tag queue_name\n";return 1;}AsyncWorker::ptr worker = std::make_shared<AsyncWorker>();// 1. 创建连接和信道Connection::ptr conn = std::make_shared<Connection>("127.0.0.1", 8888, worker);Channel::ptr cp = conn->OpenChannel();// 2. 创建虚拟机,交换机,队列,并进行绑定// cp->declareVirtualHost("host1", "./host1/resource.db", "./host1/message");// cp->declareExchange("host1", "exchange1", TOPIC, true, false, {});// cp->declareMsgQueue("host1", "queue1", true, false, false, {});// cp->declareMsgQueue("host1", "queue2", true, false, false, {});// cp->bind("host1", "exchange1", "queue1", "news.sport.#");// cp->bind("host1", "exchange1", "queue2", "news.*.zhangsan");// 3. 创建消费者cp->BasicConsume("host1", argv[1], argv[2],std::bind(Callback, cp, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), false);// 4. 等待消息while (true){std::this_thread::sleep_for(std::chrono::seconds(1000));}// 5. 关闭信道conn->CloseChannel(cp);return 0;
}

2.gc

在这里插入图片描述

3.演示

不再次创建任何交换机,队列,绑定信息,看是否能够继续发布消息
完美:
在这里插入图片描述

三、虚拟机和信道隔离测试

下面我们开多线程测一测信道和虚拟机:
信道实现了访问上的隔离,Vhost实现了资源上的隔离
两者配合使用,我们便能够在一个进程当中通过多线程完美的实现RabbitMQ的用户隔离

1.责任划分

RabbitMQ当中,多线程使用不同的信道,如果两个线程都对同一个队列进行操作,比如,一个线程向该队列绑定消费者,另一个线程删除了该队列。按道理来说,即使出现了问题,也不能怪RabbitMQ的信道,不能怪RabbitMQ。

因为你用户使用多线程没有好好使用,在你的代码当中,那个队列已经同时被两个线程访问了,而且某个线程还对该队列进行了写操作,因此这个队列对两个线程来说就已经是临界资源了,你访问这个临界资源不加锁,这是你用户的问题,不是RabbitMQ的问题

其实就像信号量一样,约定好哪个线程负责哪些资源,对资源/任务进行无冲突的划分即可这是用户使用多线程访问RabbitMQ必须要做的,这也是多线程并发编程最基本的原则

2.如何测试

在这里插入图片描述
虚拟机跟虚拟机之间是具有隔离性的,不同虚拟机之间可以创建同名交换机,队列,绑定信息,可以具有同名消费者,同msg_id的消息等等…

但是在同一虚拟机当中,不能具有同名交换机…等等

因此我们就让不同虚拟机有同名的交换机,队列,绑定信息…
就是这么测,测的就是虚拟机和信道的隔离性

3.生产者

#include "connection.hpp"
using namespace ns_mq;
#include <thread>
#include <vector>
using namespace std;// host1
void publisher1(const Connection::ptr &conn, const std::string &thread_name)
{// 1. 创建信道Channel::ptr cp = conn->OpenChannel();// 2. 创建虚拟机,交换机,队列,并进行绑定cp->declareVirtualHost("host1", "./host1/resource.db", "./host1/message");cp->declareExchange("host1", "exchange1", TOPIC, true, false, {});cp->declareMsgQueue("host1", "queue1", true, false, false, {});//cp->declareMsgQueue("host1", "queue2", true, false, false, {});cp->bind("host1", "exchange1", "queue1", "news.sport.#");//cp->bind("host1", "exchange1", "queue2", "news.*.zhangsan");// 3. 发送10条消息BasicProperities bp;bp.set_mode(DURABLE);bp.set_routing_key("news.sport.basketball");for (int i = 0; i < 5; i++){bp.set_msg_id(UUIDHelper::uuid());cp->BasicPublish("host1", "exchange1", &bp, "Hello -" + std::to_string(i));}// 4. 关闭信道conn->CloseChannel(cp);
}// host2
void publisher2(const Connection::ptr &conn, const std::string &thread_name)
{// 1. 创建信道Channel::ptr cp = conn->OpenChannel();// 2. 创建虚拟机,交换机,队列,并进行绑定cp->declareVirtualHost("host2", "./host2/resource.db", "./host2/message");cp->declareExchange("host2", "exchange1", TOPIC, true, false, {});cp->declareMsgQueue("host2", "queue1", true, false, false, {});cp->declareMsgQueue("host2", "queue2", true, false, false, {});cp->bind("host2", "exchange1", "queue1", "news.sport.#");cp->bind("host2", "exchange1", "queue2", "news.*.zhangsan");// 3. 发送10条消息BasicProperities bp;bp.set_mode(DURABLE);bp.set_routing_key("news.sport.basketball");for (int i = 0; i < 5; i++){bp.set_msg_id(UUIDHelper::uuid());cp->BasicPublish("host2", "exchange1", &bp, "Hello -" + std::to_string(i));}// 4. 关闭信道conn->CloseChannel(cp);
}int main()
{AsyncWorker::ptr worker = std::make_shared<AsyncWorker>();Connection::ptr myconn = std::make_shared<Connection>("127.0.0.1", 8888, worker);vector<thread> thread_v;thread_v.push_back(thread(publisher1, myconn, "thread1"));thread_v.push_back(thread(publisher2, myconn, "thread2"));for(auto& t:thread_v)t.join();return 0;
}

4.消费者

#include "connection.hpp"
using namespace ns_mq;
#include <thread>
#include <vector>
using namespace std;// 因为要拿到信道才能进行确认,所以这里需要把Channel::ptr bind过来
void Callback(const Channel::ptr &cp, const std::string &consumer_tag, const BasicProperities *bp, const std::string &body)
{// 1. 消费消息std::string id;if (bp != nullptr){id = bp->msg_id();}std::cout << consumer_tag << " 消费了消息: " << body << ", 消息ID: " << id << "\n";// 2. 确认消息if (bp != nullptr)std::cout << cp->BasicAck(id) << "\n";
}void consumer1(const Connection::ptr &conn, const std::string &thread_name)
{Channel::ptr cp = conn->OpenChannel();std::cout  << "consumer1: 信道ID:" << cp->cid() << "\n";// 2. 创建虚拟机,交换机,队列,并进行绑定cp->declareVirtualHost("host1", "./host1/resource.db", "./host1/message");cp->declareExchange("host1", "exchange1", TOPIC, true, false, {});cp->declareMsgQueue("host1", "queue1", true, false, false, {});//cp->declareMsgQueue("host1", "queue2", true, false, false, {});cp->bind("host1", "exchange1", "queue1", "news.sport.#");//cp->bind("host1", "exchange1", "queue2", "news.*.zhangsan");// 3. 创建消费者cp->BasicConsume("host1", "consumer1", "queue1",std::bind(Callback, cp, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), false);// 4. 等待消息while (true){std::this_thread::sleep_for(std::chrono::seconds(1000));}// 5. 关闭信道conn->CloseChannel(cp);
}void consumer2(const Connection::ptr &conn, const std::string &thread_name)
{Channel::ptr cp = conn->OpenChannel();std::cout << "consumer2: 信道ID:" << cp->cid() << "\n";// 2. 创建虚拟机,交换机,队列,并进行绑定cp->declareVirtualHost("host2", "./host2/resource.db", "./host2/message");cp->declareExchange("host2", "exchange1", TOPIC, true, false, {});cp->declareMsgQueue("host2", "queue1", true, false, false, {});cp->declareMsgQueue("host2", "queue2", true, false, false, {});cp->bind("host2", "exchange1", "queue1", "news.sport.#");cp->bind("host2", "exchange1", "queue2", "news.*.zhangsan");// 3. 创建消费者cp->BasicConsume("host2", "consumer2", "queue1",std::bind(Callback, cp, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), false);// 4. 等待消息while (true){std::this_thread::sleep_for(std::chrono::seconds(1000));}// 5. 关闭信道conn->CloseChannel(cp);
}// consumer_tag queue_name
int main()
{AsyncWorker::ptr worker = std::make_shared<AsyncWorker>();// 1. 创建连接和信道Connection::ptr conn = std::make_shared<Connection>("127.0.0.1", 8888, worker);vector<thread> thread_v;thread_v.push_back(thread(consumer1, conn, "thread1"));thread_v.push_back(thread(consumer2, conn, "thread2"));for (auto &t : thread_v)t.join();return 0;
}

5.演示

在这里插入图片描述
在这里插入图片描述
可见,正是因为RabbitMQ有信道和虚拟机,所以使用体验大幅度上升,功能更加灵活,他们两个是RabbitMQ非常好的设计

信道:

  1. 性能优化(网络层面:连接细分为信道,从而复用TCP连接)
  2. 细粒度控制(服务层面:通过信道来进行服务的提供,【会话管理】更加精细化)
  3. 资源隔离(访问句柄的资源隔离)

虚拟机:

  1. 多租户支持(实际的资源隔离)
  2. 配置灵活(用户认证,权限管理…)

以上就是项目第十二弹:功能联调的全部内容

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/147012.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL中的逻辑条件

逻辑条件组合两个比较条件的结果来产生一个基于这些条件的单个的结果&#xff0c;或者逆转一个单个条件的结果。当所有条件的结果为真时&#xff0c;返回行。 SQL的三个逻辑运算符是&#xff1a; AND、OR、NOT 可以在WHERE子句中用AND和OR运算符使用多个条件。 示例一&#…

惊爆!高通要收购英特尔,巨头也会被时代抛弃!

今天看到的外媒消息&#xff0c;高通要收购英特尔&#xff0c;看到消息的时候&#xff0c;其实&#xff0c;还是挺吃惊的。 高通是移动芯片的王者&#xff0c;英特尔是 PC 芯片的王者。当然了&#xff0c;英特尔这个可能需要再加上两个字&#xff1a;曾经的 PC 芯片王者。 其实…

植物大战僵尸【源代码分享+核心思路讲解】

植物大战僵尸已经正式完结&#xff0c;今天和大家分享一下&#xff0c;话不多说&#xff0c;直接上链接&#xff01;&#xff01;&#xff01;&#xff08;如果大家在运行这个游戏遇到了问题或者bug&#xff0c;那么请私我谢谢&#xff09; 大家写的时候可以参考一下我的代码思…

在VMware16中安装Windows 10:完整教程

在VMware中安装Windows 10&#xff1a;完整教程 1.安装环境准备2.创建虚拟机 1.安装环境准备 1.虚拟机: VMware-workstation-full-16.2.2-19200509 2.系统镜像:win10 2.创建虚拟机 1.自定义 2.下一步 3.稍后安装系统 3.默认下一步 4.虚拟机取名和选择存放路径(按需更改…

利士策分享,江西新余悲剧背后的深思:安全与责任的重构

利士策分享&#xff0c;江西新余悲剧背后的深思&#xff1a;安全与责任的重构 在这个信息瞬息万变的时代&#xff0c;每一次突发事件都能迅速触动社会的神经&#xff0c; 而江西新余近期发生的悲剧&#xff0c;更是让我们在悲痛之余&#xff0c;不得不深刻反思安全管理与社会…

AVL树与红黑树

目录 AVL树 AVL树节点的定义 AVL树的插入 AVL树的旋转 右单旋 左单旋 左右双旋 右左双旋 AVL树的验证 AVL树的性能 红黑树 红黑树的性质 红黑树节点的定义 红黑树结构 红黑树的插入操作 按照二叉搜索的树规则插入新节点 检测新节点插入后&#xff0c;红黑树的性…

升级你的HarmonyOS体验:一窥功能引导与拖拽交换的独家技巧

文章目录 前言项目目录结构开发流程主要步骤讲解关键配置Index.ets 页面讲解高光组件相关HeaderApp 总结 前言 在当今的移动应用开发领域&#xff0c;为了提供更加友好和直观的用户体验&#xff0c;开发者们通常会集成多种交互功能来增强应用的互动性和易用性。在这些功能中&a…

【机器学习】12-决策树1——概念、特征选择

机器学习10-决策树1 学习样本的特征&#xff0c;将样本划分到不同的类别&#xff08;分类问题&#xff09;或预测连续的数值&#xff08;回归问题&#xff09;。 选择特征&#xff0c;划分数据集&#xff0c;划分完成形成模型&#xff08;树结构&#xff09;&#xff0c;一个…

JavaSE——多线程基础

概述 现代操作系统&#xff08;Windows&#xff0c;macOS&#xff0c;Linux&#xff09;都可以执行多任务。多任务就是同时允许多个任务。例如&#xff1a;播放音乐的同时&#xff0c;浏览器可以进行文件下载&#xff0c;同时可以进行QQ消息的收发。 CPU执行代码都是一条一条顺…

Matlab R2018a怎么下载安装?Matlab R2018a保姆级详细安装教程

Matlab R2018a下载方法&#xff1a; Matlab R2018a安装教程&#xff1a; 1、右击下载好的压缩包&#xff0c;选择解压到Matlab R2018a 2、打开文件夹【R2018a_win64】&#xff0c;右击下面的setup.exe&#xff0c;选择【以管理员身份运行】 3、点击选择【使用文件安装密钥】&a…

IDEA连接数据库报错:Access denied for user ****

使用IDEA开发时&#xff0c;通过Databse连接数据库。多次连接报错&#xff1a;Access denied for user **** 如下所示&#xff1a; ​ ‍ ‍ ​ ‍ 花了不少时间排查&#xff0c;确认账号、密码&#xff0c;后面发现账号后多了个空格&#xff0c;而且不容易发现&#xf…

proteus仿真软件简体中文版网盘资源下载(附教程)

对于电子通信专业的小伙伴来说&#xff0c;今天文章的标题应该不会陌生。Proteus是一款具有广泛应用的仿真软件&#xff0c;它的功能非常强大&#xff0c;适用于所有单片机的仿真工作&#xff0c;能够从原理图、调试、到与电路的协同仿真一条龙全部搞定&#xff0c;受到所有用户…

交叉熵损失函数的使用

交叉熵损失函数 交叉熵损失函数&#xff08;Cross-Entropy Loss&#xff09;&#xff0c;也称为对数损失&#xff08;Log Loss&#xff09;&#xff0c;是机器学习和深度学习中常用的损失函数之一&#xff0c;尤其在分类问题中。它衡量的是模型预测的概率分布与真实标签的概率…

使用Properties

a.特点 i.它的Key-Value一般都是String-String类型的&#xff0c;可以用Map<String, String>表示。 ii.Java标准库提供Properties来表示一组“配置”。 iii.读写Properties时&#xff0c;使用getProperty()和setProperty()方法&#xff0c;不要调用继承自HashTabled的ge…

开始场景的制作+气泡特效的添加

3D场景或2D场景的切换 1.新建项目时选择3D项目或2D项目 2.如下图操作&#xff1a; 开始前的固有流程 按照如下步骤进行操作&#xff0c;于步骤3中更改Company Name等属性&#xff1a; 本案例分辨率可以如下设置&#xff0c;有能力者可根据需要自行调整&#xff1a; 场景制作…

轻掺杂漏极(LDD)技术

轻掺杂漏极&#xff08;LDD&#xff09;是一种低能量、低电流的注入工艺&#xff0c;通过该工艺在栅极附近形成浅结&#xff0c;以减少靠近漏极处的垂直电场。对于亚微米MOSFET来说&#xff0c;LDD是必需的&#xff0c;以便抑制热电子效应&#xff0c;这种效应会导致器件退化并…

Python进阶学习笔记(一)对象

1.对象模型 在面向对象理论中类和对象是不同的概念&#xff0c;而在python中类也是对象&#xff0c;叫做类型对象。 所以python中的类&#xff0c;实例对象&#xff0c;类型都是对象。 元类型&#xff1a; 在python中实例对象的类型为对应类型的对象&#xff0c;而类型的对象…

14. PEFT:在大模型中快速应用 LoRA

如果你对LoRA还没有一个直观的概念&#xff0c;可以回看这篇文章&#xff1a;《3. 认识 LoRA&#xff1a;从线性层到注意力机制》。 我们将在这里进一步探讨如何快速地在大型预训练模型中应用 LoRA&#xff0c;并解答可能存在的问题&#xff0c;包括&#xff1a; peft 和 lora …

博途TIA v18下载时,需要重启才能安装下载路径是灰色改不了

一、需要重启才能安装 删除下面注册表P开头的文件&#xff1a; 二、下载路径是灰色改不了 注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion里找到C:\Program Files或者C:\Program Files&#xff08;x86&#xff09;&#xff0c;具体哪个看安装的时候对应…

TikTokDownloader 开源项目操作教程

TikTokDownloader TikTokDownloader 是一个开源的多功能视频下载工具&#xff0c;它专门用于从抖音和TikTok平台下载无水印的视频、图集和直播内容。这个工具支持批量下载账号作品、收藏内容&#xff0c;并可以采集详细数据。它提供了命令行和Web界面&#xff0c;具有多线程下…