【消息队列开发】虚拟主机设计——操作交换机

简介: 【消息队列开发】虚拟主机设计——操作交换机

🍃前言

本次开发目标:

创造一个虚拟机类 VirtualHost 类,每个虚拟主机下面都管理着自己的 交换机, 队列, 绑定, 消息 数据,对前面的所有操作进行整合封装,同时提供 api 供上层调用.

同时呢,我们前面所抛出的异常在这里我们就要进行处理了。

本次我们先来实现一些基础属性的注入,和创建交换机与删除交换机的操作。

🌳基础属性与基础方法

首先我们有一个String类型的变量表示该虚拟机的名字。

我们还需要注入两个对象,分别为我们前面封装好的两个类

  • MemoryDataCenter
  • DiskDataCenter

并对以上属性提供get方法以供进行访问

另外,为了保证线程安全,还提供了两个锁对象

代码实现如下:

🎋初始化操作

在我们进行初始化时,需要做以下三件事儿:

  1. 根据传入的参数,为该虚拟机命名
  2. 调用DiskDataCenter 类的初始化方法
  3. 调用 MemoryDataCenter 的方法将硬盘的数据读到内存上

代码实现如下:

public VirtualHost(String name) {
    this.virtualHostName = name;
    // 对于 MemoryDataCenter 来说, 不需要额外的初始化操作的. 只要对象 new 出来就行了
    // 但是, 针对 DiskDataCenter 来说, 则需要进行初始化操作. 建库建表和初始数据的设定.
    diskDataCenter.init();
    // 另外还需要针对硬盘的数据, 进行恢复到内存中.
    try {
        memoryDataCenter.recovery(diskDataCenter);
    } catch (IOException | MqException | ClassNotFoundException e) {
        e.printStackTrace();
        System.out.println("[VirtualHost] 恢复内存数据失败!");
    }
}

🎍创建交换机

对于创建交换机

  • 如果交换机不存在, 就创建, 如果存在, 直接返回.
  • 返回值是 boolean.,创建成功, 返回 true,失败返回 false。

这里我们为了保证不同虚拟机内可以含有相同类,我们对传入的交换机名字进行简单加工下。

使现在 交换机的名字 = 虚拟机名字 + 传入交换机的名字

创建交换机我们可以分为以下五步

  1. 判定该交换机是否已经存在.,直接通过内存查询,若存在,打印一个日志,返回true即可
  2. 真正创建交换机.,根据传入的参数先构造 Exchange 对象
  3. 把交换机对象写入硬盘
  4. 把交换机写入内存中
  5. 返回true

需要注意的是:

  1. 上面操作3与操作4最好不要调换,先写硬盘, 后写内存。 目的就是因为硬盘更容易写失败. 如果硬盘写失败了, 内存就不写了。要是先写内存, 内存写成功了, 硬盘写失败了, 还需要把内存的数据给再删掉. 就比较麻烦了。
  2. 上述操作现在并不是线程安全的,所以我们需要利用上面创建的锁对象进行加锁操作
  3. 除此之外,我们需要对该层的异常进行一个处理,不再往上抛了

代码实现如下:

// 创建交换机
// 如果交换机不存在, 就创建. 如果存在, 直接返回.
// 返回值是 boolean. 创建成功, 返回 true. 失败返回 false
public boolean exchangeDeclare(String exchangeName, ExchangeType exchangeType, boolean durable, boolean autoDelete,
                               Map<String, Object> arguments) {
    // 把交换机的名字, 加上虚拟主机作为前缀.
    exchangeName = virtualHostName + exchangeName;
    try {
        synchronized (exchangeLocker) {
            // 1. 判定该交换机是否已经存在. 直接通过内存查询.
            Exchange existsExchange = memoryDataCenter.getExchange(exchangeName);
            if (existsExchange != null) {
                // 该交换机已经存在!
                System.out.println("[VirtualHost] 交换机已经存在! exchangeName=" + exchangeName);
                return true;
            }
            // 2. 真正创建交换机. 先构造 Exchange 对象
            Exchange exchange = new Exchange();
            exchange.setName(exchangeName);
            exchange.setType(exchangeType);
            exchange.setDurable(durable);
            exchange.setAutoDelete(autoDelete);
            exchange.setArguments(arguments);
            // 3. 把交换机对象写入硬盘
            if (durable) {
                diskDataCenter.insertExchange(exchange);
            }
            // 4. 把交换机对象写入内存
            memoryDataCenter.insertExchange(exchange);
            System.out.println("[VirtualHost] 交换机创建完成! exchangeName=" + exchangeName);
            // 上述逻辑, 先写硬盘, 后写内存. 目的就是因为硬盘更容易写失败. 如果硬盘写失败了, 内存就不写了.
            // 要是先写内存, 内存写成功了, 硬盘写失败了, 还需要把内存的数据给再删掉. 就比较麻烦了.
        }
        return true;
    } catch (Exception e) {
        System.out.println("[VirtualHost] 交换机创建失败! exchangeName=" + exchangeName);
        e.printStackTrace();
        return false;
    }
}

🍀删除交换机

删除交换机的逻辑,我们分为四步进行:

  1. 修改交换机的名字
  2. 查询是否有该交换机
  3. 删除硬盘上的数据
  4. 删除内存上的数据

同样,为了线程安全,我们同样利用我们前面提供的交换机对象进行加锁操作。

代码实现如下:

// 删除交换机
public boolean exchangeDelete(String exchangeName) {
    exchangeName = virtualHostName + exchangeName;
    try {
        synchronized (exchangeLocker) {
            // 1. 先找到对应的交换机.
            Exchange toDelete = memoryDataCenter.getExchange(exchangeName);
            if (toDelete == null) {
                throw new MqException("[VirtualHost] 交换机不存在无法删除!");
            }
            // 2. 删除硬盘上的数据
            if (toDelete.isDurable()) {
                diskDataCenter.deleteExchange(exchangeName);
            }
            // 3. 删除内存中的交换机数据
            memoryDataCenter.deleteExchange(exchangeName);
            System.out.println("[VirtualHost] 交换机删除成功! exchangeName=" + exchangeName);
        }
        return true;
    } catch (Exception e) {
        System.out.println("[VirtualHost] 交换机删除失败! exchangeName=" + exchangeName);
        e.printStackTrace();
        return false;
    }
}

⭕总结

关于《【消息队列开发】虚拟主机设计——操作交换机》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下

相关文章
|
2月前
|
消息中间件 C语言 RocketMQ
消息队列 MQ操作报错合集之出现"Connection reset by peer"的错误,该如何处理
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
3月前
|
消息中间件 网络协议 Java
【消息队列开发】 实现BrokerServer类——本体服务器
【消息队列开发】 实现BrokerServer类——本体服务器
|
2月前
|
消息中间件 Java 物联网
消息队列 MQ操作报错合集之建立连接时发生了超时错误,该如何解决
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
消息队列 MQ操作报错合集之建立连接时发生了超时错误,该如何解决
|
2月前
|
消息中间件 JavaScript Linux
消息队列 MQ操作报错合集之客户端在启动时遇到了连接错误,是什么原因
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
2月前
|
消息中间件 缓存 Apache
消息队列 MQ使用问题之对于Grpc参数的调优,该如何操作
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
3月前
|
消息中间件 监控 应用服务中间件
消息队列 MQ操作报错合集之重启Broker后,积压数出现为负数是什么导致的
在使用消息队列MQ时,可能会遇到各种报错情况。以下是一些常见的错误场景、可能的原因以及解决建议的汇总:1.连接错误、2.消息发送失败、3.消息消费报错、4.消息重试与死信处理、5.资源与权限问题、6.配置错误、7.系统资源限制、8.版本兼容性问题。
135 1
消息队列 MQ操作报错合集之重启Broker后,积压数出现为负数是什么导致的
|
3月前
|
消息中间件 Java 测试技术
消息队列 MQ操作报错合集之设置了setKeepAliveInterval(1)但仍然出现客户端未连接,该怎么解决
在使用消息队列MQ时,可能会遇到各种报错情况。以下是一些常见的错误场景、可能的原因以及解决建议的汇总:1.连接错误、2.消息发送失败、3.消息消费报错、4.消息重试与死信处理、5.资源与权限问题、6.配置错误、7.系统资源限制、8.版本兼容性问题。
|
3月前
|
消息中间件 设计模式 网络安全
消息队列 MQ操作报错合集之broker启用controller配置时,遇到报错,是什么导致的
在使用消息队列MQ时,可能会遇到各种报错情况。以下是一些常见的错误场景、可能的原因以及解决建议的汇总:1.连接错误、2.消息发送失败、3.消息消费报错、4.消息重试与死信处理、5.资源与权限问题、6.配置错误、7.系统资源限制、8.版本兼容性问题。
|
3月前
|
消息中间件 Apache RocketMQ
消息队列 MQ操作报错合集之设置了controller后,有一主一从,但只显示一个,该怎么解决
在使用消息队列MQ时,可能会遇到各种报错情况。以下是一些常见的错误场景、可能的原因以及解决建议的汇总:1.连接错误、2.消息发送失败、3.消息消费报错、4.消息重试与死信处理、5.资源与权限问题、6.配置错误、7.系统资源限制、8.版本兼容性问题。
|
3月前
|
消息中间件 Java Spring
JavaWeb后端开发Spring框架之消息 消息队列案例--订单短信通知
JavaWeb后端开发Spring框架之消息 消息队列案例--订单短信通知
32 0