RabbitMQ可以看作是一个用于存储和转发消息的服务器。它本质上是一个消息代理,负责管理和传递消息。具体来说,RabbitMQ 的功能包括:
1. 消息存储:当生产者发送消息时,RabbitMQ 可以将消息存储在队列中,直到消费者从队列中取出并处理。这使得即使消费者暂时不可用,消息也不会丢失。
2. 消息路由:RabbitMQ 通过 交换机(Exchange)和路由键(Routing Key)来决定消息应该发送到哪个队列中。不同类型的交换机(如 Direct、Topic、Fanout 等)提供了灵活的消息路由机制。
3. 消息确认:RabbitMQ 可以在消费者成功处理完消息后收到确认(ACK),确保消息被成功消费。未确认的消息可以重新发送或转移到死信队列中。
4. 持久化:RabbitMQ 支持消息持久化。生产者可以将消息标记为持久化,RabbitMQ 会将这些消息保存到磁盘上,以防止在服务器宕机时消息丢失。
因此,RabbitMQ 不仅仅是简单的消息传递工具,它还具备存储消息的能力,确保消息在生产者和消费者之间的可靠传递。
1.work模型
让多个消费者绑定到一个队列,共同消费队列中的消息。
默认情况下,RabbitMQ的会将消息依次轮询投递给绑定在队列上的每一个消费者。但这并没有考虑到消费者是否已经处理完消息,可能出现消息堆积(没有做到能者多劳)。
解决方法:修改application.yml,设置preFetch值为1,确保同一时刻最多投递给消费者1条消息
2.Fanout(广播)交换机
Fanout Exchange 会将接收到的消息广播到每一个跟其绑定的queue,所以也叫广播模式。
3.Direct(定向)交换机
Direct Exchange 会将接收到的消息根据规则路由到指定的Queue,因此称为定向路由。
● 每一个Queue都与Exchange设置一个BindingKey
● 发布者发送消息时,指定消息的RoutingKey
● Exchange将消息路由到BindingKey与消息RoutingKey一致的队列
4.Topic(话题)交换机
TopicExchange与DirectExchange类似,区别在于routingKey可以是多个单词的列表,并且以.分割。
Queue与Exchange指定BindingKey时可以使用通配符:
#:代指0个或多个单词
*:代指一个单词
5.用Java声明队列和交换机
方法一:基于Bean
例如,声明一个Fanout类型的交换机,并且创建队列与其绑定:
@Configuration
public class FanoutConfig {
//声明FanoutExchange交换机
@Bean
public FanoutExchange fanoutExchange() {
return new FanoutExchange("hmall. fanout");
}
//声明第1个队列
@Bean
public Queue fanoutQueue1() {
return new Queue("fanout.queue1");
}
//绑定队列1和交换机
@Bean
public Binding bindingQueue1(Queue fanoutQueue1, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
}
//以相同的方式生成更多的队列、交换机,完成绑定
}
绑定的方式还可以是这样:
@Bean
public Binding bindingQueue1() {
return BindingBuilder.bind(fanoutQueue1()).to(fanoutExchange());
}
方法二:基于注解
public class MQListener {
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "direct.queue1"),
exchange = @Exchange(name = "thehao.direct", type = ExchangeTypes.DIRECT),
key = {"red", "blue"}
))
public void listenDirectQueue1(String msg) {
System.out.println("消费者1接收Direct消息:[" + msg + "]");
}
}
6.消息转换器
RabbitMQ默认使用JDK序列化,转换后体积大、可读性低,并且不安全。
解决方法:使用JSON序列化。
步骤:
1.在publisher和consumer引入jackson依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
2.在publisher和consumer启动类中配置MessageConverter
@Bean
public MessageConverter jacksonMessageConvertor () {
return new Jackson2JsonMessageConverter();
}