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把消息投递到所有的绑定它的队列,并不是说投递到所有的消费者,因此我们前面的假设都是有问题的,这也是我在学习的过程中算是胡思乱想的吧,希望大家能够明悟。

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

猜你喜欢

转载自blog.csdn.net/weixin_42849915/article/details/82387406