zoukankan      html  css  js  c++  java
  • rabbitmq5-发布订阅模式

    前面的几篇博文中讲解的是两个简单的模式,并没有提到exchange交互及这个东西,那么是时候该引入完整的模式了,我们将引入exchange,同时介绍exchange的几种工作的模式

    一、发布订阅模式概念及应用场景:

    1、概念

    发布订阅模式使用的是“fanout”扇出模式,即exchange将忽略routing key把其投递到所有绑定的队列中

    2、应用场景:
    • 广播:例如通知所有店小二,周五放假

    二、关键组件“exchange”:

    2.1、exchange的几种模式:
    • direct:默认的一种模式,消息分发规则为:消息会被投递到binding key和routing key完全匹配的队列中去
    • topic:和direct类似,不过binding key和routing key的匹配规则可以使用正则表达式
    • header:将忽略routing key,是使用发送消息是的basicProperties对象中的headers来进行匹配的,headers是一个键值对类型发送消息的header与队列绑定时键值对匹配时,队列绑定交换机时使用x-match,在匹配是有两种模式,①:any只要匹配其中一个就可以,②:all则表示所有的都要完全匹配
    • fanout:本节要讲的一种模式。同上面一样,消息投递的时候将忽略routing key,会把接收到的消息投递到所有与之绑定的队列中去
    2.2 留一个问题思考一下:
    • 1、publishe端的肯定很好解决
    • 2、subscriber端的,以及这个消息什么时候被删除,因为不可能一直保存在队列当中的呀

    三、把代码呈上来:

    3.1、publisher:
    public class Publisher {
    
        public static final String EXCHANGE_NAME = "publisher";
    
        public static void main(String[] args) throws IOException, TimeoutException {
            Connection conn = ConnUtils.getConn();
            Channel channel = conn.createChannel();
            BuiltinExchangeType type = BuiltinExchangeType.FANOUT;
            boolean durable = true;
            boolean autoDelete = false;
            /**
             * 是否为内部交换机,如果是则不能与外部client直接,通用用于例如死信队列
             */
            boolean internal = false;
            // 在这里最后一个参数还是不做讲解,在后面高级的部分在做讲解,死信队列、延迟队列、优先级队列
            channel.exchangeDeclare(EXCHANGE_NAME,type,durable,autoDelete,internal,null);
            // 这个里面我们不指定 routing key,因为没有意义,在fanout模式下会被忽视掉的
            channel.basicPublish(EXCHANGE_NAME,"",null,"我假装是你们想要发送的消息".getBytes());
        }
    }
    3.1、subscriber:

    这个里面和官方给的代码不一样,如果不声明队列使用官方的形式的话,将会有一个临时的队列,

    public class Subscriber01 {
        public static final String EXCHANGE_NAME = "publisher";
        public static void main(String[] args) throws IOException, TimeoutException {
            Connection conn = ConnUtils.getConn();
            final Channel channel = conn.createChannel();
            channel.queueDeclare("publisher",true,false,false,null);
            // 因为routing key会被忽略,所以还是无需指定
            // 这个地方queue:队列的名称是需要指定的
            channel.queueBind("publisher",EXCHANGE_NAME,"");
            Consumer consumer = new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println(new String(body,"utf-8"));
                    channel.basicAck(envelope.getDeliveryTag(),false);
                }
            };
            boolean autoAck = false;
            channel.basicConsume("publisher",autoAck,consumer);
        }
    }

    下面我们来回答上面的问题:
    在上面的测试中,我们两个订阅者绑定的是同一个队列,结果只有其中的一个subscriber收到了消息,另外一个没有收到,这个是正常的,因为rabbitmq当消费者应答之后,mq会自动的把消息删除,现在我们看一下概念,发布订阅模式指的是:exchange忽略routing key把消息投递到所有的绑定它的队列,并不是说投递到所有的消费者,因此我们前面的假设都是有问题的,这也是我在学习的过程中算是胡思乱想的吧,希望大家能够明悟。

    如果有疑问或者是需要交流可以在下面评论也可以扫码进群

  • 相关阅读:
    Thread中的join使用
    java.lang.NoClassDefFoundError: Ljavax/enterprise/inject/spi/BeanManager;
    org.hibernate.HibernateException: Could not parse configuration: /hibernate.cfg.xm
    maven 中使用jstl 错误解决
    eclipse 安装maven
    前端 JS事件操作
    前端 JS
    前端 固定位置 与绝对定位
    前端 显示与隐藏
    前端 盒子阴影
  • 原文地址:https://www.cnblogs.com/fkxuexi/p/9588372.html
Copyright © 2011-2022 走看看