基础
RabbitMQ组成
生产者(发送消息)、exchange、queue、binding、消费者(接受消息)。
实现方式
- 使用RabbitMQ控制台可以手工增加exchange、queue、binding(绑定交换机和队列),发送消息。
- Java代码实现可以通过
SpringAMQP进行。
SpringAMQP
- 使用工具类
RabbitTemplate;
发送消息相关方法
| 方法名 | 功能描述 |
|---|---|
| convertAndSend(String exchange,String routingKey,Object message) | 将对象转换为消息并发送到指定交换机和路由键 |
| convertAndSend(String exchange,String routingKey,Object meaasge,MessagePostProcessor postProcessor) | 发送消息前允许对消息进行额外处理,例如添加头信息 |
| send(String exchange,String routingKey,Message message) | 直接发送一个Message对象到指定的交换机和路由键 |
| send(String exchange,String routingKey,Message message,CorrelationData correlationDate) | 发送消息时可以携带关联数据(用于确认机制) |
消费者接收消息的时候,一般通过@RabbitListener 注解进行消息接收。
以下方法可进行了解:
消息接收相关方法
| 方法名 | 功能描述 |
|---|---|
| receive(String queueName) | 从指定队列中接收一条消息(阻塞式,直到有消息可用) |
| receiveAndConvert(String queueName) | 接收消息并将其转换为目标类型(默认为字符串)。 |
| doReceive() | 内部方法,用于直接从信道中接收消息(通常不建议直接调用)。 |
回掉确认机制相关方法
| 方法名 | 功能描述 |
|---|---|
| setConfirmCallback(RabbitTemplate.ConfirmCallback confirmCallback) | 设置发送消息后的确认回调(适用于发布确认模式)。 |
| setReturnCallback(RabbitTemplate.ReturnCallback returnCallback) | 设置消息未被路由时的回调(适用于消息返回机制)。 |
异步发送相关方法
| 方法名 | 功能描述 |
|---|---|
| execute(ChannelCallback action) | 在当前线程的 RabbitMQ 信道上执行自定义操作(支持异步逻辑)。 |
| asyncSend(String exchange, String routingKey, Message message) | 异步发送消息(需要配置异步支持)。 |
其他方法
| 方法名 | 功能描述 |
|---|---|
| convertSendAndReceive(String exchange, String routingKey, Object request) | 发送消息并等待响应(类似于 RPC 调用)。 |
| convertSendAndReceive(String exchange, String routingKey, Object request, MessagePostProcessor postProcessor) | 发送消息并等待响应,同时允许对消息进行额外处理 |
| getMessageConverter() | 获取当前使用的 MessageConverter 实例(用于消息转换逻辑)。 |
| setMessageConverter(MessageConverter messageConverter) | 设置自定义的 MessageConverter 实例(用于自定义消息转换逻辑)。 |
- 在配置文件
application.yml配置RabbitMQ服务器信息:
spring:
rabbitmq:
host: localhost ## ip地址
port: 5672 ##端口
username: guest
password: guest
virtual-host: / ## 虚拟机
- 声明队列交换机的类:
Queue:声明队列,可以使用工厂类QueueBuilder构建;
Exchange:声明交换机,可以使用工厂类ExchangeBuilder构建;
| 交换机类型 | 特点 | 应用场景 |
|---|---|---|
| Fanout Exchange (广播模式) | 不关心路由键(Routing Key)将消息广播到所有绑定的队列 | 适用于需要将消息广播到多个消费者的情况,例如:日志收集、通知系统 |
| Direct Exchange(定向路由) | 根据路由键(Routing Key)精确匹配消息发送到与路由键完全匹配的队列(一个队列可以有多个路由键) | 适用于一对一的消息分发场景,例如:根据消息类型将消息发送到特定队列进行处理 |
| Topic Exchange | 基于路由模式匹配(支持通配符*和#) 路由键(Routing Key)可以是多级结构 建议使用该交换机 | 适用于需要灵活匹配的消息分发场景,例如根据设备类型或区域分发消息 |
| Headers Exchange | 不依赖路由键(Routing Key)根据消息头(Headers)中的键值对进行匹配 | 适用于需要基于复杂条件匹配消息的场景 - 例如:根据用户角色或其他属性分发消息 |
| Custom Exchange(自定义交换机) | 自定义路由逻辑,需要通过插件实现 | 复杂业务场景,内置交换机无法满足需求时 |
| Dead Letter Exchange(死信交换机) | 处理未被成功消费的消息,需要队列声明时配置参数,可用于延迟消息 | 监控和处理异常消息,如消息超时、队列满、消费者拒绝消息 |
Binding:声明队列和交换机的绑定关系,可以使用工厂类BindingBuilder构建。
实现方式
- 通过定义
@Bean的方式使用上述提到的工具类进行队列、交换机、绑定关系的声明。 - 使用注解
@RabbitListener进行声明(一般在消费者那里声明)
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "my.topic.queue", durable = "true"), // 指定监听的持久化队列
exchange = @Exchange(value = "my.topic.exchange", type = "topic", durable = "true"), // 持久化 Topic 交换机
key = "my.routing.key" // 路由键 可以是多个key使用{}
))
public void handleMessage(String message) {
System.out.println("Received message: " + message);
}
- RabbitMQ可以配置多个virtual-host虚拟机,满足不同业务场景。
- 一个队列可以有多个消费者,处理消息,基于不同消费者的性能考虑,可在配置文件中增加配置,确保同一时刻最多投递给消费者1条消息,保证能者多劳:
spring:
rabbitmq:
listener:
simple:
prefetch: 1
- 使用JSON进行序列化:
导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-amqp'
implementation 'com.fasterxml.jackson.core:jackson-databind'
}
配置类
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitConfig {
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
template.setMessageConverter(jsonMessageConverter());
return template;
}
@Bean
public MessageConverter jsonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
}