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

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

🍃前言

本次开发任务:

  • 实现对绑定的添加与绑定

🌲添加绑定

对于绑定的操作相较于前面对交换机和队列的操作就会麻烦一点了

我们分为以下七步来实现:

  1. 对传入的队列名与交换机名字进行重命名
  2. 获取绑定是否存在,若存在,直接返回即可
  3. 验证 bindingKey 是否合法.
  1. 该步骤我们另外创建一个类,创建相应的方法,来判定验证 bindingKey 是否合法.
  2. 这里先不关心具体实现细节,后面会一一实现
  1. 创建bing对象
  2. 获取相应的交换机与队列对象,若有一个不存在,则不存在绑定关系
  3. 写入硬盘时,我们需要交换机与队列都持久化,才将该绑定写入硬盘
  4. 写入内存

同样我们需要为了线程安全,我们需要进行加锁操作,由于我们该操作既涉及了交换机,有涉及了队列。所以我们这里需要进行双重加锁。

同时不要忘了进行异常处理,代码实现如下:

//添加绑定
public boolean queueBind(String queueName, String exchangeName, String bindingKey) {
    queueName = virtualHostName + queueName;
    exchangeName = virtualHostName + exchangeName;
    try {
        synchronized (exchangeLocker) {
            synchronized (queueLocker) {
                // 1. 判定当前的绑定是否已经存在了.
                Binding existsBinding = memoryDataCenter.getBinding(exchangeName, queueName);
                if (existsBinding != null) {
                    throw new MqException("[VirtualHost] binding 已经存在! queueName=" + queueName
                            + ", exchangeName=" + exchangeName);
                }
                // 2. 验证 bindingKey 是否合法.
                if (!router.checkBindingKey(bindingKey)) {
                    throw new MqException("[VirtualHost] bindingKey 非法! bindingKey=" + bindingKey);
                }
                // 3. 创建 Binding 对象
                Binding binding = new Binding();
                binding.setExchangeName(exchangeName);
                binding.setQueueName(queueName);
                binding.setBindingKey(bindingKey);
                // 4. 获取一下对应的交换机和队列. 如果交换机或者队列不存在, 这样的绑定也是无法创建的.
                MSGQueue queue = memoryDataCenter.getQueue(queueName);
                if (queue == null) {
                    throw new MqException("[VirtualHost] 队列不存在! queueName=" + queueName);
                }
                Exchange exchange = memoryDataCenter.getExchange(exchangeName);
                if (exchange == null) {
                    throw new MqException("[VirtualHost] 交换机不存在! exchangeName=" + exchangeName);
                }
                // 5. 先写硬盘
                if (queue.isDurable() && exchange.isDurable()) {
                    diskDataCenter.insertBinding(binding);
                }
                // 6. 写入内存
                memoryDataCenter.insertBinding(binding);
            }
        }
        System.out.println("[VirtualHost] 绑定创建成功! exchangeName=" + exchangeName
                + ", queueName=" + queueName);
        return true;
    } catch (Exception e) {
        System.out.println("[VirtualHost] 绑定创建失败! exchangeName=" + exchangeName
                + ", queueName=" + queueName);
        e.printStackTrace();
        return false;
    }
}

🌳删除绑定

关于删除绑定,我们分为以下四步实现:

  1. 对传入的队列名与交换机名字进行重命名
  2. 查询相应绑定是否存在,若不存在,直接返回即可
  3. 若存在,无论绑定是否持久化了, 都尝试从硬盘删一下. 就算不存在, 这个删除也无副作用.
  4. 删除内存数据

需要特别注意的是,为了线程安全,我们依旧需要进行加锁操作。

而且加锁顺序一定要与上面增加绑定的顺序相同,不然可能会出现死锁。

最后不要忘了处理异常即可,代码实现如下:

//删除绑定
public boolean queueUnbind(String queueName, String exchangeName) {
    queueName = virtualHostName + queueName;
    exchangeName = virtualHostName + exchangeName;
    try {
        synchronized (exchangeLocker) {
            synchronized (queueLocker) {
                // 1. 获取 binding 看是否已经存在~
                Binding binding = memoryDataCenter.getBinding(exchangeName, queueName);
                if (binding == null) {
                    throw new MqException("[VirtualHost] 删除绑定失败! 绑定不存在! exchangeName=" + exchangeName + ", queueName=" + queueName);
                }
                // 2. 无论绑定是否持久化了, 都尝试从硬盘删一下. 就算不存在, 这个删除也无副作用.
                diskDataCenter.deleteBinding(binding);
                // 3. 删除内存的数据
                memoryDataCenter.deleteBinding(binding);
                System.out.println("[VirtualHost] 删除绑定成功!");
            }
        }
        return true;
    } catch (Exception e) {
        System.out.println("[VirtualHost] 删除绑定失败!");
        e.printStackTrace();
        return false;
    }

⭕总结

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

相关文章
|
27天前
|
消息中间件 Java 数据库
【消息队列开发】 实现 VirtualHostTests 类——测试虚拟主机操作
【消息队列开发】 实现 VirtualHostTests 类——测试虚拟主机操作
|
27天前
|
消息中间件 网络协议 Java
【消息队列开发】 实现BrokerServer类——本体服务器
【消息队列开发】 实现BrokerServer类——本体服务器
|
20天前
|
消息中间件 监控 应用服务中间件
消息队列 MQ操作报错合集之重启Broker后,积压数出现为负数是什么导致的
在使用消息队列MQ时,可能会遇到各种报错情况。以下是一些常见的错误场景、可能的原因以及解决建议的汇总:1.连接错误、2.消息发送失败、3.消息消费报错、4.消息重试与死信处理、5.资源与权限问题、6.配置错误、7.系统资源限制、8.版本兼容性问题。
消息队列 MQ操作报错合集之重启Broker后,积压数出现为负数是什么导致的
|
20天前
|
消息中间件 Java 测试技术
消息队列 MQ操作报错合集之设置了setKeepAliveInterval(1)但仍然出现客户端未连接,该怎么解决
在使用消息队列MQ时,可能会遇到各种报错情况。以下是一些常见的错误场景、可能的原因以及解决建议的汇总:1.连接错误、2.消息发送失败、3.消息消费报错、4.消息重试与死信处理、5.资源与权限问题、6.配置错误、7.系统资源限制、8.版本兼容性问题。
|
20天前
|
消息中间件 设计模式 网络安全
消息队列 MQ操作报错合集之broker启用controller配置时,遇到报错,是什么导致的
在使用消息队列MQ时,可能会遇到各种报错情况。以下是一些常见的错误场景、可能的原因以及解决建议的汇总:1.连接错误、2.消息发送失败、3.消息消费报错、4.消息重试与死信处理、5.资源与权限问题、6.配置错误、7.系统资源限制、8.版本兼容性问题。
|
20天前
|
消息中间件 Apache RocketMQ
消息队列 MQ操作报错合集之设置了controller后,有一主一从,但只显示一个,该怎么解决
在使用消息队列MQ时,可能会遇到各种报错情况。以下是一些常见的错误场景、可能的原因以及解决建议的汇总:1.连接错误、2.消息发送失败、3.消息消费报错、4.消息重试与死信处理、5.资源与权限问题、6.配置错误、7.系统资源限制、8.版本兼容性问题。
|
7天前
|
消息中间件 Java Spring
JavaWeb后端开发Spring框架之消息 消息队列案例--订单短信通知
JavaWeb后端开发Spring框架之消息 消息队列案例--订单短信通知
13 0
|
20天前
|
消息中间件 测试技术 开发工具
消息队列 MQ操作报错合集之收到"WARN RocketmqClient - consumeMessage Orderly return"警告,是什么原因
在使用消息队列MQ时,可能会遇到各种报错情况。以下是一些常见的错误场景、可能的原因以及解决建议的汇总:1.连接错误、2.消息发送失败、3.消息消费报错、4.消息重试与死信处理、5.资源与权限问题、6.配置错误、7.系统资源限制、8.版本兼容性问题。
|
20天前
|
消息中间件 网络安全 网络虚拟化
消息队列 MQ操作报错合集之如何实现公网访问内网RocketMQ集群
在使用消息队列MQ时,可能会遇到各种报错情况。以下是一些常见的错误场景、可能的原因以及解决建议的汇总:1.连接错误、2.消息发送失败、3.消息消费报错、4.消息重试与死信处理、5.资源与权限问题、6.配置错误、7.系统资源限制、8.版本兼容性问题。
|
20天前
|
消息中间件 RocketMQ
消息队列 MQ操作报错合集之无法自动创建topic,该怎么办
在使用消息队列MQ时,可能会遇到各种报错情况。以下是一些常见的错误场景、可能的原因以及解决建议的汇总:1.连接错误、2.消息发送失败、3.消息消费报错、4.消息重试与死信处理、5.资源与权限问题、6.配置错误、7.系统资源限制、8.版本兼容性问题。