如何在Spring Boot中集成RabbitMQ

如何在Spring Boot中集成RabbitMQ

在现代微服务架构中,消息队列(如RabbitMQ)扮演了关键的角色,它不仅能够提供高效的消息传递机制,还能解耦服务间的通信。本文将介绍如何在Spring Boot项目中集成RabbitMQ,实现生产者和消费者的基本配置。

步骤1:添加Maven依赖

首先,在你的Spring Boot项目的pom.xml中添加spring-boot-starter-amqp依赖:

java 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

这个starter包含了与RabbitMQ集成所需的所有基本依赖。

步骤2:配置RabbitMQ

在application.yml或application.properties中配置RabbitMQ的连接信息:

java 复制代码
spring:
  rabbitmq:
    host: 10.5.2.27
    port: 30700
    username: user
    password: Sungrow@2023

步骤3:实现生产者

在Spring Boot中,发送消息到RabbitMQ的生产者可以很简单地通过RabbitTemplate实现:

java 复制代码
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.web.bind.annotation.*;
import com.alibaba.fastjson.JSONObject;

@RestController
@RequestMapping("/menu")
public class MenuController {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @PostMapping("/add")
    public Result<SysPermission> add(@RequestBody SysPermission permission) {
        // ... 添加菜单的业务逻辑
        rabbitTemplate.convertAndSend(RabbitConstant.GOODS_EXCHANGE, RabbitConstant.MENU_MESSAGE, JSONObject.toJSONString(permission));
        return new Result<SysPermission>().success("添加成功!");
    }
}

这里,convertAndSend方法用于发送消息到指定的交换机和路由键。

步骤4:配置RabbitMQ交换机、队列和绑定

在Spring Boot中,可以通过配置类来定义交换机、队列和它们之间的绑定关系:

java 复制代码
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQConfig {
    // 定义交换机、队列、路由键等常量
    // ... 

    @Bean
    public Queue queueA() {
        return new Queue(GOODS_QUEUE_A, true);
    }

    @Bean
    TopicExchange myExchange() {
        return new TopicExchange(GOODS_EXCHANGE);
    }

    @Bean
    Binding bindingA(Queue queueA, TopicExchange exchange) {
        return BindingBuilder.bind(queueA).to(exchange).with(GOODS_APP_ROUTING);
    }

    // 其他队列和绑定的定义
    // ...
}

这段代码定义了队列、交换机,并将它们通过路由键绑定起来。

有了配置后,启动服务,可以在rabbitmq控制台看到该交换机,队列以及他们之间的绑定

点进去后可以看到绑定的队列,

如果点进来,没有显示这个绑定队列,就说明配置的不对,后续也无法消费,点进队列后,就会显示队列中的消息了

步骤5:实现消费者

消费者用于处理接收到的消息。使用@RabbitListener注解可以很容易地实现:

java 复制代码
import org.springframework.amqp.rabbit.annotation.RabbitListener;

@Component
public class MessageReceiver {

    @RabbitListener(bindings = @QueueBinding(
        value = @Queue(name = RabbitMQConfig.GOODS_QUEUE_A),
        exchange = @Exchange(name = RabbitMQConfig.GOODS_EXCHANGE, type = ExchangeTypes.TOPIC),
        key = RabbitMQConfig.GOODS_APP_ROUTING
    ))
    public void receiveAppMessage(Message message, Channel channel) {
        // 处理接收到的消息
        // ...
    }

    // 其他消费者方法
    // ...
}

这里,@RabbitListener注解定义了消息的监听和处理逻辑。

步骤6:处理死信队列

配置死信队列:

java 复制代码
@Bean
public Queue deadQueue() {
    Map<String, Object> args = new HashMap<>();
    args.put("x-dead-letter-exchange", DEAD_EXCHANGE_A);
    args.put("x-dead-letter-routing-key", DEAD_ROUTING_KEY_A);
    return new Queue(DEAD_QUEUE_A, true, false, false, args);
}

@Bean
DirectExchange deadExchange() {
    return new DirectExchange(DEAD_EXCHANGE_A, true, false);
}

@Bean
Binding bindingDead(Queue deadQueue, DirectExchange deadExchange) {
    return BindingBuilder.bind(deadQueue).to(deadExchange).with(DEAD_ROUTING_KEY_A);
}

在RabbitMQ中,死信队列(Dead Letter Queue, DLQ)用于存储无法正常处理的消息。消息可能由于几种原因被发送到死信队列,包括:

消息被拒绝(Basic.Reject/Basic.Nack):当消费者明确拒绝消息且不重新排队时(通过设置requeue为false),消息会进入死信队列。

消息过期:如果消息在队列中存活时间超过设定的TTL(Time-To-Live),它会被自动发送到死信队列。

队列达到最大长度:如果队列设置了最大长度并达到这个限制,最老的消息可能会被移动到死信队列。

在Spring Boot集成的RabbitMQ应用中,通常会在消费者处理消息时发生异常的情况下,明确地将消息发送到死信队列。例如:

java 复制代码
 
@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = RabbitMQConfig.GOODS_QUEUE_A),
    exchange = @Exchange(name = RabbitMQConfig.GOODS_EXCHANGE, type = ExchangeTypes.TOPIC),
    key = RabbitMQConfig.GOODS_APP_ROUTING
))
public void receiveAppMessage(Message message, Channel channel) throws IOException {
    try {
        // 处理消息
    } catch (Exception e) {
        // 处理消息失败,拒绝消息并不重新排队
        channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
        // 将消息发送到死信队列
        rabbitTemplate.convertAndSend(RabbitMQConfig.DEAD_EXCHANGE_A, RabbitMQConfig.DEAD_ROUTING_KEY_A, message);
    }
}

在这个例子中,如果在处理消息的过程中发生异常,消息会被明确地拒绝,并发送到配置的死信队列。

为什么使用死信队列

避免消息丢失:死信队列确保无法处理的消息不会被丢失,而是存储在一个特定的地方,供进一步的检查和处理。

分析和调试:可以对死信队列中的消息进行分析,以确定为什么消息不能被正常处理。

避免重复处理无效消息:通过将无法处理的消息移动到死信队列,防止消费者重复尝试处理同一消息,这可能导致无限循环。

死信队列(DLQ)用于处理无法正常消费的消息。配置死信队列类似于配置普通队列,但需要一些额外的参数,如TTL(Time-To-Live)和死信交换机:

复制代码
相关推荐
嘵奇1 小时前
深入解析 Spring Boot 测试核心注解
java·spring boot·后端
陈平安Java and C2 小时前
RabbitMQ简单介绍和安装
rabbitmq
陈平安Java and C2 小时前
RabbitMQ应用2
rabbitmq
技术liul2 小时前
解决Spring Boot Configuration Annotation Processor not configured
java·spring boot·后端
RainbowSea3 小时前
4. RabbitMQ 发布确认的配置详细说明
java·消息队列·rabbitmq
腥臭腐朽的日子熠熠生辉5 小时前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
绝顶少年7 小时前
Spring Boot 注解:深度解析与应用场景
java·spring boot·后端
雨会停rain7 小时前
如何提高rabbitmq消费效率
分布式·rabbitmq
西木风落7 小时前
springboot整合Thymeleaf web开发出现Whitelabel Error Page
spring boot·thymeleaf error·whitelabelerror
hycccccch7 小时前
RabbitMQ技术方案分析
数据库·rabbitmq