🍃前言
本次开发任务:
- 实现对绑定的添加与绑定
🌲添加绑定
对于绑定的操作相较于前面对交换机和队列的操作就会麻烦一点了
我们分为以下七步来实现:
- 对传入的队列名与交换机名字进行重命名
- 获取绑定是否存在,若存在,直接返回即可
- 验证 bindingKey 是否合法.
- 该步骤我们另外创建一个类,创建相应的方法,来判定验证 bindingKey 是否合法.
- 这里先不关心具体实现细节,后面会一一实现
- 创建bing对象
- 获取相应的交换机与队列对象,若有一个不存在,则不存在绑定关系
- 写入硬盘时,我们需要交换机与队列都持久化,才将该绑定写入硬盘
- 写入内存
同样我们需要为了线程安全,我们需要进行加锁操作,由于我们该操作既涉及了交换机,有涉及了队列。所以我们这里需要进行双重加锁。
同时不要忘了进行异常处理,代码实现如下:
//添加绑定 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; } }
🌳删除绑定
关于删除绑定,我们分为以下四步实现:
- 对传入的队列名与交换机名字进行重命名
- 查询相应绑定是否存在,若不存在,直接返回即可
- 若存在,无论绑定是否持久化了, 都尝试从硬盘删一下. 就算不存在, 这个删除也无副作用.
- 删除内存数据
需要特别注意的是,为了线程安全,我们依旧需要进行加锁操作。
而且加锁顺序一定要与上面增加绑定的顺序相同,不然可能会出现死锁。
最后不要忘了处理异常即可,代码实现如下:
//删除绑定 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; }
⭕总结
关于《【消息队列开发】 虚拟主机设计——操作绑定》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下