当前位置:首页 > 技术 > 正文内容

RabbitMQ 部署、配置及应用示例

访客 技术 2026年7月17日 1

本指南将介绍如何在 Linux 环境下使用 Docker 部署 RabbitMQ,并配置 Spring Boot 应用以实现消息队列的集成和实际应用。

Docker 部署 RabbitMQ

请确保您的 Linux 系统(以 CentOS 7.8 为例)已安装 Docker。执行以下命令以启动 RabbitMQ 容器,并启用管理界面:


docker run -d \
  --name rabbitmq_manager \
  -e RABBITMQ_DEFAULT_USER=myuser \
  -e RABBITMQ_DEFAULT_PASS=mypassword \
  -p 15672:15672 \
  -p 5672:5672 \
  rabbitmq:3.9.7-management
    

部署完成后,请在服务器的网络安全组中开放以下端口:

  • 4369: Erlang 端口发现
  • 5672: AMQP 客户端通信端口
  • 15672: 管理界面 UI 端口
  • 25672: RabbitMQ 集群节点间通信端口

您可以通过访问 http://<服务器IP>:15672 来打开 RabbitMQ 管理界面。

Spring Boot 引入 RabbitMQ 依赖

在您的 Spring Boot 项目的 pom.xml 文件中添加 spring-boot-starter-amqp 依赖:


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
    

Spring Boot 配置文件

application.propertiesapplication.yml 文件中配置 RabbitMQ 连接信息:


spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: myuser
    password: mypassword
    virtual-host: /
    listener:
      simple:
        # 消息确认模式: auto (自动确认) 或 manual (手动确认)
        acknowledge-mode: auto
        retry:
          # 开启消费者消息重试机制
          enabled: true
          # 最大重试次数
          max-attempts: 3
          # 重试间隔时间 (毫秒)
          max-interval: 5000
    

RabbitMQ 配置类

以下示例定义了一个 Topic 类型的交换机,以及两个队列,并使用通配符路由键将它们绑定到交换机。这种配置适用于需要根据消息内容进行分发和处理的场景。


package com.example.mq;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQConfig {

    // 定义交换机名称
    public static final String MY_EXCHANGE = "my_app.exchange";

    // 定义队列名称
    public static final String QUEUE_ONE = "my_app.queue.one";
    public static final String QUEUE_TWO = "my_app.queue.two";

    // 定义路由键模式
    public static final String ROUTING_KEY_PATTERN_ONE = "data.process.*";
    public static final String ROUTING_KEY_PATTERN_TWO = "data.*.details";

    /**
     * 配置Topic类型的交换机
     */
    @Bean
    public Exchange myExchange() {
        return new TopicExchange(MY_EXCHANGE, true, false);
    }

    /**
     * 配置第一个队列
     */
    @Bean
    public Queue queueOne() {
        return new Queue(QUEUE_ONE, true, false, false);
    }

    /**
     * 配置第二个队列
     */
    @Bean
    public Queue queueTwo() {
        return new Queue(QUEUE_TWO, true, false, false);
    }

    /**
     * 将第一个队列绑定到交换机,使用通配符路由键
     */
    @Bean
    public Binding bindingQueueOne() {
        return BindingBuilder.bind(queueOne())
                           .to(myExchange())
                           .with(ROUTING_KEY_PATTERN_ONE);
    }

    /**
     * 将第二个队列绑定到交换机,使用通配符路由键
     */
    @Bean
    public Binding bindingQueueTwo() {
        return BindingBuilder.bind(queueTwo())
                           .to(myExchange())
                           .with(ROUTING_KEY_PATTERN_TWO);
    }
}
    

消息消费者

以下是两个独立的消费者类,分别监听不同的队列。当消息到达各自的队列时,对应的消费者将被触发。


package com.example.mq.consumer;

import com.example.dto.EventMessage; // 假设这是您的消息体对象
import com.example.exception.BizException; // 假设这是您的自定义异常
import com.example.exception.BizCodeEnum; // 假设这是您的业务错误码
import com.example.service.MyDataProcessingService; // 假设这是您的业务服务类

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
@Slf4j
@RabbitListener(queues = RabbitMQConfig.QUEUE_ONE) // 监听第一个队列
public class MyDataProcessingListener {

    @Autowired
    private MyDataProcessingService dataProcessingService;

    @RabbitHandler
    public void processMessage(EventMessage eventMessage, Message message, com.rabbitmq.client.Channel channel) throws IOException {
        log.info("Received message for QUEUE_ONE: {}", eventMessage);
        try {
            // 假设 EventMessage 中有一个类型字段,用于区分具体处理逻辑
            eventMessage.setEventType("PROCESS_DATA");
            dataProcessingService.handleEvent(eventMessage);
            log.info("Successfully processed message from QUEUE_ONE: {}", eventMessage);
            // 手动确认消息(如果 acknowledge-mode 为 manual)
            // channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            log.error("Failed to process message from QUEUE_ONE: {}, error: {}", eventMessage, e.getMessage());
            // 业务异常处理
            if (!(e instanceof BizException)) {
                throw new BizException(BizCodeEnum.MQ_CONSUME_ERROR);
            } else {
                throw e; // 重新抛出业务异常
            }
            // 发生异常时,根据需要进行死信队列处理或重试
            // channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false); // 拒绝消息,不重新入队
        }
    }
}
    

package com.example.mq.consumer;

import com.example.dto.EventMessage; // 假设这是您的消息体对象
import com.example.exception.BizException; // 假设这是您的自定义异常
import com.example.exception.BizCodeEnum; // 假设这是您的业务错误码
import com.example.service.MyDetailsProcessingService; // 假设这是另一个业务服务类

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
@Slf4j
@RabbitListener(queues = RabbitMQConfig.QUEUE_TWO) // 监听第二个队列
public class MyDetailsProcessingListener {

    @Autowired
    private MyDetailsProcessingService detailsProcessingService;

    @RabbitHandler
    public void processDetails(EventMessage eventMessage, Message message, com.rabbitmq.client.Channel channel) throws IOException {
        log.info("Received message for QUEUE_TWO: {}", eventMessage);
        try {
            eventMessage.setEventType("PROCESS_DETAILS");
            detailsProcessingService.handleEventDetails(eventMessage);
            log.info("Successfully processed message from QUEUE_TWO: {}", eventMessage);
            // 手动确认消息 (如果 acknowledge-mode 为 manual)
            // channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            log.error("Failed to process message from QUEUE_TWO: {}, error: {}", eventMessage, e.getMessage());
            // 业务异常处理
            if (!(e instanceof BizException)) {
                throw new BizException(BizCodeEnum.MQ_CONSUME_ERROR);
            } else {
                throw e; // 重新抛出业务异常
            }
            // 发生异常时,根据需要进行死信队列处理或重试
            // channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
        }
    }
}
    

消息生产者示例

在 Controller 或 Service 层,您可以使用 RabbitTemplate 来发送消息。


package com.example.controller;

import com.example.dto.EventMessage; // 您的消息体对象
import com.example.mq.RabbitMQConfig; // 引入配置类
import com.example.util.JsonData; // 假设这是您的统一返回对象

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/v1/events")
public class EventController {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RabbitMQConfig rabbitMQConfig; // 注入配置类以获取交换机和路由键

    /**
     * 发送一个事件消息
     * @param requestData 包含事件信息的请求体
     * @return 统一返回对象
     */
    @PostMapping("send")
    public JsonData sendEvent(@RequestBody EventMessage requestData) {
        // 构建要发送的消息体
        EventMessage messageToSend = EventMessage.builder()
            // ... 设置 requestData 中的字段到 messageToSend ...
            .build();

        // 选择路由键,这里演示发送一个会匹配到 QUEUE_ONE 的路由键
        String routingKey = "data.process.raw"; // 示例路由键

        // 发送消息到 RabbitMQ
        rabbitTemplate.convertAndSend(
            RabbitMQConfig.MY_EXCHANGE,     // 交换机名称
            routingKey,                     // 路由键
            messageToSend                   // 消息体
        );

        // 返回成功响应
        return JsonData.buildSuccess("Event message sent successfully.");
    }

    /**
     * 发送另一个事件消息,可能匹配到 QUEUE_TWO
     * @param requestData 包含事件信息的请求体
     * @return 统一返回对象
     */
    @PostMapping("send-details")
    public JsonData sendDetailsEvent(@RequestBody EventMessage requestData) {
        EventMessage messageToSend = EventMessage.builder()
            // ... 设置 requestData 中的字段到 messageToSend ...
            .build();

        // 选择一个可能匹配到 QUEUE_TWO 的路由键
        String routingKey = "data.specific.details"; // 示例路由键

        rabbitTemplate.convertAndSend(RabbitMQConfig.MY_EXCHANGE, routingKey, messageToSend);

        return JsonData.buildSuccess("Details event message sent successfully.");
    }
}
    

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。