11.交换机介绍&扇出

无名交换机

前面都是发送消息到队列,交换机的参数设置为空串"",其实使用的是默认交换机。

channel.basicPublish("", queueName, null, message.getBytes());

可以看出默认交换机属于直接交换机类型direct。

默认交换机会路由到指定的的队列。

交换机队列是通过routingkey进行绑定。之前使用无名交换机,这个routingkey默认就是队列的名称

简单模式,工作模式流程图

发布订阅模式路程图

一条消息通过交换机给不同的队列,多个消费者就可以消费相同的消息。

 所以,发布订阅模式就使用到了交换机。

交换机

rabbitmq消息传递模型的核心思想是:生产者生产的消息从不会直接发送给队列。通常生产者都不知道消息传递到了哪些队列。

生产者只是将消息发送给交换机。

交换机的工作内容

1.接收来自生产者的消息。

2.将它们推入队列。

交换机应该把这些消息放入特定队列,还是许多队列,还是丢失掉,是由交换机的类型决定的。

交换机的类型

1.直接类型direct

2.主题类型topic

3.标题类型headers(不常用)

4.扇出类型fanout

临时队列

是不带持久化的消息队列,一旦断开消费者的连接,队列会自动删除。

测试一旦生产者挂掉,临时队列也会删除。

每当连接到rabbitmq时,需要一个全新的空队列,为此创建一个具有随机名称的队列。或者让服务器为我们选择一个随机队列名称那就更好了。

创建临时队列的方法:

//创建临时队列
String queueName = channel.queueDeclare().getQueue();

绑定

binding就是exchange与queue之间的桥梁。

Fanout扇出(广播)

是将接收到的消息广播到它知道的所有队列中。

系统中默认的交换机

图中binding是一样的,就像qq群消息群发,大喇叭一样,发一条消息所有的消费者都能看见。

交换机logs

队列名随机产生

接收者1

package com.xkj.org.mq.fanout;

import com.rabbitmq.client.*;
import com.xkj.org.utils.RabbitMQUtil;


public class Receiver01 {

    //交换机名称
    public static final String EXCHANGE_NAME = "logs";


    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMQUtil.getChannel();
        //声明交换机
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
        //声明一个临时队列
        //生成一个临时队列,队列名称是随机的
        //当消费者断开与队列的连接的时候,队列就自动删除
        String queueName = channel.queueDeclare().getQueue();
        //绑定交换机与队列
        channel.queueBind(queueName, EXCHANGE_NAME, "");
        System.out.println("receiver01等待接收消息,把接收到的消息打印出来....");
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println("receiver01接收到的消息:"+ new String(message.getBody(), "UTF-8"));
        };
        CancelCallback cancelCallback = consumerTag -> {
            System.out.println("receiver01消息消费被中断...");
        };
        channel.basicConsume(queueName, true, deliverCallback, cancelCallback);

    }

}

接收者2

package com.xkj.org.mq.fanout;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import com.xkj.org.utils.RabbitMQUtil;


public class Receiver02 {

    //交换机名称
    public static final String EXCHANGE_NAME = "logs";


    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMQUtil.getChannel();
        //声明交换机
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
        //声明一个临时队列
        //生成一个临时队列,队列名称是随机的
        //当消费者断开与队列的连接的时候,队列就自动删除
        String queueName = channel.queueDeclare().getQueue();
        //绑定交换机与队列
        channel.queueBind(queueName, EXCHANGE_NAME, "");
        System.out.println("receiver02等待接收消息,把接收到的消息打印出来....");
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println("receiver02接收到的消息:"+ new String(message.getBody(), "UTF-8"));
        };
        CancelCallback cancelCallback = consumerTag -> {
            System.out.println("receiver02消息消费被中断...");
        };
        channel.basicConsume(queueName, true, deliverCallback, cancelCallback);

    }

}

发送者

package com.xkj.org.mq.fanout;

import com.rabbitmq.client.Channel;
import com.xkj.org.utils.RabbitMQUtil;

import java.io.IOException;
import java.util.Scanner;

public class EmitLog {

    //交换机名称
    public static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws IOException {
        Channel channel = RabbitMQUtil.getChannel();
        //声明交换机(如果先启动了消费者,交换机就已经声明了,这里就不能重复声明了)
//        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNext()) {
            String message = scanner.next();
            channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes("UTF-8"));
            System.out.println("生产者发送消息:"+ message);
        }
    }
}

结论:两个消息接收者收到的消息是一模一样的。这里的routingKey绑定的是空串,相当于没有绑定,都是一样的。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

卷土重来…

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

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

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

打赏作者

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

抵扣说明:

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

余额充值