一文搞定springBoot集成RabbitMq

一.什么是RabbitMq

RabbitMQ 是一个开源的消息代理(message broker)和队列服务器(queue server),它基于高级消息队列协议(AMQP)标准进行开发。RabbitMQ 最初起源于 Erlang 语言,后来用一系列插件扩展了其功能,如消息确认、持久化、发布/订阅、路由、集群和高可用性。RabbitMQ 可以作为应用程序之间的消息中间件,用于解耦应用、异步通信和流量削峰。

二.主要组成

  1. 生产者(Producer):发送消息到队列的实体。

  2. 消费者(Consumer):从队列接收消息并处理的实体。

  3. 队列(Queue):存储消息的容器。生产者发送的消息会存储在这里,等待消费者来取。

  4. 交换机(Exchange):接收生产者发送的消息,并根据路由规则将消息路由到不同的队列。RabbitMQ 中有多种交换机类型,如 Direct、Topic、Fanout 和 Headers。

  5. 绑定(Binding):将交换机和队列绑定起来,同时指定一个路由键(Routing Key)。路由键是交换机将消息路由到队列的依据。

  6. 路由键(Routing Key):用于交换机将消息路由到队列的标识符。

  7. 连接(Connection):生产者或消费者与 RabbitMQ 服务器之间的 TCP 连接。

  8. 信道(Channel):基于 TCP 连接建立的虚拟连接,用于发送和接收消息。每个 TCP 连接上都可以创建多个信道,且信道之间相互独立。

三.常见应用场景

  1. 异步处理:例如,将比较耗时而且不需要即时(同步)返回结果的操作,作为消息放入消息队列。

  2. 应用解耦:例如,订单系统可以将订单信息发送到一个名为"order_queue"的消息队列中,而库存管理系统则监听该队列,并在收到订单消息时进行库存更新。

  3. 流量削峰:例如,在秒杀或团抢等高并发场景中,使用RabbitMQ可以有效削峰填谷,避免流量直接冲击数据库等核心资源,保障系统的稳定运行。

  4. 任务调度:RabbitMQ可以配合定时任务框架(如Quartz)实现任务的调度和分发,支持任务的优先级、延迟执行等功能。

  5. 分布式事务:RabbitMQ的可靠消息传递机制可以支持分布式事务的实现,确保在分布式系统中事务的一致性和完整性。

  6. 跨系统、跨语言的异步通信:由于消息是平台无关和语言无关的,因此RabbitMQ适合作为多个应用之间的松耦合的接口。

四.关于RabbitMq的安装

这里简单介绍在虚拟机(CentOS7)用Docker拉取

1.Docker拉取RabbitMq镜像

rabbitmq:management镜像,rabbitmq:management镜像包含了 RabbitMQ 的管理插件,它提供了一个 Web UI 来监控和管理 RabbitMQ 服务器。

docker pull rabbitmq:management

这将会拉取最新的rabbitmq,也可以指定版本 例如:docker pull rabbitmq:3.8.15-management

2.启动RabbitMQ

docker run -dit \
--name rabbitmq \
-p 5672:5672 \
-p 15672:15672 \
rabbitmq:management

参数:

-p 5672:5672: 将容器的 5672 端口映射到宿主机的 5672 端口。RabbitMQ 使用这个端口来提供 AMQP 协议的消息服务。

-p 15672:15672: 将容器的 15672 端口映射到宿主机的 15672 端口。RabbitMQ 的管理插件使用这个端口来提供一个 Web UI,你可以通过这个 UI 来监控和管理 RabbitMQ 服务器。

通过docker ps 命令查询运行的容器

3.访问http://linuxip地址:15672,这里的用户名和密码默认都是guest

五.SpringBoot集成RabbitMq 

步骤一:创建交换机、队列进行绑定

登录进去我们可以新建一个交换机

然后再新建一个Queue

 

最后我们绑定RouteKey

 

步骤二:构建SpringBoot项目(略)

下面是我的springboot的demo架构

步骤三:添加依赖到pom.xml

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

步骤四:配置生产者

这是我的目录结构

在product模块的application.yaml中配置RabbitMq相关信息

server:
  port: 87
spring:
  rabbitmq:
    #虚拟机地址
    host: 192.168.73.144
    port: 5672
    username: guest
    password: guest
    virtual-host: /
    #确保消息未被队列接收返回
    publisher-returns: true
    #发布消息成功到交换机后触发回调的方法
    publisher-confirm-type: correlated

在config包下面创建MqConfig以及MqProductCallBack(MqConfig里配置Bean创建,我们可以不用在web界面去配置,为了方便我两种都写上了)

package com.org.product.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 你的名字
 * @Description:定义交换机等
 */
@Configuration
public class MqConfig {

    private  static final String  exchangeName = "mq_exchange1";
    private static final String queueName = "queue1";
    private static final String routingKey = "mq_routeKey1";

    @Bean
    public DirectExchange directExchange() {
        return new DirectExchange(exchangeName);
    }

    @Bean
    public Queue queue() {
        return new Queue(queueName, true); // 第二个参数为true表示队列持久化
    }

    @Bean
    public Binding binding(Queue queue, DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(routingKey);
    }
}
package com.org.product.config;

import cn.hutool.json.JSONUtil;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 你的名字
 * @Description:生产者消息确认
 */
@Component
public class MqProductCallBack implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnsCallback {
    /**
     * @param correlationData 对象内部只有一个id属性,用来表示当前消息的唯一性
     * @param ack             消息投递到broker的状态,true成功,false失败
     * @param cause           投递失败的原因
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (ack)
            System.out.println("消息投递收到确认,correlationData=" + correlationData.getId());
        if (!ack)
            System.out.println("消息ID="+correlationData.getId()+"投递失败,失败原因:"+cause);
    }

    @Override
    public void returnedMessage(ReturnedMessage returnedMessage) {
        System.out.println("消息返回结果:"+ JSONUtil.toJsonStr(returnedMessage));
    }
}

写一个生产者Controller类,启动product模块用PostMan进行请求

package com.org.product.controller;

import com.org.product.config.MqProductCallBack;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * Created with IntelliJ IDEA.
 * @Author: 你的名字
 */
@RestController
@RequestMapping("/product")
@Slf4j
public class PushMessageController {


    private static final String  exchangeName = "mq_exchange1";
    private static final String routingKey = "mq_routeKey1";
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private MqProductCallBack mqProductCallBack;


    @GetMapping("/pushMessage")
    public String pushMessage() {
        log.info("-------------消息推送开始--------------");
        //创建CorrelationData对象,包含唯一id,id的作用是在回调函数中识别消息,也就是根据id跟踪这条消息
        CorrelationData correlationData = new CorrelationData("id_" + System.currentTimeMillis());
        //消息确认与返回
        rabbitTemplate.setConfirmCallback(mqProductCallBack);
        rabbitTemplate.setReturnsCallback(mqProductCallBack);
        //消息发送
        //hello_mq1 消息的路由键
        rabbitTemplate.convertAndSend(exchangeName,routingKey, "乾坤未定,你我皆是牛马!",
                //Lambda表达式,实现MessagePostProcessor接口
                message -> {
                    //获取消息的属性,设置传输模式DeliveryMode为持久化,会写入磁盘
                    message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
                    //返回修改后的消息
                    return message;
                }, correlationData);
        log.info("--------------消息推送结束------------------");
        return "消息发送成功了!!!";
    }
}

控制台输出

我们到RabbitMq管理页面查看

既然生产者消息发送成功,接下来我们配置消费者,把消息消费下来

步骤五:配置消费者

我的目录结构

 

在application.yaml中配置rabbitmq 

server:
  port: 86

spring:
  rabbitmq:
    host: 192.168.73.144
    port: 5672
    username: guest
    password: guest
    virtual-host: /

#自动ack
    listener:
      simple:
        acknowledge-mode: auto
        retry:
          enabled: true #开启消费者失败重试
          initial-interval: 2000 #初始的失败等待时长为2秒
          multiplier: 2 #失败的等待时长倍数,下次等待时长= multiplier * last-interval
          max-attempts: 3 #最大重试次数
          stateless: true #true为无状态 false有状态 ,如果业务中包含事务,这里改为false

#手动ack
#    listener:
#      simple:
#        acknowledge-mode: manual

#acknowledge-mode: none 则是关闭ack

配置消费者有多种方式,比如使用@RabbitListener注解(本文用注解)

使用SimpleMessageListenerContainer,使用RabbitTemplate进行手动监听等

我们在listener下创建MessageListener

package com.org.consumer.listener;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 你的名字
 * @Description:监听消息
 */
@Component
public class MessageListener {

    //默认情况下,当使用@RabbitListener注解时,消息确认模式通常是自动的(AcknowledgeMode.AUTO)可以在yaml文件中更改,
    // 消息一旦被消费者接收并处理完成(即方法执行完成),就会自动发送ack确认给RabbitMQ。
    @RabbitListener(queues ="queue1")
    public void handleMessage(String message) {
        //处理接收到的消息
        System.out.println("接收到的消息是:" + message);
    }


    //手动ack
//    @RabbitListener(queues = "queue2")
//    public void handleMessage1(String message,Channel channel, @Header(AmqpHeaders.DELIVERY_TAG)Long tag) throws IOException {
//        System.out.println("接收到的消息是:" + message);
//        try {
//            Thread.sleep(2000);
//            //发生异常
//            int i = 1/0;
//            //手动ack
//            channel.basicAck(tag,false);
//        } catch (Exception e) {
//            //手动ack,让消息重回队列,参数三表示是否重回队列
//         channel.basicNack(tag,false,false);
//
//        }
//
//    }
}

启动consumer进行消息消费

代码中注释掉的是消费者进行手动ack确认,可以按照自己的业务逻辑进行手动ack

至此,springboot简单集成rabbitMq完成 ,欢迎大佬指正!!!!

  • 28
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot集成RabbitMQ可以通过以下步骤实现。首先,在配置文件中添加RabbitMQ的连接信息。例如,在application.yml文件中配置RabbitMQ的主机、端口、用户名和密码等信息。\[1\]然后,引入SpringBoot整合RabbitMQ的依赖,包括spring-boot-starter-amqp和spring-rabbit-test等依赖项。\[2\]接下来,可以编写代码来实现与RabbitMQ的交互,例如发送和接收消息等操作。通过使用RabbitTemplate和@RabbitListener等注解,可以方便地实现消息的发送和接收。最后,可以通过运行SpringBoot应用程序来测试RabbitMQ集成是否成功。 #### 引用[.reference_title] - *1* [SpringBoot 集成RabbitMQ](https://blog.csdn.net/July_whj/article/details/120634833)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Springboot整合RabbitMQ](https://blog.csdn.net/weixin_49076273/article/details/124991012)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [SpringBoot教程(十五) | SpringBoot集成RabbitMq](https://blog.csdn.net/lsqingfeng/article/details/123652520)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值