RabbitMQ三种Exchange模式详解


前言

本文主要介绍RabbitMQ的三种Exchange模式,分别为Direct ,Topic ,Fanout 。


一、Direct

发送到该Exchange上的消息,会按照routing key路由到指定的Queue。该routing key必须和binding key完全匹配。

示例

Direct
可以看到,direct exchange X绑定了两个Queue,其中,Q1由binding key ‘orange’绑定,Q2有两个binding key,分别为‘black’和‘green’。
在这样的设置中,将使用routing key ‘orange’将要发布到交换机的消息 路由到队列Q1。routing key 为‘black’或‘green’的消息将转到Q2。所有其他消息将被丢弃。

示例代码

先引入jar包

<dependency>
	<groupId>com.rabbitmq</groupId>
	<artifactId>amqp-client</artifactId>
	<version>3.6.5</version>
</dependency>	

消费端

// 通过ConnectionFactory 创建一个Connection 
ConnectionFactory connectionFactory = new ConnectionFactory() ;  
// 配置连接的host        
connectionFactory.setHost("127.0.0.1");
// 配置连接的端口
connectionFactory.setPort(5672);
// 配置连接的virtualhost
connectionFactory.setVirtualHost("/");

connectionFactory.setAutomaticRecoveryEnabled(true);
connectionFactory.setNetworkRecoveryInterval(3000);
// 创建Connection 
Connection connection = connectionFactory.newConnection();
// 创建Channel 
Channel channel = connection.createChannel();  
// 声明
String exchangeName = "exchange";
String exchangeType = "direct";
String queueName = "queue";
String routingKey = "routingKey";
// 声明Exchange
channel.exchangeDeclare(exchangeName, exchangeType, true, false, false, null);
// 声明队列
channel.queueDeclare(queueName, false, false, false, null);
// 绑定Exchange和队列
channel.queueBind(queueName, exchangeName, routingKey);

// 声明消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 参数:队列名称、是否自动ACK、Consumer
channel.basicConsume(queueName, true, consumer);  
// 循环获取消息  
while(true){  
    //获取消息,如果没有消息,这一步将会一直阻塞  
    Delivery delivery = consumer.nextDelivery();  
    String msg = new String(delivery.getBody());    
    System.out.println("收到消息:" + msg);  
} 

生产端

//1 创建ConnectionFactory
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");

//2 创建Connection
Connection connection = connectionFactory.newConnection();
//3 创建Channel
Channel channel = connection.createChannel();  
//4 声明
String exchangeName = "exchange";
String routingKey = "routingKey";
//5 发送
String msg = "RabbitMQ Direct Exchange Message ... ";
channel.basicPublish(exchangeName, routingKey , null , msg.getBytes());

channel.close();  
connection.close();  

注意:Direct模式可以使用RabbitMQ自带的Exchange:defaut exchange,可以不将Exchang进行任何的绑定(binding),消息传递时,routing key必须和Queue名称完全匹配, 消息才会被路由,反之消息将被丢弃

二、Topic

发送到topic exchange的消息的 routing key,必须是以点分隔的单词列表。示例:
“ stock.usd.nyse ”,“ nyse.vmw ”,“quick.orange.rabbit ”。
routing key中可以包含任意多个单词,最多255个字节。
binding key也必须采用相同的形式。topic exchange背后的逻辑 类似于direct exchange-用特定routing key发送的消息将传递到所有匹配binding key绑定的队列。但是,binding key有两个重要的特殊情况:

● *(星号)可以代替一个单词。
● #(哈希)可以替代零个或多个单词。

示例

topic
在此示例中,我们创建了三个绑定:Q1与绑定键“ * .orange.* ”绑定,Q2与“ *.*.rabbit ”和“ lazy.# ”绑定。

其中:
routing key设置为“ quick.orange.rabbit ”的消息将传递到两个队列。消息“ lazy.orange.elephant ”也将发送给他们两个。
而“ quick.orange.fox ”只会进入第一个队列,
“ lazy.brown.fox ”只会进入第二个队列。
“ lazy.pink.rabbit ”将被传递到第二队列一次,即使有两个绑定匹配。
“ quick.brown.fox ”与任何绑定都不匹配,因此将被丢弃。

如果我们违约并发送一个或四个单词的消息,例如“orange”或“ quick.orange.male.rabbit ”,会发生什么?好吧,这些消息将不匹配任何绑定,并且将会丢失。

另一方面,“ lazy.orange.male.rabbit ”即使有四个单词,也将匹配最后一个绑定,并将其传送到第二个队列。

代码示例

消费端

ConnectionFactory connectionFactory = new ConnectionFactory() ;  
        
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");

connectionFactory.setAutomaticRecoveryEnabled(true);
connectionFactory.setNetworkRecoveryInterval(3000);
Connection connection = connectionFactory.newConnection();

Channel channel = connection.createChannel();  
//4 声明
String exchangeName = "exchange";
String exchangeType = "topic";
String queueName = "queue";
//String routingKey = "user.*";
String routingKey = "user.#";
channel.exchangeDeclare(exchangeName, exchangeType, true, false, false, null);
channel.queueDeclare(queueName, false, false, false, null);
channel.queueBind(queueName, exchangeName, routingKey);

QueueingConsumer consumer = new QueueingConsumer(channel);
//	参数:队列名称、是否自动ACK、Consumer
channel.basicConsume(queueName, true, consumer);

//	循环获取消息  
while(true){  
    //	获取消息,如果没有消息,这一步将会一直阻塞  
    Delivery delivery = consumer.nextDelivery();  
    String msg = new String(delivery.getBody());    
    System.out.println("收到消息:" + msg + ", RoutingKey: " + delivery.getEnvelope().getRoutingKey());  
} 

生产端

//1 创建ConnectionFactory
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");

//2 创建Connection
Connection connection = connectionFactory.newConnection();
//3 创建Channel
Channel channel = connection.createChannel();  
//4 声明
String exchangeName = "exchange";
String routingKey1 = "user.save";
String routingKey2 = "user.update";
String routingKey3 = "user.delete.abc";
//5 发送
String msg = "RabbitMQ Topic Exchange Message ...";
channel.basicPublish(exchangeName, routingKey1 , null , msg.getBytes()); 
//channel.basicPublish(exchangeName, routingKey2 , null , msg.getBytes()); 	
//channel.basicPublish(exchangeName, routingKey3 , null , msg.getBytes()); 
channel.close();  
connection.close();  

三、Fanout

发送到fanout exchange的所有消息都将广播到它所绑定的(binding)所有队列中,因此routing key在此将不起作用。

示例

fanout
所有发送到exchange X的消息都会广播到与其绑定的两个队列中,且routing key在此将被忽略。

总结

以上三种模式就是最常使用的三种Exchange 模式。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值