RabbitMQ 各类交换机
为什么要用交换机?
交换机用来路由消息。如果直发队列,这个消息就被处理消失了,那别的队列也需要这个消息怎么办?那就要用到交换机
交换机类型
1,fanout:广播
特点
广播所有消息:将消息发送到所有绑定到该交换机的队列(忽略 routing_key
)。
无过滤:所有消费者都会收到相同的消息副本。
适用场景
系统通知(如全局公告)。
事件广播(如用户注册后触发邮件、短信、积分发放)。
控制台定义好交换机(交换机类型)、队列。
绑定交换机和队列。
java写代码消息发送者发送消息到交换机。
java写代码实现消费者,绑定监听的队列。
消息发送者将消息发送到交换机,交换机路由消息到各个队列,消费者处理队列里的消息。
2,Direct:定向
特点
队列和交换机约定一个(暗号)routing_key
。
交换机里面有个记录表,记录了各个队列的 routing_key
(队列也可以绑定多个不同key,不同队列也可以绑定相同的routing_key
)
消息发送者发消息时,指定消息的routing_key
交换机 根据 发送者发来的 routing_key 在自己的表里找到相同的routing_key
的队列
一对一或一对多:可通过多个队列绑定相同的 routing_key
实现多消费者接收。
适用场景
分类任务处理(如将 error
日志发送到错误处理队列)。
订单状态更新(如 order.paid
路由到支付服务)。
3,Topic:话题(推荐使用)
特点
通配符匹配 routing_key
:
*
(星号):匹配一个单词(如 order.*
可匹配 order.paid
)。
#
(井号):匹配零或多个单词(如 order.#
可匹配 order.paid.2023
)。
灵活路由:适合需要多维度分类的场景。
适用场景
多级日志分类(如 app.error
、app.warning
)。
复杂事件路由(如 user.signup.email
、user.signup.sms
)。
声明队列交换机
队列都在控制台生成,比较繁琐,容易出错。后面可能还有更多队列和交换机。开发环境转实际运行环境还要手动去控制台里添加,比较繁琐,容易出错。
如何在java代码里声明队列、交换机
队列和交换机一般在消费者这边声明。发送方不关心队列,只关心交换机
加了bean的方法都会被spring动态代理。当我们调用这个方法时,spring会先检查spring容器里有没有这个bean。如果有这个bean,直接返回bean,没有才执行方法中的代码
绑定队列和交换机传参有两种方式
形参传参, 直接调用方法绑定(直接从spring容器里取,并没有调用这个方法)
存在的问题
当我们写direct时,我们要写routingKey,每写一个routingKey都要写一个bean,太繁琐了
如何解决:利用@RabbitListener注解来写
消息转换器
当发送的消息不是massage类型,是map、java类时,消息放松会自动序列化为字节码,体积变大,可读性差,还可能有安全漏洞
改变消息转换器,采用json序列化
转换器必须再收发方都要有。声明了消息转换器后,其他代码都不用变。只用改变消息接收类型。
消息消费者处理失败了,消息直接丢失了,这种情况如何解决?