virtual_host.hpp模块

news2024/9/21 22:58:07

目录

一.VirtualHost虚拟机模块介绍

二.VirtualHost的实现

1. 类概述

2. 交换机操作

3. 队列操作

4. 绑定操作

5. 消息操作

6. 清理操作

总结

三.全部代码

一.VirtualHost虚拟机模块介绍

虚拟机是对之前几个数据管理模块的整合,并封装了之前的一些操作。
实际上虚拟机也可以有很多个,这里为了操作简便,整个项目中只有一个虚拟机对象。

二.VirtualHost的实现

1. 类概述

VirtualHost 类代表一个虚拟主机的抽象,主要用于管理消息队列系统的核心模块,如交换机、消息队列、绑定关系和消息管理。每个虚拟主机有自己独立的资源,通过类成员 _emp_mqmp_bmp_mmp 来管理相应的交换机、队列、绑定和消息。
保证了每个虚拟机内部数据的独立性。

    private:
        std::string _name;          // 虚拟主机名称
        ExchangeManager::ptr _emp;  // 交换机管理
        MsgQueueManager::ptr _mqmp; // 队列管理
        BindingManager::ptr _bmp;   // 绑定管理
        MessageManager::mmp _mmp;   // 消息管理

    public:
        using ptr = std::shared_ptr<VirtualHost>;
        VirtualHost(const std::string &name, const std::string &dbname, const std::string &msgdir)
            : _name(name),
              _emp(std::make_shared<ExchangeManager>(dbname)),
              _mqmp(std::make_shared<MsgQueueManager>(dbname)),
              _bmp(std::make_shared<BindingManager>(dbname)),
              _mmp(std::make_shared<MessageManager>(msgdir))
        {
            // _emp,_mqmp,_bmp创建后会自动recover
            // _mmp 需要手动调用initQueueMsg来recover文件中的数据
            // 1.获取_mqmp中的所有队列
            msgqueue_map queue_map = _mqmp->selectAll();
            //  2.遍历队列,recover每个队列的历史消息
            for (auto &kv : queue_map)
            {
                _mmp->initQueueMsg(kv.first);
            }
        }
  • 私有成员变量:

    • _name:虚拟主机的名称。
    • _emp:交换机管理器,管理虚拟主机内的所有交换机。
    • _mqmp:消息队列管理器,负责管理消息队列的声明与操作。
    • _bmp:绑定管理器,处理交换机与队列之间的绑定关系。
    • _mmp:消息管理器,负责管理消息的存储和传输。
  • 构造函数 VirtualHost():

    • 通过参数 namedbnamemsgdir 初始化虚拟主机名称、数据库名和消息存储目录。
    • 初始化成员 _emp, _mqmp, _bmp, _mmp,并通过各自的构造函数进行 recover 操作。
    • 通过 MsgQueueManager::selectAll() 获取所有队列,并使用 MessageManager::initQueueMsg() 还原队列的历史消息。
2. 交换机操作
        // 1. 声明/删除/查找交换机
        bool declareExchange(const std::string &name, msg::ExchangeType type,
                             bool durable,
                             bool auto_del,
                             const google::protobuf::Map<std::string, std::string> args)
        {
            return _emp->declareExchange(name, type, durable, auto_del, args);
        }
        bool removeExchange(const std::string &name)
        {
            // 删除交换机+对应的绑定
            _bmp->removeByExchange(name);
            return _emp->removeExchange(name);
        }
        bool exchangeExists(const std::string &name)
        {
            return _emp->exists(name);
        }
        Exchange::ptr selectExchange(const std::string &name)
        {
            return _emp->selectExchange(name);
        }
  • declareExchange():

    • 声明一个交换机,包括交换机名称、类型、持久性、自动删除等属性。实际操作由 ExchangeManager 类的 declareExchange() 函数完成。
  • removeExchange():

    • 删除一个交换机,调用 BindingManager::removeByExchange() 删除与该交换机关联的绑定关系,然后移除交换机。
  • exchangeExists()selectExchange():

    • 分别用于检查交换机是否存在以及获取交换机实例。
3. 队列操作
        // 2. 声明/删除队列
        bool declareQueue(const std::string &name, bool durable,
                          bool exclusive, bool auto_del,
                          const google::protobuf::Map<std::string, std::string> &args)
        {
            // 初始化队列的消息+队列
            _mmp->initQueueMsg(name);
            return _mqmp->declareQueue(name, durable, exclusive, auto_del, args);
        }
        bool removeQueue(const std::string &name)
        {
            // 删除队列的消息+对应的绑定+队列
            _mmp->destroyQueueMsg(name);
            _bmp->removeByQueue(name);
            return _mqmp->removeQueue(name);
        }
        bool queueExists(const std::string &name)
        {
            return _mqmp->exists(name);
        }
  • declareQueue():

    • 声明一个队列,同时初始化该队列的消息存储。通过调用 MessageManager::initQueueMsg() 处理消息初始化后,再由 MsgQueueManager::declareQueue() 声明队列。
  • removeQueue():

    • 删除队列时,调用 MessageManager::destroyQueueMsg() 删除该队列的所有消息,并移除与该队列相关的绑定关系。
  • queueExists():

    • 检查队列是否存在,封装了 MsgQueueManager::exists() 的调用。
4. 绑定操作
     // 3. 绑定/解绑
        bool bind(const std::string &ename, const std::string &qname, const std::string &key)
        {
            Exchange::ptr ep = _emp->selectExchange(ename);
            if (ep.get() == nullptr)
            {
                DLOG("进行队列绑定失败,交换机%s不存在!", ename.c_str());
                return false;
            }

            MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
            if (mqp.get() == nullptr)
            {
                DLOG("进行队列绑定失败,队列%s不存在!", qname.c_str());
                return false;
            }

            return _bmp->bind(ename, qname, key, ep->_durable && mqp->_durable);
        }
        bool unbind(const std::string &ename, const std::string &qname)
        {
            Exchange::ptr ep = _emp->selectExchange(ename);
            if (ep.get() == nullptr)
            {
                DLOG("进行队列绑定失败,交换机%s不存在!", ename.c_str());
                return false;
            }
            MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
            if (mqp.get() == nullptr)
            {
                DLOG("进行队列绑定失败,队列%s不存在!", qname.c_str());
                return false;
            }
            return _bmp->unbind(ename, qname);
        }
        bool bindExists(const std::string &ename, const std::string &qname)
        {
            return _bmp->exists(ename, qname);
        }
  • bind():

    • 实现队列与交换机之间的绑定,首先验证交换机和队列是否存在,然后通过 BindingManager::bind() 进行绑定。绑定关系通常涉及路由键(key)的定义。
  • unbind():

    • 解绑定操作,与 bind() 相对应,用于移除队列与交换机之间的绑定。
  • bindExists():

    • 检查特定的交换机与队列之间是否存在绑定关系。
  • selectByExchange():

    • 获取某一交换机下所有绑定的队列信息。该函数依赖于 BindingManager::selectByExchange() 来检索绑定数据。
5. 消息操作
    // 5. 消息的发布,获取,确认
        bool basicPublish(const std::string &qname, msg::BasicAttributes *bp, const std::string &body)
        {
            MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
            if (mqp.get() == nullptr)
            {
                DLOG("发布消息失败,队列%s不存在!", qname.c_str());
                return false;
            }
            // std::cout<<mqp->_name<<std::endl;
            return _mmp->insertMsg(qname, bp, body, mqp->_durable);
        }
        msg_ptr basicConsume(const std::string &qname)
        {
            return _mmp->front(qname);
        }
        void basicAck(const std::string &qname, const std::string &id)
        {
            _mmp->ack(qname, id);
        }
  • basicPublish():

    • 向指定队列发布消息,首先确认队列是否存在,若存在则调用 MessageManager::insertMsg() 插入消息。插入过程中,队列的持久性属性将被传递,以决定消息是否需要持久化到磁盘。
  • basicConsume():

    • 从指定队列中消费一条消息,调用 MessageManager::front() 获取队列中的第一条消息。
  • basicAck():

    • 确认消息已被成功消费,通过 MessageManager::ack() 标记该消息为已处理。
6. 清理操作
     void clear()
        {
            _emp->clear();
            _mqmp->clear();
            _bmp->clear();
            _mmp->clear();
        };
  • clear():
    • 清除虚拟主机内的所有资源,包括交换机、队列、绑定和消息。这通常用于重置或关闭虚拟主机时的资源清理操作。
总结

将消息队列系统中的各个模块分层管理。通过 VirtualHost 类将交换机、队列、绑定、消息管理等功能模块统一整合,提供了虚拟主机层级的操作接口。
在实现中,利用 shared_ptr 进行智能指针管理,保证了内存的安全使用。
同时,消息的持久化处理以及与消息队列工具的结合,提高了系统的可靠性。

三.全部代码

#pragma once
#include "exchange.hpp"
#include "msg_queue.hpp"
#include "binding.hpp"
#include "message.hpp"

namespace mq
{
    using msg_ptr = std::shared_ptr<msg::Message>;
    class VirtualHost
    {
    private:
        std::string _name;          // 虚拟主机名称
        ExchangeManager::ptr _emp;  // 交换机管理
        MsgQueueManager::ptr _mqmp; // 队列管理
        BindingManager::ptr _bmp;   // 绑定管理
        MessageManager::mmp _mmp;   // 消息管理

    public:
        using ptr = std::shared_ptr<VirtualHost>;
        VirtualHost(const std::string &name, const std::string &dbname, const std::string &msgdir)
            : _name(name),
              _emp(std::make_shared<ExchangeManager>(dbname)),
              _mqmp(std::make_shared<MsgQueueManager>(dbname)),
              _bmp(std::make_shared<BindingManager>(dbname)),
              _mmp(std::make_shared<MessageManager>(msgdir))
        {
            // _emp,_mqmp,_bmp创建后会自动recover
            // _mmp 需要手动调用initQueueMsg来recover文件中的数据
            // 1.获取_mqmp中的所有队列
            msgqueue_map queue_map = _mqmp->selectAll();
            // ILOG("数量:%ld",queue_map.size());
            //  2.遍历队列,recover每个队列的历史消息
            for (auto &kv : queue_map)
            {
                //ILOG("初始化:%s", kv.first.c_str());
                _mmp->initQueueMsg(kv.first);
            }
        }

        // 1. 声明/删除/查找交换机
        bool declareExchange(const std::string &name, msg::ExchangeType type,
                             bool durable,
                             bool auto_del,
                             const google::protobuf::Map<std::string, std::string> args)
        {
            return _emp->declareExchange(name, type, durable, auto_del, args);
        }
        bool removeExchange(const std::string &name)
        {
            // 删除交换机+对应的绑定
            _bmp->removeByExchange(name);
            return _emp->removeExchange(name);
        }
        bool exchangeExists(const std::string &name)
        {
            return _emp->exists(name);
        }
        Exchange::ptr selectExchange(const std::string &name)
        {
            return _emp->selectExchange(name);
        }
        // 2. 声明/删除队列
        bool declareQueue(const std::string &name, bool durable,
                          bool exclusive, bool auto_del,
                          const google::protobuf::Map<std::string, std::string> &args)
        {
            // 初始化队列的消息+队列
            _mmp->initQueueMsg(name);
            return _mqmp->declareQueue(name, durable, exclusive, auto_del, args);
        }
        bool removeQueue(const std::string &name)
        {
            // 删除队列的消息+对应的绑定+队列
            _mmp->destroyQueueMsg(name);
            _bmp->removeByQueue(name);
            return _mqmp->removeQueue(name);
        }
        bool queueExists(const std::string &name)
        {
            return _mqmp->exists(name);
        }
        // 3. 绑定/解绑
        bool bind(const std::string &ename, const std::string &qname, const std::string &key)
        {
            Exchange::ptr ep = _emp->selectExchange(ename);
            if (ep.get() == nullptr)
            {
                DLOG("进行队列绑定失败,交换机%s不存在!", ename.c_str());
                return false;
            }

            MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
            if (mqp.get() == nullptr)
            {
                DLOG("进行队列绑定失败,队列%s不存在!", qname.c_str());
                return false;
            }

            return _bmp->bind(ename, qname, key, ep->_durable && mqp->_durable);
        }
        bool unbind(const std::string &ename, const std::string &qname)
        {
            Exchange::ptr ep = _emp->selectExchange(ename);
            if (ep.get() == nullptr)
            {
                DLOG("进行队列绑定失败,交换机%s不存在!", ename.c_str());
                return false;
            }
            MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
            if (mqp.get() == nullptr)
            {
                DLOG("进行队列绑定失败,队列%s不存在!", qname.c_str());
                return false;
            }
            return _bmp->unbind(ename, qname);
        }
        bool bindExists(const std::string &ename, const std::string &qname)
        {
            return _bmp->exists(ename, qname);
        }
        // 4. 获取对应交换机的所有绑定信息(关联路由模块 )
        MsgQueueBindingMap selectByExchange(const std::string &ename)
        {
            if (!_emp->exists(ename))
            {
                ILOG("交换机:%s 不存在", ename.c_str());
                return MsgQueueBindingMap();
            }
            return _bmp->selectByExchange(ename);
        }

        // 5. 消息的发布,获取,确认
        bool basicPublish(const std::string &qname, msg::BasicAttributes *bp, const std::string &body)
        {
            MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
            if (mqp.get() == nullptr)
            {
                DLOG("发布消息失败,队列%s不存在!", qname.c_str());
                return false;
            }
            // std::cout<<mqp->_name<<std::endl;
            return _mmp->insertMsg(qname, bp, body, mqp->_durable);
        }
        msg_ptr basicConsume(const std::string &qname)
        {
            return _mmp->front(qname);
        }
        void basicAck(const std::string &qname, const std::string &id)
        {
            _mmp->ack(qname, id);
        }
        void clear()
        {
            _emp->clear();
            _mqmp->clear();
            _bmp->clear();
            _mmp->clear();
        };
    };
};

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

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

相关文章

安装Jmeter,配置jdk

注意点: java的jdk和jmeter的版本相匹配 ! ! ! 目前我使用的是1.8的的,jmeter使用的是5.6.3 JDK下载地址&#xff1a;https://www.oracle.com/cn/java/technologies/downloads 别管,直接傻瓜式安装点点就完了... 1.电脑-属性-高级系统设置-环境变量 2.系统变量-新建-变量…

如何理解:进程控制

文章目录 前言&#xff1a;进程创建&#xff1a;进程终止&#xff1a;如何终止进程&#xff1f;进程等待非阻塞等待&#xff1a; 总结&#xff1a; 前言&#xff1a; ​ 对于前面的地址空间的学习&#xff0c;我们现在了解到原来所谓变量的地址其实是虚拟地址&#xff0c;该虚…

python管理mysql(实现读写分离)及如何用Mycat读写分离

Day24 编写python代码实现读写分离 1、安装pymysql&#xff0c;它是python管理mysql的驱动&#xff0c;或者称为连接器 [rootpyhton ~]#pip3 config set global.index-url Simple Index [rootpython ~]# pip3 install pymysql #安装pymysql [rootpyhton ~]# python3 …

【C++】什么是内存管理?

如果有不懂的地方&#xff0c;可以看我以往文章哦&#xff01; 个人主页&#xff1a;CSDN_小八哥向前冲 所属专栏&#xff1a;C入门 目录 C/C内存分布 C内存管理方式 new/delete操作内置类型 new/delete操作自定义类型 operator new与operator delete函数 new和delete实现…

【秋招笔试】24-08-10-OPPO-秋招笔试题(第二套)

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 编程一对一辅导 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🍒 本专栏已收…

2024巴黎奥运会VIS视觉设计分享学习

2024年巴黎奥运会的视觉识别系统&#xff08;VIS&#xff09;以其独特的设计和创意&#xff0c;展现了法国的优雅与活力。该设计融合了现代感与传统元素&#xff0c;以巴黎标志性的建筑和文化为灵感&#xff0c;创造出一系列令人印象深刻的视觉符号。 色彩上&#xff0c;采用了…

SpringCloud网关

1.网关的作用 2.网关入门 2.1引入依赖 <dependencies><dependency><groupId>com.heima</groupId><artifactId>hm-common</artifactId><version>1.0.0</version></dependency><!--网关--><dependency><g…

【qt】基于tcp的客户端搭建

ui界面设计 我们给客户端提供服务器的ip地址&#xff0c;以及服务器的端口号 1.界面设计 2.修改对象名称 代码实现 断开按键的槽函数处理 转到槽&#xff0c;然后实现槽函数&#xff0c;直接关闭该窗口&#xff0c;就可以了 连接槽函数编写&#xff0c;首先要支持网络通信…

C# 解析html

C#解析html库 网上查找有如下几个库 SGMLReader (好久不更新了)html-agility-pack(活跃)AngleSharp(活跃)CsQuery(好久不更新) 选择AngleSharp 原因:能向写js一样获取元素 安装AngleSharp 1.2.0-beta.431 using AngleSharp.Html.Parser;namespace HtmlParse01;class Progr…

示波法电子血压原理

血压是指血液在血管内流动时作用于单位面积血管壁的侧压力&#xff0c;它是推动血液在血管内流动的动力。在不同血管内被分别称为动脉血压、毛细血管压和静脉血压&#xff0c;通常所说的血压是指体循环的动脉血压。 血压正常范围值&#xff1a;收缩压130mmHg&#xff0c;舒张压…

【Python学习-UI界面】PyQt5 小部件9-QMenuBar,QMenuQAction 菜单栏

样式如下: 在pyqt5中直接添加就行&#xff0c;子项只能输入英文&#xff0c;输入中文的方式待研究 一个水平的 QMenuBar 位于QMainWindow对象的标题栏下方&#xff0c;用于显示QMenu对象。 QMenu 类提供了一个可以添加到菜单栏的小部件。它还用于创建上下文菜单和弹出菜单。…

基于YOLOv10深度学习的草莓成熟度检测与识别系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、人工智能

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

SpringCloud完整教程

一下内容为本人在听黑马程序员的课程时整理的 微服务技术栈 ⎛⎝≥⏝⏝≤⎛⎝ ⎛⎝≥⏝⏝≤⎛⎝ ⎛⎝≥⏝⏝≤⎛⎝ ⎛⎝≥⏝⏝≤⎛⎝ 1、微服务框架 1.1、认识微服务 1.1.1、服务架构演变 **单体架构&#xff1a;**将业务的所有功能集中在一个项目中开发&#xff0c;打包成…

TypeScript 编译选项

编译TS 编译 .ts 文件&#xff1a; tsc app.ts执行命令tsc app.ts 可以把 单个文件 app.ts编译成 app.js。 这个命令需要每次编译时手动执行。 自动编译文件 tsc app.ts -w // 或者 tsc app.ts --watch通常 -w 或 --watch 指令用于启动 TypeScript 编译器的监视模式。 编译…

梅丽尔·斯特里普表演艺术家中心对外开放并恢复线下活动 体现了她的“卓越”

梅丽尔斯特里普表演艺术家中心对外开放并恢复线下活动 体现了她的“卓越” 2024-08-14 20:38 发布于&#xff1a;河北省 该中心将为美国演员工会和美国电视广播艺人协会的艺术家提供资源和机会&#xff0c;而且全部免费 同时命名的还有汤姆汉克斯和丽塔威尔逊放映室、妮可…

工业WiFi网关在工业领域的具体应用-天拓四方

工业WIFI网关在工业领域的应用已经变得极为广泛&#xff0c;它不仅是连接工业设备、传感器与云平台之间的桥梁&#xff0c;更是推动工业智能化和自动化的重要动力。下面将进一步详细介绍工业WiFi网关在工业领域的一些具体应用。 工业自动化生产&#xff1a; 在工业自动化生产…

算法力扣刷题记录 八十一【343. 整数拆分】

前言 动态规划第8篇。记录 八十一【343. 整数拆分】 一、题目阅读 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。返回 最大乘积 。 示例 1: 输入: n 2 输出: 1 解释: 2 1 1, 1 …

货代企业转型海外仓,会面临哪些难点?

根据数据统计&#xff0c;跨境电商出口B2C物流市场规模已经达到3825亿元&#xff0c;其中海外仓物流以2102亿的规模以及55%的市场份额成为主流。从细分领域看&#xff0c;其中FBA物流、第三方仓、自建仓的市场规模分别达到1156亿、736亿、210亿。 在跨境物流行业中&#xff0c…

uniapp粘贴板地址识别 address-parse插件的使用

1&#xff1a; 插件安装 主要是依靠 address-parse 这个插件&#xff1a; 官网 收货地址自动识别 支持pc、h5、微信小程序 - DCloud 插件市场 // 首先需要引入插件 npm install address-parse --save 2&#xff1a;html部分 <view class""><view class&quo…

QT、C++简单界面设计

#include "mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent) {---------------------窗口设置----------------------this->setWindowTitle("南城贤子摄影工作室");//设置窗口标题this->setWindowIcon(QIcon("d:\\Pictures\\C…