RabbitMQ 之 Exchange 交换机

Exchange 用于接收消息,并根据路由键转发消息到所绑定的队列。
在这里插入图片描述
上图来源于某视频课程截图,如侵权,请联系立即删除!

从图中可以看出,Exchange 与 Queue 是通过 RoutingKye 来进行关联的,且 Exchange 与 Queue 是多对多的关系。

交换机常见属性

Name: 交换机名称
Type: 交换机类型,主要有 direct topic fanout headers
Durability: 是否需要持久化,true 表示持久化
Auto Delete: 当最后一个绑定到 Exchange上的队列删除后,自动删除该 Exchange
Internal: 当前 Exchange 是否用于 RabbitMQ 内部使用,默认为 False
Arguments: 扩展参数,用于扩展 AMQP 协议自定化使用

常用交换机类型

Direct Exchange

所有发送到 Direct Exchange 的消息被转发到 RouteKey 中指定的 Queue。此类型 Exchange 中生产者发送消息指定的 routingKey 与 消费者中 Exchange 和 Queue 绑定时指定的 routingKey 相同,否则发送失败。
注意:Direct 模式可以使用 RabbitMQ 自带的 Exchange(default Exchange),所以可以不需要将 Exchange 进行任何绑定操作,但是消息传递时,RouteKey 必须完全匹配才会被队列接收,否则该消息会被抛弃。
在这里插入图片描述上图来源于某视频课程截图,如侵权,请联系立即删除!

DirectProducer.java

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class DirectProducer {

	public static void main(String[] args) throws Exception {
		ConnectionFactory connectionFactory = new ConnectionFactory();
		connectionFactory.setHost("192.168.0.125");
		connectionFactory.setPort(5672);
		connectionFactory.setVirtualHost("/");
		
		// 获取连接
		Connection connection = connectionFactory.newConnection();
		// 创建信道
		Channel channel = connection.createChannel();

		// 通过信道发送信息
		String exchangeName = "test.exchange.direct";
		String routingKey = "key.direct";
		for(int i = 0; i < 3; i++) {
			String msg = "rabbitmq Producer: direct exchange test send message ";
//			channel.basicPublish(exchange, routingKey, props, body);
			channel.basicPublish(exchangeName, routingKey, null, msg.getBytes());
			System.out.println("生产端消息已发送。。。");
		}
		// 关闭连接
		channel.close();
		connection.close();
	}
}

DirectConsumer.java

import java.io.IOException;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class DirectConsumer {

	public static void main(String[] args) throws Exception {
		ConnectionFactory connectionFactory = new ConnectionFactory();
		connectionFactory.setHost("192.168.0.125");
		connectionFactory.setPort(5672);
		connectionFactory.setVirtualHost("/");
		
		Connection connection = connectionFactory.newConnection();
		Channel channel = connection.createChannel();
		
		// 声明一个队列
		String queueName = "test.queue.direct";
//		channel.queueDeclare(queue, durable, exclusive, autoDelete, arguments);
		channel.queueDeclare(queueName, true, false, false, null);
		// 声明一个交换机
		String exchangeName = "test.exchange.direct";
		String exchangeType = "direct";
		String routingKey = "key.direct"; //与生产者发送消息使用的routingKey一样
//		channel.exchangeDeclare(exchange, type, durable, autoDelete, internal, arguments);
		channel.exchangeDeclare(exchangeName, exchangeType, false, false, false, null);
		//交换机与队列绑定
		channel.queueBind(queueName, exchangeName, routingKey);

		// 创建消费者
		Consumer consumer = new DefaultConsumer(channel) {
			@Override
            public void handleDelivery(String consumerTag,
                                       Envelope envelope,
                                       AMQP.BasicProperties properties,
                                       byte[] body) throws IOException {

				String msg = new String(body, "UTF-8");
                //TODO 自己的业务
                //交换机
                String exchange = envelope.getExchange();
                //路由key
                String routingKey = envelope.getRoutingKey();
                //消息id
                long deliveryTag = envelope.getDeliveryTag();
                //消息内容
                System.err.println("消费端收到 message : " + msg);
			}
		};
		
		channel.basicConsume(queueName, true, consumer);
		
	//	channel.close();
	//	connection.close(); 流先不关闭,要不然看不到System.err.println的输出
	}
}

由于本服务器还没有我定义的 Exchange ,因此先运行消息消费者程序,先声明相应的 Exchange 和 Queue 。
此时登录 RabbitMQ 管控台,可以查看本程序声明的 Exchange 和 Queue,及它们的绑定关系。
在这里插入图片描述在这里插入图片描述
Direct 类型的 Exchange 中 routingKey 必须相同
这时运行生产者程序,发送消息到 RabbitMQ 服务器,再运行消息消费者程序即可接收消息。
在这里插入图片描述

Topic Exchange

所有发送到 Topic Exchange 的消息被转发到所有关心 RouteKey 中指定 Topic 的 Queue 上。通俗地说:Exchange 会将 RouteKey 和某 Topic 进行模糊匹配,此时队列需要绑定一个 Topic
注意:可以使用通配符进行模糊匹配
“ # ”——匹配一个或多个词
“ * ” ——匹配一个词
例如:" hello.# " 能匹配到"hello.world.test"
" hello.* " 只能匹配到"hello.world"
在这里插入图片描述上图来源于某视频课程截图,如侵权,请联系立即删除!

Topic Exchange 消息的生产与消费与 Direct Exchange 类似,只是 Exchange 的类型换了,下面就只贴关键代码。
TopicProducer.java

		// 通过信道发送信息
		String exchangeName = "test.exchange.topic";
		String routingKey1 = "key.topic.hello";
		String routingKey2 = "key.topic.world";
		String routingKey3 = "key.topic.test.hello";
		String msg = "rabbitmq Producer: topic exchange test send message ";
//		channel.basicPublish(exchange, routingKey, props, body);
		// 用3个不同的 routingKey 各发送一条消息
		channel.basicPublish(exchangeName, routingKey1, null, msg.getBytes());
		channel.basicPublish(exchangeName, routingKey2, null, msg.getBytes());
		channel.basicPublish(exchangeName, routingKey3, null, msg.getBytes());
		System.out.println("生产端消息已发送,请查收。。。");

TopicConsumer.java

		// 声明一个队列
		String queueName = "test.queue.topic";
//		channel.queueDeclare(queue, durable, exclusive, autoDelete, arguments);
		channel.queueDeclare(queueName, true, false, false, null);
		// 声明一个交换机
		String exchangeName = "test.exchange.topic";
		String exchangeType = "topic";
//		String routingKey = "key.topic.#";
		String routingKey = "key.topic.*";
//		channel.exchangeDeclare(exchange, type, durable, autoDelete, internal, arguments);
		channel.exchangeDeclare(exchangeName, exchangeType, false, false, false, null);
		//交换机与队列绑定
		channel.queueBind(queueName, exchangeName, routingKey);

如果Exchange 与 Queue 进行绑定时用的 RoutingKey 是 “ key.topic.* ”,消费端将只能收到2条消息。如果绑定时 RoutingKey 是“ key.topic.# ”,则消费端可以收到生产端发送的3条消息。
注意:在测试第二种绑定方式时,记得先去解绑前一种绑定方式
在这里插入图片描述

Fanout Exchange

不处理任何路由键,只需简单地把队列绑定到交换机上
发送到交换机的消息都会被转发到与该交换机绑定的所有队列上
Fanout 交换机转发消息是最快的,因为不用匹配 routingKey 。
在这里插入图片描述上图来源于某视频课程截图,如侵权,请联系立即删除!

FanoutProducer.java

		// 通过信道发送信息
		String exchangeName = "test.exchange.fanout";
		String msg = "rabbitmq Producer: fanout exchange test send message ";
//		channel.basicPublish(exchange, routingKey, props, body);
		channel.basicPublish(exchangeName, "", null, msg.getBytes());//这里的路由键可以任意,也可以没有
		System.out.println("生产端消息已发送,请查收。。。");

FanoutConsumer.java

		// 声明一个队列
		String queueName = "test.queue.fanout";
//		channel.queueDeclare(queue, durable, exclusive, autoDelete, arguments);
		channel.queueDeclare(queueName, true, false, false, null);
		// 声明一个交换机
		String exchangeName = "test.exchange.fanout";
		String exchangeType = "fanout";
		String routingKey = "";//不设置路由键
//		channel.exchangeDeclare(exchange, type, durable, autoDelete, internal, arguments);
		channel.exchangeDeclare(exchangeName, exchangeType, false, false, false, null);
		//交换机与队列绑定
		channel.queueBind(queueName, exchangeName, routingKey);

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值