【消息队列开发】 虚拟主机设计——放送消息到队列/交换机中

🍃前言

本次开发任务

  • 实现放送消息到队列/交换机中
    在这里插入图片描述

🎋实现思路

大致思路为根据交换机的类型与转发规则,将消息转发到相应的队列。

具体步骤如下:

  1. 首先我们需要对该交换机进行重命名

  2. 检查 routingKey 是否合法,该部分的逻辑统一放在 Router 里面进行处理,后面会进行开发的

  3. 查询当前交换机对象是否存在,不存在返回即可

  4. 查询当前交换机的类型,若为DIRECT(直接交换机)

    1. 按照直接交换机的方式来转发消息以 routingKey 作为队列的名字, 直接把消息写入指定的队列中.
    2. 构造相应的消息对象
    3. 查找该队列名对应的对象
    4. 存在,直接写入对象即可
  5. 若不为,按照 fanout 和 topic 的方式来转发

    1. 找到该交换机关联的所有绑定, 并遍历这些绑定对象
    2. 遍历时,我们需要获取到绑定对象, 判定对应的队列是否存在,此处队列不存在咱们就不抛出异常了.。可能此处有多个这样的队列。希望不要因为一个队列的失败, 影响到其他队列的消息的传输.
    3. 构造消息对象
    4. 判定这个消息是否能转发给该队列,该逻辑同样放在 Router 里面进行处理
      - 如果是 fanout, 所有绑定的队列都要转发的.
      - 如果是 topic, 还需要判定下, bindingKey 和 routingKey 是不是匹配

    5.真正转发消息给队列

    • 此处我们先创建个方法,表示转发。但具体实现后面才会进行实现。
  6. 返回true

最后不要忘了进行异常处理

🎍代码实现

// 发送消息到指定的交换机/队列中.
public boolean basicPublish(String exchangeName, String routingKey, BasicProperties basicProperties, byte[] body) {
    try {
        // 1. 转换交换机的名字
        exchangeName = virtualHostName + exchangeName;
        // 2. 检查 routingKey 是否合法.
        if (!router.checkRoutingKey(routingKey)) {
            throw new MqException("[VirtualHost] routingKey 非法! routingKey=" + routingKey);
        }
        // 3. 查找交换机对象
        Exchange exchange = memoryDataCenter.getExchange(exchangeName);
        if (exchange == null) {
            throw new MqException("[VirtualHost] 交换机不存在! exchangeName=" + exchangeName);
        }
        // 4. 判定交换机的类型
        if (exchange.getType() == ExchangeType.DIRECT) {
            // 按照直接交换机的方式来转发消息
            // 以 routingKey 作为队列的名字, 直接把消息写入指定的队列中.
            // 此时, 可以无视绑定关系.
            String queueName = virtualHostName + routingKey;
            // 5. 构造消息对象
            Message message = Message.createMessageWithId(routingKey, basicProperties, body);
            // 6. 查找该队列名对应的对象
            MSGQueue queue = memoryDataCenter.getQueue(queueName);
            if (queue == null) {
                throw new MqException("[VirtualHost] 队列不存在! queueName=" + queueName);
            }
            // 7. 队列存在, 直接给队列中写入消息
            sendMessage(queue, message);
        } else {
            // 按照 fanout 和 topic 的方式来转发.
            // 5. 找到该交换机关联的所有绑定, 并遍历这些绑定对象
            ConcurrentHashMap<String, Binding> bindingsMap = memoryDataCenter.getBindings(exchangeName);
            for (Map.Entry<String, Binding> entry : bindingsMap.entrySet()) {
                // 1) 获取到绑定对象, 判定对应的队列是否存在
                Binding binding = entry.getValue();
                MSGQueue queue = memoryDataCenter.getQueue(binding.getQueueName());
                if (queue == null) {
                    // 此处咱们就不抛出异常了. 可能此处有多个这样的队列.
                    // 希望不要因为一个队列的失败, 影响到其他队列的消息的传输.
                    System.out.println("[VirtualHost] basicPublish 发送消息时, 发现队列不存在! queueName=" + binding.getQueueName());
                    continue;
                }
                // 2) 构造消息对象
                Message message = Message.createMessageWithId(routingKey, basicProperties, body);
                // 3) 判定这个消息是否能转发给该队列.
                //    如果是 fanout, 所有绑定的队列都要转发的.
                //    如果是 topic, 还需要判定下, bindingKey 和 routingKey 是不是匹配.
                if (!router.route(exchange.getType(), binding, message)) {
                    continue;
                }
                // 4) 真正转发消息给队列
                sendMessage(queue, message);
            }
        }
        return true;
    } catch (Exception e) {
        System.out.println("[VirtualHost] 消息发送失败!");
        e.printStackTrace();
        return false;
    }
}

private void sendMessage(MSGQueue queue, Message message) throws IOException, MqException, InterruptedException {
   
}

⭕总结

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

  • 10
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

遇事问春风乄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值