Springboot整合rabbitMQ

目录

1.Springboot整合rabbitMQ

2 如何确保消息的可靠性

 2.1 保证消息从生产者到交换机

2.2 保证消息可以从交换机到队列

2.3 如何保证消息在队列

2.4 保证消费者可靠的消费消息

3 如何限制消费者消费消息的条数(消费端限流)

4 设置队列过期时间

4.1 创建队列时为队列设置过期时间(每条信息都是相同时间)

4.2 单独为消息设置过期时间(为某一个设置过期时间)

 5 死信队列

6 延迟队列

7 如何防止消息被重复消费

8 rabbitMQ的常见面试题


1.Springboot整合rabbitMQ

1.创建springboot项目

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

2.创建两个子项目producer生产者服务    consumer消费者服务

3.生产者服务

①配置文件application.properties

server.port=7000

#rabbitMQ配置  rabbitMQ所在ip
spring.rabbitmq.host=192.168.1.88
# 都有默认值
spring.rabbitmq.port=5672
spring.rabbitmq.virtual-host=/
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

②使用工具类RabbitTemplate发送消息到队列

package com.wzh.producer.controller;

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

import java.util.HashMap;
import java.util.Map;


@RestController
public class ProducerController {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @GetMapping("saveOrder")
    public void saveOrder(){
        System.out.println("保存订单到数据库");
        Map<String,Object> map = new HashMap<>();
        map.put("orderId","110");
        map.put("price",2500);
        map.put("num",3);
        map.put("phone","15700085997");
        // 交换机  路由key
        rabbitTemplate.convertAndSend("topic_exchange","a.orange.b",map);
    }

}

③创建主启动类

package com.wzh.producer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
public class ProducerApp {
    public static void main(String[] args) {
        SpringApplication.run(ProducerApp.class,args);
    }
}

④运行并访问7000端口 

然后rabbitmq客户端就可以查看到,这里都是提前创建好的队列,交换机等。 

4.消费者服务

①配置文件application.properties

server.port=7001

#rabbitMQ配置
spring.rabbitmq.host=192.168.1.88
spring.rabbitmq.port=5672
spring.rabbitmq.virtual-host=/
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

②使用工具类RabbitTemplate发送消息到队列

package com.wzh.rabbitmq;

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.util.Map;


@Component
public class MyListener {
    //队列名
    @RabbitListener(queues = "topic_queue01")
    public void test(Map<String,Object> msg){
        System.out.println(msg);
        //进行相关的业务处理
    }

③创建主启动类

package com.wzh.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
public class ConsumerApp {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApp.class,args);
    }
}

④运行主启动类

2 如何确保消息的可靠性

首先确定消息可能在哪些位置丢失---不同的位置可以有不同的解决方案。

 2.1 保证消息从生产者到交换机

confirm确认机制

1. 手动开启确认机制(producer服务的配置文件)

        spring.rabbitmq.publisher-confirm-type=correlated
 2. 为rabbitTemplate设置确认回调函数

package com.wzh;

import com.wzh.producer.ProducerApp;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

/**
 * @ProjectName: springboot-rabbitmq
 * @Package: com.wzh
 * @ClassName: TestRabbitMQ
 * @Author: 王振华
 * @Description:
 * @Date: 2022/9/20 19:56
 * @Version: 1.0
 */
@SpringBootTest(classes=ProducerApp.class)
public class TestRabbitMQ {
    //springboot集成了rabbitMQ提供了一个工具类,该类封装了消息的发送
    @Resource
    private RabbitTemplate rabbitTemplate;

    //测试确认机制
    @Test
    public void testConfirm(){
        //为rabbitTemplate设置确认回调函数
        //ConfirmCallback函数式接口   匿名内部类
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            //不管是否到达交换机  都会触发该方法
            @Override
            public void confirm(CorrelationData correlationData, boolean b, String s) {
                if(b==false){
                    //根据自己的业务完成相应的代码
                    System.out.println("消息发送失败---订单回滚");
                }
            }
        });
        //这里用的是路由模式
        rabbitTemplate.convertAndSend("direct_exchange","info","hello springboot");
    }
}

查看消费者

package com.wzh.consumer.rabbitmq;

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

import java.util.Map;

/**
 * @ProjectName: springboot-rabbitmq
 * @Package: com.wzh.consumer.rabbitmq
 * @ClassName: Consumer
 * @Author: 王振华
 * @Description:
 * @Date: 2022/9/20 15:27
 * @Version: 1.0
 */
@Component
public class Consumer {
    @RabbitListener(queues = "router_queue01")
    public void queue01(String s){
        System.out.println(s);
    }

    @RabbitListener(queues = "router_queue02")
    public void queue02(String s){
        System.out.println(s);
    }
}

消费者的参数必须与生产者的参数类型一致

2.2 保证消息可以从交换机到队列

returning机制: 如果消息无法到达队列,则会触发returning机制。如果能从交换机到队列则不会触发returning机制。

默认rabbitMQ不开启该机制。

①开启returning机制(生产者配置文件)

         spring.rabbitmq.publisher-returns=true

②为rabbitTemplate设置returning回调函数

/**
     * 1.开启returning机制 spring.rabbitmq.publisher-returns=true
     * 2.为rabbitTemplate设置returning回调函数
     */
    @Test
    public void testReturning(){
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            //该方法只有从交换机到队列失败时才会触发
            @Override
            public void returnedMessage(ReturnedMessage returned) {
                //根据自己的业务完成相应的代码
                System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~");
            }
        });
        //这里用的是路由模式
        rabbitTemplate.convertAndSend("direct_exchange","error","hello springboot2");
    }

 ③消费者监听结果

2.3 如何保证消息在队列

  1. 队列持久化---》创建的时候设置持久化

  2. 搭建rabbitmq集群--保证高可用

2.4 保证消费者可靠的消费消息

①修改为手动确认模式

改为手动确认(消费者服务配置文件)

        spring.rabbitmq.listener.simple.acknowledge-mode=manual

②当业务处理完毕后在确认消息给队列让其删除该消息

package com.wzh.consumer.rabbitmq;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;

/**
 * @ProjectName: springboot-rabbitmq
 * @Package: com.wzh.consumer.rabbitmq
 * @ClassName: Consumer
 * @Author: 王振华
 * @Description:
 * @Date: 2022/9/20 15:27
 * @Version: 1.0
 */
@Component
public class Consumer {
    @RabbitListener(queues = "router_queue01")
    public void queue01(String s){
        System.out.println(s);
    }

    @RabbitListener(queues = "router_queue02")
    //Message message 封装了信息类, Channel channel 信道
    public void queue02(Message message, Channel channel){
        byte[] body = message.getBody();
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        System.out.println("接受到消息"+new String(body));
        try {

            System.out.println("处理业务代码");
            //这里会因为硬件问题 或其他业务代码问题  导致处理不完  出现异常了 走catch
            System.out.println("业务处理完毕");
            //设置手动确认---队列会把该信息移除。
            //long deliveryTag,消息的标记
            // boolean multiple: 是否把之前没有确认的消息以前确认掉。
            channel.basicAck(deliveryTag,true);
        }catch (Exception e){
            //1.让队列在给我发一次。
            //long deliveryTag, boolean multiple,
            // boolean requeue: 继续发给我 直接扔掉
            try {
                channel.basicNack(deliveryTag,true,true);
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }

        }


    }
}

如何保证消息的可靠性。

  1. 设置confirm和returning机制

  2. 设置队列和交互机的持久化

  3. 搭建rabbitMQ服务集群

  4. 消费者改为手动确认机制。

3 如何限制消费者消费消息的条数(消费端限流)

如果队列里有10w条数据,消费者不管能不能消化,会直接把10w条消息都接受,会导致消费者服务垮掉

  1. 设置消费者消费消息的条数

  2. 消费者端必须为手动确认模式。

① 修改每次拉取消息的条数

 ②测试

 

package com.wzh.consumer.rabbitmq;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;

/**
 * @ProjectName: springboot-rabbitmq
 * @Package: com.wzh.consumer.rabbitmq
 * @ClassName: Consumer
 * @Author: 王振华
 * @Description:
 * @Date: 2022/9/20 15:27
 * @Version: 1.0
 */
@Component
public class Consumer {
    @RabbitListener(queues = "test03")
    public void queue01(Message message, Channel channel) throws IOException {
        byte[] body = message.getBody();
        System.out.println("消息的内容:"+new String(body));
        //手动确认
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);
    }

    @RabbitListener(queues = "router_queue02")
    //Message message 封装了信息类, Channel channel 信道
    public void queue02(Message message, Channel channel){
        byte[] body = message.getBody();
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        System.out.println("接受到消息"+new String(body));
        try {

            System.out.println("处理业务代码");
            //这里会因为硬件问题 或其他业务代码问题  导致处理不完  出现异常了 走catch
            System.out.println("业务处理完毕");
            //设置手动确认---队列会把该信息移除。
            //long deliveryTag,消息的标记
            // boolean multiple: 是否把之前没有确认的消息以前确认掉。
            channel.basicAck(deliveryTag,true);
        }catch (Exception e){
            //1.让队列在给我发一次。
            //long deliveryTag, boolean multiple,
            // boolean requeue: 继续发给我 直接扔掉
            try {
                channel.basicNack(deliveryTag,true,true);
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }

        }


    }
}

4 设置队列过期时间

TTL:time to live

可以为整个队列设置也可以单独为某条信息设置

4.1 创建队列时为队列设置过期时间(每条信息都是相同时间)

创建队列 

 

创建交换机

 点击test01进行 交换机与队列绑定

 测试

//测试过期时间
    @Test
    public void test01(){
        for(int i=0;i<10;i++) {
            if(i<5){
                //前五个  同时创建  后五个 每个间隔两秒 创建   过期时间也不一样 
                rabbitTemplate.convertAndSend("test01", "aaa", "hello springboot"+i);
            }else {
                try{
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                rabbitTemplate.convertAndSend("test01", "aaa", "hello springboot" + i);
            }
        }
    }

4.2 单独为消息设置过期时间(为某一个设置过期时间)

当前消息队列为普通队列,没有在创建队列的时候设置过期时间

 @Test
    public void test02() {
        MessagePostProcessor messagePostProcessor=new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setExpiration("10000");
                return message;
            }
        };
        rabbitTemplate.convertAndSend("test01", "aaa", "Hello Springboot",messagePostProcessor);
    }

 5 死信队列

 

创建普通队列

 创建死信队列

 

 创建普通交换机

创建死信交换机 

 队列绑定交换机

 

 死信交换机与死信队列绑定

 测试

    @Test
    public void test02() {
        for (int i = 0; i < 10; i++)
            rabbitTemplate.convertAndSend("pt_exchange", "dead", "Hello Springboot-------"+i);
        }
    }

6 延迟队列

 这里的判断订单状态 是因为 如果支付系统第29分分钟去支付,支付的比较慢,最后在第31分钟支付成功了。消息30分钟加入死信队列执行库存回滚,就会出错。

 7 如何防止消息被重复消费

 

8 rabbitMQ的常见面试题

1. 如何防止消息被重复消费

2.如何保证消息的可靠性

3.rabbitMQ消息积压过多

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
天猫商城是一个基于SSM框架的综合性B2C电商平台,需求设计主要参考天猫商城的购物流程:用户从注册开始,到完成登录,浏览商品,加入购物车,进行下单,确认收货,评价等一系列操作。 作为模拟天猫商城系统的核心组成部分之一,采用SSM框架的天猫数据管理后台包含商品管理,订单管理,类别管理,用户管理和交易额统计等模块,实现了对整个商城的一站式管理和维护。本课程是一门专业的Java微服架构开发实战课程,主要讲解了当下流行的SpringBoot框架、SpringCloud架构以及与第三方技术整合开发实战内容。通过本课程的学习,能够理解并掌握SpringBoot的基础知识,同时能够掌握SpringBoot与常用的第三方技术整合实现实际开发中的业务需求,包括实现Web开发、数据访问、缓存管理、安全管理、消息服务、任务管理等;了解并掌握SpringCloud微服务架构的基础知识及相关组件的应用,掌握微服务架构在企业级开发的实践,建立起微服架构思想。项目技术栈:采用SpringBoot简化商城系统的初始搭建以及开发过程采用SpringMVC+Spring+IBatis完成项目的整合采用Mysql作为数据库存储,Druid配置数据库连接池采用SpringCloud+Netflix 微服务技术栈的实战开发使用Redis完成缓存的数据存储,搭建Redis搭建主从、哨兵、集群应用,保证Redis的高可用使用ElasticSearch全文检索系统进行商品数据搜索,使用ElasticSearch搭建搜索服务的高可用使用Ngnix实现页面动静分离与负载均衡的配置采用FastDFS文件储存系统文件存储,完成广告图片、商品图片的上传和存储系统使用采用CAS+shiro单点登录系统实现用户认证使用ECharts根据后台查询数据生成图表使用POI实现了商城盈利状况的Excel表格导出。商品的详情页使用Thymeleaf完成页面静态化,减少页面数据展示延迟项目中使用SpringBoot下的Aop + 自定义注解完成用户行为记录,日志采集后台管理系统使用Shiro实现登录验证和权限管理(超级管理员、管理员、产品编辑员)项目整合微信完成订单的支付使用Redission完成分布式锁,生成订单的编号使用SpringCloud Alibaba Seat完成下订单模块的分布式事务(新增订单表,库存减少,库存超卖设计)使用RabbitMQ 做消息队列,完成订单未支付自动取消和模块直接的解耦合使用Quartz任务调度,完成缓存的定时刷新,保证缓存的一致性使用本地消息表机制完成消息然队列RabbitMQ消息可靠性传输订单支付模块使用微信扫码支付,并设置订单超时自动取消通过Jquery实现前端校验,通过基于Hibernate的Valida注解实现后端的校验功能使用Base64编码对Json数据传输进行编码和解码项目使用RESTful设计风格实现资源的访问,实现前后端分离项目使用聚合数据第三方短信平台完成用户的登陆功能项目使用SpringBoot整合JavaMail完成邮件的发送项目使用SpringBoot整合Swagger2生成接口文档使用PostMan完成接口的测试项目的测试:SpringTest、dbunit、EasyMock使用Docker 进行应用的自动化打包和发布、自动化测试和持续集成、部署和调整其他应用使用 PowerDesigner,完成数据库的建模项目使用禅道进行BUG管理环境采用Maven实施多模块项目构建,采用Git进行项目版本管理 架构解读:  项目部分截图:              讲义部分截图:          
Spring Boot框架可以很容易地与RabbitMQ进行集成。为了实现这个目标,你需要在项目的依赖项中添加两个关键的依赖项。首先,你需要添加spring-boot-starter-amqp依赖项,它提供了与RabbitMQ进行通信的必要类和方法。其次,你还需要添加spring-boot-starter-web依赖项,以便在项目中使用Web功能。 在你的项目中创建两个Spring Boot应用程序,一个是RabbitMQ的生产者,另一个是消费者。通过这两个应用程序,你可以实现消息的发送和接收。生产者应用程序负责将消息发送到RabbitMQ的消息队列,而消费者应用程序则负责从队列中接收并处理消息。这样,你就可以实现基于RabbitMQ的消息传递系统。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [SpringBoot整合RabbitMQ](https://blog.csdn.net/K_kzj_K/article/details/106642250)[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^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Springboot 整合RabbitMq ,用心看完这一篇就够了](https://blog.csdn.net/qq_35387940/article/details/100514134)[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^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [undefined](undefined)[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^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值