RabbitMQ(006 消息可靠性part1)

本文详细介绍了如何在12小时内通过RabbitMQ教程学习消息可靠性,包括生产者消费者模式、ConfirmCallback接口的使用、Spring集成、依赖注入方式,以及交换机属性如持久化和路由设置。

动力节点RabbitMQ教程|12小时学会rabbitmq消息中间件

总时长 12:20:00 共65P

此文章包含第38p-第p44的内容


消息可靠性

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

confirm (保证 消息到交换机的安全性)

外部类写法

在这里插入图片描述

函数式接口长这样
在这里插入图片描述

在这里插入图片描述

第一步:开启生产者消费模式

在这里插入图片描述

第二步:实现ConfirmCallback接口

在这里插入图片描述

第三步:在发送消息的rabbitTemplate里设置 回调接口

spring自动装配 只要把jar包引入进来 springboot就会把rabbitTemplate可以放到map里 直接使用rabbitTemplate

演化方向(将类放到xml里 -》 使用 @Bean注解 -》 使用spring自动装配 直接通过pom文件引入jar包进行引用)
在这里插入图片描述

依赖注入
在这里插入图片描述

在这里插入图片描述

第二种写法 在发送消息的类里直接实现

set时把this自己进去
在这里插入图片描述

在这里插入图片描述

第三种写法 匿名内部类

缺点 其他类想引用 无法引用 因为没有名称 所以叫匿名内部类 而且因为无名其他类无法引用
在这里插入图片描述
在这里插入图片描述

第四种写法 使用lambda表达式

只适用于 只有一个抽象方法的接口
在这里插入图片描述

在这里插入图片描述

类型也可以去掉
在这里插入图片描述
作用 简化匿名内部类的写法

return(保证 交换机到队列的安全性)

在这里插入图片描述

第一步 开启return模式

在这里插入图片描述

第二步 实现外部类接口

在这里插入图片描述

第三步 在发送类里设置一个回调函数

在这里插入图片描述

路由写错时 返回错误信息
在这里插入图片描述
响应文本 这样多一些
在这里插入图片描述
原因:无路由
在这里插入图片描述

第二种方法

发送类自己实现接口
在这里插入图片描述
在这里插入图片描述

第三种 匿名内部类

在这里插入图片描述

在这里插入图片描述

这个是函数式接口,但是有三个方法 仔细看会发现有两个方法是default开头的,所以它俩已经实现了 所以不是抽象方法
在这里插入图片描述
只有一个抽象方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
使用lambda表达式 只有一个参数时 连括号都可以省略
在这里插入图片描述

在这里插入图片描述

交换机属性(保证 队列到的安全性)

在这里插入图片描述

在这里插入图片描述

交换机属性

持久化 属性 durable

在这里插入图片描述

durable 持久化 默认值是true 开启持久化 如果不开的话(false) 重启mq之后会自动消失

在这里插入图片描述

在这里插入图片描述

rabbitmqctl shutdown      ----关闭mq

rabbitmq-server -detached     ----启动mq

在这里插入图片描述

在这里插入图片描述

自动删除 autoDelete

默认不自动删除,没有队列和他绑定的时候 会自动删除掉

在这里插入图片描述

在这里插入图片描述

内部 internal

一般不使用 用于交换机与交换机直接的绑定


<think>我们正在处理关于RabbitMQ的问题,用户询问如何监听整个交换机的消息。在RabbitMQ中,消费者通常从队列中消费消息,而不是直接从交换机。要监听交换机上的所有消息,需要创建一个队列并将其绑定到该交换机,然后消费该队列。根据引用[1],我们看到了一个使用rabbitpy库消费队列的例子,其中设置了`no_ack=True`,表示不确认消息。但这里的关键是,消费者必须绑定到一个队列。引用[2]提供了一些RabbitMQ的参考资料,其中提到了交换机和绑定(bindings)的概念。交换机通过路由键(routingkey)将消息路由到绑定的队列。因此,要监听整个交换机的消息,我们需要将队列绑定到该交换机,并使用合适的绑定键(bindingkey)。如果我们想接收所有消息,可以使用通配符(在topic交换机中)或者使用fanout交换机(它会将消息广播到所有绑定的队列)。引用[3]展示了SpringBoot集成RabbitMQ的配置,其中生产者使用`amqpTemplate.convertAndSend("myQueue",message);`发送消息到名为"myQueue"的队列。但这里并没有直接绑定交换机的例子。引用[4]描述了交换机的属性,如名称、持久性等。因此,解决方案步骤如下:1.创建一个队列(可以是临时的,也可以是持久的)。2.将该队列绑定到目标交换机。绑定键取决于交换机的类型:-对于fanout交换机:绑定键会被忽略,所以绑定任何键(或者不指定)都会接收到所有消息。-对于direct交换机:需要为每个路由键分别绑定,所以如果要接收所有消息,需要绑定所有可能的路由键(这通常不现实)。-对于topic交换机:可以使用通配符(如`#`)来匹配所有路由键。3.然后消费该队列。如果用户想要监听交换机上的所有消息,最直接的方式是使用fanout交换机,或者如果使用topic交换机,则使用`#`作为绑定键。另外,如果用户只是临时监听,可以创建一个匿名队列(服务器生成名称)并绑定到交换机,这样当消费者断开时,队列会被自动删除。下面我们将给出一个示例,使用rabbitpy(如引用[1])和SpringAMQP(如引用[3])的两种方式。注意:在RabbitMQ中,不能直接“监听交换机”,因为交换机只是一个路由消息的组件,消息必须通过队列来接收。因此,我们给出两种代码示例:1.使用rabbitpy(Python):-首先连接到RabbitMQ。-创建一个通道。-声明一个交换机(如果还不存在,这一步可选,但通常交换机应该已经存在)。-创建一个队列(可以是非持久的、自动删除的)。-将队列绑定到交换机,使用fanout类型或者使用通配符(根据交换机类型)。-然后消费该队列。2.使用SpringBoot(Java):-配置一个队列,并绑定到目标交换机。-使用`@RabbitListener`监听该队列。由于用户问题中没有指定语言,我们将提供两种常见语言的示例。但是,请注意,用户上一次的问题中使用了Python(rabbitpy)和SpringBoot(Java)的代码片段,因此我们参考这些。由于引用中提供了rabbitpy和SpringBoot的例子,我们分别展示。首先,使用rabbitpy(Python)监听fanout交换机的所有消息:假设我们有一个fanout交换机,名为'my_fanout_exchange'。步骤:1.创建连接和通道。2.声明交换机(如果不存在则创建,这里假设是fanout类型)。3.创建一个临时队列(当连接关闭时自动删除)。4.将队列绑定到交换机(fanout交换机不需要指定路由键)。5.消费该队列。代码示例:```pythonimportrabbitpyurl='amqp://guest:guest@localhost:5672/%2F'withrabbitpy.Connection(url)asconnection:withconnection.channel()aschannel:#声明一个fanout交换机(如果不存在则创建)exchange=rabbitpy.Exchange(channel,'my_fanout_exchange',exchange_type='fanout')exchange.declare()#创建一个临时队列,队列名由服务器生成,连接关闭后自动删除queue=rabbitpy.Queue(channel,exclusive=True,auto_delete=True)queue.declare()#绑定队列到交换机,fanout交换机不需要路由键queue.bind(exchange.name,routing_key='')#消费队列中的所有消息formessageinqueue.consume_messages(no_ack=True):message.pprint()```如果交换机是topic类型,我们可以使用通配符`#`来匹配所有路由键。绑定步骤改为:queue.bind(exchange.name,routing_key='#')其次,使用SpringBoot(Java)监听fanout交换机的所有消息:在SpringBoot中,我们可以使用`@RabbitListener`注解来监听队列。但我们需要先声明队列、交换机和绑定。配置方式(在配置类中):```java@ConfigurationpublicclassRabbitMQConfig{@BeanpublicFanoutExchangemyFanoutExchange(){returnnewFanoutExchange("my_fanout_exchange");}@BeanpublicQueuefanoutQueue(){//创建一个临时队列,匿名队列(非持久,独占,自动删除)returnnewAnonymousQueue();}@BeanpublicBindingbinding(FanoutExchangemyFanoutExchange,QueuefanoutQueue){returnBindingBuilder.bind(fanoutQueue).to(myFanoutExchange);}}```然后在监听器类中:```java@ComponentpublicclassFanoutListener{@RabbitListener(queues="#{fanoutQueue.name}")publicvoidreceiveMessage(Stringmessage){System.out.println("Receivedfromfanout:"+message);}}```这样,当有消息发送到交换机"my_fanout_exchange"时,该队列就会收到消息,然后被`receiveMessage`方法处理。对于topic交换机,我们可以使用通配符绑定:```java@ConfigurationpublicclassRabbitMQConfig{@BeanpublicTopicExchangemyTopicExchange(){returnnewTopicExchange("my_topic_exchange");}@BeanpublicQueuetopicQueue(){returnnewAnonymousQueue();}@BeanpublicBindingbinding(TopicExchangemyTopicExchange,QueuetopicQueue){//使用通配符#绑定所有路由键returnBindingBuilder.bind(topicQueue).to(myTopicExchange).with("#");}}```监听器类似。总结:要监听整个交换机的消息,必须创建一个队列并绑定到该交换机,根据交换机的类型选择合适的绑定方式(fanout直接绑定,topic用通配符#),然后消费该队列。注意:在实际应用中,考虑队列的持久化和消息的确认机制(如引用[1]中的`no_ack=True`会关闭确认,可能导致消息丢失,除非不关心消息可靠性)。最后,生成相关问题。</think>### RabbitMQ 监听交换机所有消息的方法 在 RabbitMQ 中,**消费者不能直接从交换机消费消息**。必须通过队列作为中介:交换机将消息路由到队列,消费者再从队列获取消息。要监听交换机所有消息,需执行以下步骤: #### 核心步骤 1. **创建队列** - 创建临时队列(推荐)或持久化队列 - 临时队列特性:`exclusive=true`(独占)或 `auto-delete=true`(自动删除) ```python # Python (rabbitpy) queue = rabbitpy.Queue(channel, exclusive=True) # 创建临时队列 queue.declare() ``` 2. **绑定队列到交换机** - **Fanout 交换机**:绑定时不需路由键(自动接收所有消息) ```python queue.bind(exchange_name, routing_key='') # Fanout 忽略路由键 ``` - **Topic/Direct 交换机**:使用通配符 `#` 匹配所有路由键 ```python queue.bind(exchange_name, routing_key='#') # 匹配所有消息 ``` 3. **消费队列消息** ```python # Python 示例 (rabbitpy) for message in queue.consume_messages(): print(f"收到消息: {message.body}") message.ack() # 手动确认 ``` #### 完整流程示例(Python) ```python import rabbitpy # 连接配置 url = 'amqp://user:pass@host:port/vhost' exchange_name = 'your_exchange' # 目标交换机名 with rabbitpy.Connection(url) as conn: with conn.channel() as channel: # 1. 创建临时队列 queue = rabbitpy.Queue(channel, exclusive=True) queue.declare() # 2. 绑定到交换机(匹配所有路由键) queue.bind(exchange_name, routing_key='#') # '#' 匹配所有消息 # 3. 消费消息 print(f"监听交换机: {exchange_name}, 队列: {queue.name}") for message in queue.consume_messages(): print(f"收到消息: {message.body}") message.ack() ``` #### Spring Boot 配置(Java) ```java @Configuration public class RabbitConfig { // 声明交换机 @Bean public FanoutExchange exchange() { return new FanoutExchange("your_exchange"); } // 创建临时队列 @Bean public Queue tempQueue() { return new AnonymousQueue(); // 自动生成临时队列 } // 绑定队列到交换机 @Bean public Binding binding(FanoutExchange exchange, Queue tempQueue) { return BindingBuilder.bind(tempQueue).to(exchange); } } // 消息监听 @Component public class Listener { @RabbitListener(queues = "#{tempQueue.name}") public void handleMessage(String message) { System.out.println("收到消息: " + message); } } ``` ### 关键注意事项 1. **交换机类型支持**: - `Fanout`:天然广播所有消息 - `Topic/Direct`:需用 `#` 通配符绑定 - `Headers`:需配置匹配所有头的绑定 2. **队列特性**: - 临时队列(`exclusive=true`)在消费者断开后自动删除 - 持久化队列需显式声明 `durable=true`[^4] 3. **消息确认**: - 关闭自动确认(`no_ack=false`)确保可靠消费 - 处理失败时需 `reject` 或重试[^1] > **原理**:RabbitMQ 消息流始终遵循 `生产者 → 交换机 → 队列 → 消费者` 路径。直接监听交换机不可行,必须通过队列中介[^2]。 --- ### 相关问题 1. 如何区分 RabbitMQ 中 `fanout` 和 `topic` 交换机的使用场景? 2. RabbitMQ 临时队列和持久化队列在可靠性方面有何差异? 3. 如何实现 RabbitMQ 消息消费失败后的自动重试机制? 4. 在 Spring Boot 中如何动态创建多个交换机监听器? 5. RabbitMQ 的通配符 `#` 和 `*` 在路由键匹配中有何区别?[^2] [^1]: 当要消费消息时,你的应用注册自己到RabbitMQ。会发送一个Basic.Consume请求,同时包含no-ack标志。当此标志为True,这会告诉RabbitMQ你的消费者不会确认收到的消息,因此RabbitMQ应该尽可能快的发送消息。 [^2]: https://www.rabbitmq.com https://www.cloudamqp.com/blog/2015-09-03-part4-rabbitmq-for-beginners-exchanges-routing-keys-bindings.html 《RabbitMQ实战》 [^4]: Name:交换机名称 Durability:是否持久化。如果持久性,则RabbitMQ重启后,交换机还存在 Auto-delete:当所有与之绑定的消息队列都完成了对此交换机的使用后,删掉它 Arguments:扩展参数
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值