Rabbitmq(五)

64 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情

4.5 第三种模型(fanout)

fanout 扇出 也称为广播

image-20191126213115873

在广播模式下,消息发送流程是这样的:

  • 可以有多个消费者
  • 每个消费者有自己的queue(队列)
  • 每个队列都要绑定到Exchange(交换机)
  • 生产者发送的消息,只能发送到交换机,交换机来决定要发给哪个队列,生产者无法决定。
  • 交换机把消息发送给绑定过的所有队列
  • 队列的消费者都能拿到消息。实现一条消息被多个消费者消费
1. 开发生产者
//声明交换机
channel.exchangeDeclare("logs","fanout");//广播 一条消息多个消费者同时消费
//发布消息
channel.basicPublish("logs","",null,"hello".getBytes());

生产者类:

public class Provider {

    public static void main(String[] args) throws IOException {
        // 获取连接对象
        Connection connection = RabbitMQUtils.getConnection();
        // 创建通道对象
        Channel channel = connection.createChannel();

        // 将通道声明指定的交换机  交换机名字  交换机类型fanout:广播类型   注;交换机不存在的话会自动创建
        channel.exchangeDeclare("logs", "fanout");  // 广播的话交换机类型必须写 fanout

        // 发送消息         交换机名字  路由key    消息持久化特性         消息
        channel.basicPublish("logs", "", null, "fanout type message".getBytes());

        // 释放资源
        RabbitMQUtils.closeConnectionAndChanel(channel, connection);

    }
}
2. 开发消费者-1
//绑定交换机
channel.exchangeDeclare("logs","fanout");
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//将临时队列绑定exchange
channel.queueBind(queue,"logs","");
//处理消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
  @Override
  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    System.out.println("消费者1: "+new String(body));
  }
});

消费者1类:

public class Consumer1 {

    public static void main(String[] args) throws IOException {
        // 获取连接对象
        Connection connection = RabbitMQUtils.getConnection();
        // 获取通道对象
        Channel channel = connection.createChannel();

        // 通道绑定交换机      交换机名字     交换机类型
        channel.exchangeDeclare("logs", "fanout");      // 消费者一定要和生产者对应上

        // 临时队列的名字(没有必要创建持久队列,减轻Rabbitmq中队列的数量)
        String queueName = channel.queueDeclare().getQueue();

        // 绑定交换机和队列(通过通道把它俩组合到一起)   队列名字  哪个交换机   路由key
        channel.queueBind(queueName, "logs", "");

        // 消费消息           队列名字   是否自动确认    回调接口用来消费消息
        channel.basicConsume(queueName, true, new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者1:" + new String(body));
            }
        });
    }
}
3. 开发消费者-2
//绑定交换机
channel.exchangeDeclare("logs","fanout");
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//将临时队列绑定exchange
channel.queueBind(queue,"logs","");
//处理消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
  @Override
  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    System.out.println("消费者2: "+new String(body));
  }
});

消费者2类:


public class Consumer2 {

    public static void main(String[] args) throws IOException {
        // 获取连接对象
        Connection connection = RabbitMQUtils.getConnection();
        // 获取通道对象
        Channel channel = connection.createChannel();

        // 通道绑定交换机      交换机名字     交换机类型
        channel.exchangeDeclare("logs", "fanout");      // 消费者一定要和生产者对应上

        // 临时队列的名字(没有必要创建持久队列,减轻Rabbitmq中队列的数量)
        String queueName = channel.queueDeclare().getQueue();

        // 绑定交换机和队列(通过通道把它俩组合到一起)   队列名字  哪个交换机   路由key
        channel.queueBind(queueName, "logs", "");

        // 消费消息           队列名字   是否自动确认    回调接口用来消费消息
        channel.basicConsume(queueName, true, new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者2:" + new String(body));
            }
        });
    }
}

4.开发消费者-3
//绑定交换机
channel.exchangeDeclare("logs","fanout");
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//将临时队列绑定exchange
channel.queueBind(queue,"logs","");
//处理消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
  @Override
  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    System.out.println("消费者3: "+new String(body));
  }
});

消费者3类:

public class Consumer3 {

    public static void main(String[] args) throws IOException {
        // 获取连接对象
        Connection connection = RabbitMQUtils.getConnection();
        // 获取通道对象
        Channel channel = connection.createChannel();

        // 通道绑定交换机      交换机名字     交换机类型
        channel.exchangeDeclare("logs", "fanout");      // 消费者一定要和生产者对应上

        // 临时队列的名字(没有必要创建持久队列,减轻Rabbitmq中队列的数量)
        String queueName = channel.queueDeclare().getQueue();

        // 绑定交换机和队列(通过通道把它俩组合到一起)   队列名字  哪个交换机   路由key
        channel.queueBind(queueName, "logs", "");

        // 消费消息           队列名字   是否自动确认    回调接口用来消费消息
        channel.basicConsume(queueName, true, new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者3:" + new String(body));
            }
        });
    }
}
5. 测试结果

image-20220824082807196

image-20220824082823255

image-20220824082841071