本文参考:RabbitMQ官方文档
1. 简介
RabbitMQ是一个开源的消息代理和队列服务器,它提供了一个可靠的消息传递服务,适用于多种场景,包括但不限于异步处理、应用解耦、流量控制和提高消息系统的可靠性。RabbitMQ遵循AMQP(Advanced Message Queuing Protocol)协议,同时也支持其他消息协议,如STOMP、MQTT等。
关键特性以及概念:
-
消息(Message):
消息是传递数据的基本单位,包含有效载荷(payload)和一些属性(如路由键、优先级等)。 -
队列(Queue):
队列是消息的容器,它们存储等待处理的消息。队列是消息的缓冲区,可以存储消息,直到有消费者准备好处理它们。 -
交换器(Exchange):
交换器是RabbitMQ中的核心组件,负责接收来自生产者的消息,并将它们路由到一个或多个队列。交换器有不同类型,包括direct、topic、fanout和headers等,每种类型根据特定的规则来路由消息。 -
绑定(Binding):
绑定是交换器、队列和路由键之间的关系定义。通过绑定,你可以定义消息如何从交换器路由到队列。 -
路由键(Routing Key):
路由键是一个字符串,用于确定消息如何通过交换器路由到队列。它的使用方式取决于交换器的类型。 -
虚拟主机(Virtual Host):
虚拟主机是RabbitMQ服务器的逻辑分区,它们提供了隔离的环境,允许不同的应用程序或不同的部分应用程序使用不同的交换器、队列和绑定,而不会相互干扰。 -
持久化(Persistence):
RabbitMQ支持消息和队列的持久化,这意味着即使在服务器重启之后,消息也不会丢失。 -
集群(Clustering):
RabbitMQ支持集群部署,可以横向扩展以提供更高的吞吐量和可用性。 -
高可用性(High Availability):
通过镜像队列和故障转移机制,RabbitMQ可以在部分节点失败的情况下继续处理消息。 -
消息确认(Message Acknowledgments):
消费者可以发送确认信号,告知消息已经成功处理。这有助于确保消息不会被意外丢失。 -
死信队列(Dead Letter Exchanges):
当消息无法被正常处理时,可以被发送到死信队列,以便后续分析和处理。 -
延迟消息(Delayed Messages):
RabbitMQ支持延迟消息,允许消息在一段时间后再被消费。
2. 基本消息传输流程
交换器、队列和路由键之间的工作流程:
-
生产者(Producer) 发送消息到 交换器(Exchange),并指定一个 路由键(Routing Key)。
-
交换器(Exchange) 根据其类型和路由键来决定如何处理消息:
-
Direct Exchange:查找具有完全相同路由键的绑定。
-
Topic Exchange:查找匹配模式的绑定。
-
Fanout Exchange:不使用路由键,将消息发送到所有绑定的队列。
-
Headers Exchange:查找具有匹配header属性的绑定。
-
-
交换器(Exchange) 根据上述规则将消息路由到一个或多个 队列(Queue)。
如果没有绑定关系,那么:
-
Direct Exchange 和 Topic Exchange 会丢弃消息,因为没有绑定的队列可以接收它。
-
Fanout Exchange 会将消息发送到所有绑定的队列,不论路由键是什么,因为扇形交换器不使用路由键进行路由。
-
Headers Exchange 也会丢弃消息,因为没有绑定的队列可以匹配消息的header属性。
3. 相关概念图
-
工作队列
工作队列(又称任务队列)背后的主要思想是避免立即执行资源密集型任务并等待其完成。相反,将任务安排在稍后完成。将任务封装 为消息并将其发送到队列。在后台运行的工作进程将弹出任务并最终执行该作业。当运行许多工作进程时,任务将在它们之间共享。
-
路由
根据不同的routingKey将消息推送到不同的queue。
-
发布订阅
使用相同的绑定键绑定多个队列是完全合法的。在X
和之间添加绑定,Q1
绑定键为vlog。在这种情况下,交换机direct
将表现得像fanout
并将消息广播到所有匹配的队列。具有路由键的消息vlog将同时传递给 Q1
和Q2。
4. 案例
定义交换器、路由键、队列之间的关系
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitConfig {
// 定义队列
@Bean
public Queue myQueue() {
return new Queue("queue", true); // true表示队列持久化
}
// 定义Direct交换器
@Bean
public DirectExchange myExchange() {
return new DirectExchange(" exchange");
}
// 定义队列和交换器之间的绑定
@Bean
public Binding binding(Queue myQueue, DirectExchange myExchange) {
return BindingBuilder.bind(myQueue).to(myExchange).with("routingKey");
}
}
发送消息
package com.xiaokai.service;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Author:yang
* Date:2024-10-15 15:02
*/
@Service
public class SendService {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendMessage(String message){
rabbitTemplate.convertAndSend("exchange","routingKey",message);
}
}
消费消息
package com.xiaokai.listener;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* Author:yang
* Date:2024-10-15 15:11
*/
@Component
public class MessageListener {
@RabbitListener(queues = "queue")
public void processMessage(String message) {
System.out.println("Received message: " + message);
}
}