RabbitMq系列(七):直接交换Direct exchange

系列文章

RabbitMq系列(一):服务器搭建

RabbitMq系列(二):最简单的例子

RabbitMq系列(三):工作队列

RabbitMq系列(四):消息确认和持久性

RabbitMq系列(五):公平派遣

RabbitMq系列(六):交换类型以及例子

RabbitMq系列(七):直接交换Direct exchange

RabbitMq系列(八):扇出交换Fanout Exchange

RabbitMq系列(九):主题交换Topic Exchange

RabbitMq系列(十):标头交换Headers exchange

RabbitMq系列(十一):远程调用RPC

 

目录

前言

实际演示

演示1

演示2


前言

直接交换是RabbitMq主要的四种交换类型之一,其主要是针对单对单的单路由消息通信,类似于单聊。

直接交换依赖于路由键,我们可以使用 空字符串自定义路由键+交换机类型 这两种方式来快速的创建我们需要的单路由通信机制。

直接交换没有通配符的说法和应用,所以其比较规则类型于 生产者routeKey == 消费者routeKey 这样的比较方式。当消息到达交换机过后,交换机将消息带来的 routing-key( 这里就是生产者定义的 routingKey ) 与 队列绑定的 binding-key( 这里就是消费者定义的 routingKey )进行比较,通过规则验证的队列会收到由交换机路由过来的消息。

实际演示

为了对直接交换有更加清楚的认识,我们采用两个消费者一个生产者的方式来演示(其中有对有错,请注意)。

演示1

  • 环境:
身份交换机队列routeKey
消费者1direct.exchangedirect.queue.onequeue.route.*
消费者2direct.exchangedirect.queue.onequeue.route.one
生产者direct.exchangequeue.route.one
  •  消费者1
/**
 * 消费者1
 *
 * @Tag 直接交换 Direct exchange
 */
public class MQConsumerOne {

    public static void main(String[] args) {
        try {
            consumerMsg("direct.exchange","direct.queue.one","queue.route.*");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void consumerMsg(String exchange,String queue,String routeKey) throws IOException, TimeoutException {
        //创建工厂连接
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置连接地址
        connectionFactory.setHost("192.168.239.128");
        //创建连接
        Connection connection = connectionFactory.newConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //声明交换机
        channel.exchangeDeclare(exchange, BuiltinExchangeType.DIRECT,false);
        //声明队列
        channel.queueDeclare(queue,false,false,true,null);
        //绑定队列
        channel.queueBind(queue,exchange,routeKey,null);
        //创建消费者,消费消息
        channel.basicConsume(queue, true, (consumerTag, message) -> {
            //消费消息
            String msg = new String(message.getBody(), "UTF-8");
            System.out.println(msg);
        }, (consumerTag) -> {
            System.out.println(consumerTag);
        });
        //关闭连接
     /*   channel.close();
        connection.close();*/
    }
}
  • 消费者2
/**
 * 消费者2
 *
 * @Tag 直接交换 Direct exchange
 */
public class MQConsumerTwo {

    public static void main(String[] args) {
        try {
            consumerMsg("direct.exchange","direct.queue.one","queue.route.one");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void consumerMsg(String exchange,String queue,String routeKey) throws IOException, TimeoutException {
        //创建工厂连接
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置连接地址
        connectionFactory.setHost("192.168.239.128");
        //创建连接
        Connection connection = connectionFactory.newConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //声明交换机
        channel.exchangeDeclare(exchange, BuiltinExchangeType.DIRECT,false);
        //声明队列
        channel.queueDeclare(queue,false,false,true,null);
        //绑定队列
        channel.queueBind(queue,exchange,routeKey,null);
        //创建消费者,消费消息
        channel.basicConsume(queue, true, (consumerTag, message) -> {
            //消费消息
            String msg = new String(message.getBody(), "UTF-8");
            System.out.println(msg);
        }, (consumerTag) -> {
            System.out.println(consumerTag);
        });
        //关闭连接
     /*   channel.close();
        connection.close();*/
    }
}
  • 唯一生产者 
/**
 * 生产者
 *
 *  @Tag 直接交换 Direct exchange
 */
public class MQProducer {

    public static void main(String[] args) {
        try {
            consumerMsg("direct.exchange","queue.route.one","这么耿直的人,当然是直接交换!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void consumerMsg(String exchange,String routeKey,String msg) throws IOException, TimeoutException {
        //创建工厂连接
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置连接地址
        connectionFactory.setHost("192.168.239.128");
        //创建连接
        Connection connection = connectionFactory.newConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //声明交换机
        channel.exchangeDeclare(exchange, BuiltinExchangeType.DIRECT,false);
        //创建生产者,发送消息
        channel.basicPublish(exchange,routeKey,null,msg.getBytes());
        //关闭连接
        channel.close();
        connection.close();
    }
}
  • 全部代码编写完成后,分别启动消费者1、消费者2和生产者,观察收到消息的情况,突然发现消费者1 MQConsumerOne 竟然 收到消息了,而消费者2没收到消息。

  • 分析一下:

          1)消费者1的 routeKey:queue.route.*

          2)消费者2的 routeKey:queue.route.one

          3)生产者的 routeKey:queue.route.one

     消费者1的 routeKey  和 生产者的 routeKey 不相等,消费者2的 routeKey 和 生产者的 routeKey完全相等,理论上消费者1不该收到消息,消费者2该收到消息,但是实际结果却和我们的想象恰好相反,为什么呢?

额。。。。突然发现,妈蛋两个消费者的绑定队列竟然一模一样,都是 direct.queue.one !!!

这个时候队列变成了 工作队列,只要有一个消费者的 routeKey 跟生产者的 routeKey 完全匹配,绑定在同一个队列的消费者都会收到消息。

各单位请注意,各单位请注意,演示1失败

演示2

  • 环境
身份交换机队列routeKey
消费者1direct.exchangedirect.queuequeue.route.*
消费者2direct.exchangedirect.queue.onequeue.route.one
生产者direct.exchangequeue.route.*
  • 消费者1
/**
 * 消费者1
 *
 * @Tag 直接交换 Direct exchange
 */
public class MQConsumerOne {

    public static void main(String[] args) {
        try {
            consumerMsg("direct.exchange","direct.queue","queue.route.*");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void consumerMsg(String exchange,String queue,String routeKey) throws IOException, TimeoutException {
        //创建工厂连接
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置连接地址
        connectionFactory.setHost("192.168.239.128");
        //创建连接
        Connection connection = connectionFactory.newConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //声明交换机
        channel.exchangeDeclare(exchange, BuiltinExchangeType.DIRECT,false);
        //声明队列
        channel.queueDeclare(queue,false,false,true,null);
        //绑定队列
        channel.queueBind(queue,exchange,routeKey,null);
        //创建消费者,消费消息
        channel.basicConsume(queue, true, (consumerTag, message) -> {
            //消费消息
            String msg = new String(message.getBody(), "UTF-8");
            System.out.println(msg);
        }, (consumerTag) -> {
            System.out.println(consumerTag);
        });
        //关闭连接
     /*   channel.close();
        connection.close();*/
    }
}
  • 消费者2
/**
 * 消费者2
 *
 * @Tag 直接交换 Direct exchange
 */
public class MQConsumerTwo {

    public static void main(String[] args) {
        try {
            consumerMsg("direct.exchange","direct.queue.one","queue.route.one");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void consumerMsg(String exchange,String queue,String routeKey) throws IOException, TimeoutException {
        //创建工厂连接
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置连接地址
        connectionFactory.setHost("192.168.239.128");
        //创建连接
        Connection connection = connectionFactory.newConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //声明交换机
        channel.exchangeDeclare(exchange, BuiltinExchangeType.DIRECT,false);
        //声明队列
        channel.queueDeclare(queue,false,false,true,null);
        //绑定队列
        channel.queueBind(queue,exchange,routeKey,null);
        //创建消费者,消费消息
        channel.basicConsume(queue, true, (consumerTag, message) -> {
            //消费消息
            String msg = new String(message.getBody(), "UTF-8");
            System.out.println(msg);
        }, (consumerTag) -> {
            System.out.println(consumerTag);
        });
        //关闭连接
     /*   channel.close();
        connection.close();*/
    }
}
  • 唯一生产者
/**
 * 生产者
 *
 *  @Tag 直接交换 Direct exchange
 */
public class MQProducer {

    public static void main(String[] args) {
        try {
            consumerMsg("direct.exchange","queue.route.*","这么耿直的人,当然是直接交换!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void consumerMsg(String exchange,String routeKey,String msg) throws IOException, TimeoutException {
        //创建工厂连接
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置连接地址
        connectionFactory.setHost("192.168.239.128");
        //创建连接
        Connection connection = connectionFactory.newConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //声明交换机
        channel.exchangeDeclare(exchange, BuiltinExchangeType.DIRECT,false);
        //创建生产者,发送消息
        channel.basicPublish(exchange,routeKey,null,msg.getBytes());
        //关闭连接
        channel.close();
        connection.close();
    }
}
  • 再来确认一下,免得又出幺蛾子,分别启动消费者1、消费者2、生产者,查看下消息的收到情况,这里发现只有消费者1收到消息,消费者2未收到消息,可以多试几次,多发几次消息

  • 分析一下

          1)消费者1的 routeKey:queue.route.*

          2)消费者2的 routeKey:queue.route.one

          3)生产者的 routeKey:queue.route.*

 消费者1的 routeKey  和 生产者的 routeKey 完全相等,消费者2的 routeKey 和 生产者的 routeKey不相等,理论上消费者1应该收到消息,消费者2应该没消息。

除了上面的分析条件外,这里两个消费者的队列很明显不一样,测试结果完全完全跟我们想像的一样,演示成功

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值