RabbitMQ学习笔记(未完)

75 阅读4分钟

基础

RabbitMQ组成

生产者(发送消息)、exchange、queue、binding、消费者(接受消息)。

实现方式

  1. 使用RabbitMQ控制台可以手工增加exchange、queue、binding(绑定交换机和队列),发送消息。
  2. Java代码实现可以通过SpringAMQP进行。

SpringAMQP

  1. 使用工具类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 实例(用于自定义消息转换逻辑)。
  1. 在配置文件application.yml配置RabbitMQ服务器信息:
spring:
  rabbitmq:
    host: localhost ## ip地址
    port: 5672  ##端口
    username: guest 
    password: guest
    virtual-host: /  ## 虚拟机

  1. 声明队列交换机的类:
    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);
    }
  1. RabbitMQ可以配置多个virtual-host虚拟机,满足不同业务场景。
  2. 一个队列可以有多个消费者,处理消息,基于不同消费者的性能考虑,可在配置文件中增加配置,确保同一时刻最多投递给消费者1条消息,保证能者多劳:
spring:
  rabbitmq:
    listener:
        simple:
            prefetch: 1
  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();
    }
}

高级