SpringBoot(三十九)SpringBoot集成RabbitMQ实现流量削峰添谷

前边我们有具体的学习过RabbitMQ的安装和基本使用的情况。

但是呢,没有演示具体应用到项目中的实例。

这里使用RabbitMQ来实现流量的削峰添谷。

一:添加pom依赖

<!--rabbitmq-需要的 AMQP 依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

二:yml配置

spring:
#配置rabbitmq 服务器
rabbitmq:virtual-host: /host: 1.15.157.156port: 5672username: xxxxxpassword: xxxxx# 开启发布确认机制#SIMPLE,     // 使用 RabbitTemplate#waitForConfirms() 或 waitForConfirmsOrDie()#CORRELATED, // 使用 CorrelationData 关联确认与发送的消息#NONE        // 不启用发布确认publisher-confirm-type: correlated# publisher-confirms 消息的可靠投递, confirm 确认模式 默认为false#publisher-confirms: true# 添加发布确认返回, return 回退模式 默认为falsepublisher-returns: true### listenerlistener:# 每次从队列中预取5条消息prefetch: 20# 最小消费者数量concurrency: 1# 最大的消费者数量max-concurrency: 10simple:# 设置预取数量为1  每次取一个prefetch: 1# manual:手动 ack,需要在业务代码结束后,调用 api 发送 ack,虽灵活但会提高编码复杂度。# auto:自动 ack,没有异常则返回 ack;抛出异常则返回 nack,消息重新入队,一直到没有异常为止,也可以设置最大重试次数,超过次数后发送到专门收集错误消息的队列进一步处理# none:关闭ack,MQ 假定消费者获取消息后会成功处理,因此消息投递后立即被删除(消息投递是不可靠的,可能丢失)acknowledge-mode: manual# 失败重试retry:# 开启消费者失败重试enabled: true# 初始的失败等待时长为1秒initial-interval: 1000# 失败的等待时长倍数,下次等待时长 = multiplier * last-intervalmultiplier: 3# 最大重试次数max-attempts: 4# true无状态;false有状态。如果业务中包含事务,这里改为falsestateless: true

具体的配置都有对应的注释,参照即可。

三:编写config配置类

package com.modules.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;@Configuration
public class RabbitMQConfig
{@Value("${spring.rabbitmq.host}")private String host;@Value("${spring.rabbitmq.port}")private int port;@Value("${spring.rabbitmq.username}")private String userName;@Value("${spring.rabbitmq.password}")private String password;@Value("${spring.rabbitmq.listener.prefetch}")private int prefetch;@Value("${spring.rabbitmq.listener.concurrency}")private int concurrentConsumers;@Value("${spring.rabbitmq.listener.max-concurrency}")private int maxConcurrentConsumers;/*** 链接RabbitMQ* @return*/@Beanpublic ConnectionFactory connectionDirectFactory(){CachingConnectionFactory connectionFactory = new CachingConnectionFactory();connectionFactory.setHost(host);connectionFactory.setPort(port);connectionFactory.setUsername(userName);connectionFactory.setPassword(password);connectionFactory.setPublisherConfirms(true); //必须要设置return connectionFactory;}/*** 配置RabbitMQ参数* @return*/@Beanpublic SimpleRabbitListenerContainerFactory rabbitDirectListenerContainerFactory(){SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();factory.setConnectionFactory(connectionDirectFactory());//设置最小并发的消费者数量factory.setConcurrentConsumers(concurrentConsumers);//设置最大并发的消费者数量factory.setMaxConcurrentConsumers(maxConcurrentConsumers);//限流,单位时间内消费多少条记录factory.setPrefetchCount(prefetch);// json转消息//factory.setMessageConverter(new Jackson2JsonMessageConverter());//设置rabbit 确认消息的模式,默认是自动确认//factory.setAcknowledgeMode(AcknowledgeMode.AUTO);//设置rabbit 确认消息的模式,默认是自动确认factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);return factory;}/*** 回调函数* @param connectionFactory* @return*/@Beanpublic RabbitTemplate createDirectRabbitTemplate(ConnectionFactory connectionFactory){RabbitTemplate rabbitTemplate = new RabbitTemplate();rabbitTemplate.setConnectionFactory(connectionFactory);//设置开启Manatory,才能触发回调函数,无论消息推送结果怎么样都会强制调用回调函数rabbitTemplate.setMandatory(true);// 设置确认发送到交换机的回调函数 =》 消息推送到server,但是在server里找不到交换机 / 消息推送到sever,交换机和队列啥都没找到 / 消息推送到server,找到交换机了,但是没找到队列 / 消息推送成功rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {if(ack){System.out.println("发送者消息确认成功!");}else{System.out.println("发送者消息确认是呗,考虑重发:"+cause);}//System.out.println("相关数据:"+correlationData);//System.out.println("确认情况:"+ack);//System.out.println("原因:"+cause);//System.out.println("===============================");});//设置确认消息已发送到队列的回调  =》 消息推送到server,找到交换机了,但是没找到队列 触发这个回调函数rabbitTemplate.setReturnsCallback(returnedMessage -> {System.out.println("交换机为:"+returnedMessage.getExchange());System.out.println("返回消息为:"+returnedMessage.getMessage());System.out.println("路由键为:"+returnedMessage.getRoutingKey());System.out.println("回应消息为:"+returnedMessage.getReplyText());System.out.println("回应代码为:"+returnedMessage.getReplyCode());System.out.println("===============================");});return rabbitTemplate;}@BeanQueue trafficSpikedQueue(){return new Queue("trafficSpikedQueue", true);}@BeanDirectExchange trafficSpikedExchange(){return new DirectExchange("trafficSpikedExchange");}@BeanBinding binding(Queue trafficSpikedQueue, DirectExchange trafficSpikedExchange){return BindingBuilder.bind(trafficSpikedQueue).to(trafficSpikedExchange).with("trafficSpikedKey");}//*/
}

四:创建生产者

package com.modules.controller.rabbitmq;import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
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.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class TrafficController {@Autowiredprivate RabbitTemplate rabbitTemplate;@GetMapping("/java/traffic")public String sendTrafficMessage(@RequestParam String message){for (int i = 1; i <= 100; i++){// 使用java多线程来模拟多用户并发请求final int temp = i;new Thread(()->{// 给RabbitMQ发送消息rabbitTemplate.convertAndSend("trafficExchange","trafficKey","hello world:"+temp,new MessagePostProcessor() {@Overridepublic Message postProcessMessage(Message message) throws AmqpException{// System.out.println("发送回调:"+temp);System.out.println(message);return message;}});}).start();}// rabbitTemplate.convertAndSend("trafficSpikedExchange", "trafficSpikedKey", message);return "Message sent";}
}

五:创建消费者

package com.modules.controller.rabbitmq;import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import org.springframework.amqp.core.Message;
import com.rabbitmq.client.*;
import java.io.IOException;@Component
public class TrafficSpikedConsumer {@RabbitListener(queues = "trafficQueue")public void receiveMessage(Message message, Channel channel) throws InterruptedException, IOException{// 为了演示一个一个消费的情况,这里使用线程暂停来延迟控制台输出Thread.sleep(100);// =========================================// 处理消息,例如写入数据库或进行计算System.out.println("Received message: " + new String(message.getBody()));//System.out.println("channel: " + channel);// =========================================// 成功处理后手动确认消息long deliveryTag = message.getMessageProperties().getDeliveryTag();//System.out.println("deliveryTag:"+deliveryTag);channel.basicAck(deliveryTag, false);}
}

控制台输出的数据比较多。我这里就不做展示了。

PS:我这里测试的时候遇到一个小问题,发现消费者最后消费的数量跟生产者生产的数量对不上。我百思不得其解。这问题出在哪里呢?

后来,我才发现,我测试是在本地做的测试,对应的代码,我服务器端打包的jar里边也有一份,也就是说,我一个生产者,对应两个消费者(本地+服务器)这也是我本地消费者消费的数量跟生产数量不一致的原因。

以上大概就是Springboot集成RabbitMQ实现流量削峰添谷的一个小例子。

通过RabbitMQ的队列机制,可以有效地缓解高峰期的流量压力。

有好的建议,请在下方输入你的评论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/60826.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

异步编程在ArkTS中具体怎么实现?

大家好&#xff0c;我是 V 哥&#xff0c;很好奇&#xff0c;在ArkTS中实现异步编程是怎样的&#xff0c;今天的内容来聊聊这个问题&#xff0c;总结了一些学习笔记&#xff0c;分享给大家&#xff0c;在 ArkTS中实现异步编程主要可以通过以下几种方式&#xff1a; 1. 使用asy…

Pytorch使用手册-Build the Neural Network(专题五)

在 PyTorch 中如何构建一个用于 FashionMNIST 数据集分类的神经网络模型,并解析了 PyTorch 的核心模块 torch.nn 的使用方法。以下是具体内容的讲解: 构建神经网络 在 PyTorch 中,神经网络的核心在于 torch.nn 模块,它提供了构建神经网络所需的所有工具。关键点如下: nn.…

【linux】服务器加装硬盘后如何将其设置为独立硬盘使用

【linux】服务器加装硬盘后如何将其设置为独立硬盘使用 问题描述&#xff1a;本服务器原本使用了两个硬盘作为存储硬盘&#xff0c;同时对这两个硬盘设置了raid1阵列。现在内存不足要进行加载硬盘&#xff0c;新加载的硬盘不设置为raid1&#xff0c;而是将新加装的两个硬盘作为…

亚信安全与飞书达成深度合作

近日&#xff0c;亚信安全联合飞书举办的“走近先进”系列活动正式走进亚信。活动以“安全护航信息化 共筑数字未来路”为主题&#xff0c;吸引了众多数字化转型前沿企业的近百位领导参会。作为“走近先进”系列的第二场活动&#xff0c;本场活动更加深入挖掘了数字化转型的基础…

TMS FNC UI Pack 5.4.0 for Delphi 12

TMS FNC UI Pack是适用于 Delphi 和 C Builder 的多功能 UI 控件的综合集合&#xff0c;提供跨 VCL、FMX、LCL 和 TMS WEB Core 等平台的强大功能。这个统一的组件集包括基本工具&#xff0c;如网格、规划器、树视图、功能区和丰富的编辑器&#xff0c;确保兼容性和简化的开发。…

Transformer详解及衍生模型GPT|T5|LLaMa

简介 Transformer 是一种革命性的神经网络架构&#xff0c;首次出现在2017年的论文《Attention Is All You Need》中&#xff0c;由Google的研究团队提出。与传统的RNN和LSTM模型不同&#xff0c;Transformer完全依赖于自注意力&#xff08;Self-Attention&#xff09;机制来捕…

11超全局变量php

超级全局变量是指在php任意脚本下都可以使用 PHP 超级全局变量列表: $GLOBALS&#xff1a;是PHP的一个超级全局变量组&#xff0c;在一个PHP脚本的全部作用域中都可以访问。 $_SERVER&#xff1a;$_SERVER 是一个PHP内置的超级全局变量,它是一个包含了诸如头信息(header)、路…

Git(一)基本使用

目录 一、使用git -v 查看安装git版本 二、使用mkdir 创建一个文件&#xff0c;并使用 git init 在该目录下创建一个本地仓库&#xff0c; 三、通过git clone命令接入线上仓库 四、使用git status查看仓库状态信息 五、利用echo写入一个文件 并使用cat进行查看 【Linux】e…

vue3 uniapp 扫普通链接或二维码打开小程序并获取携带参数

vue3 uniapp 扫普通链接或二维码打开小程序并获取携带参数 微信公众平台添加配置 微信公众平台 > 开发管理 > 开发设置 > 扫普通链接二维码打开小程序 配置链接规则需要下载校验文档给后端存入服务器中&#xff0c;保存配置的时候会校验一次&#xff0c;确定当前的配…

Vercel 设置自动部署 GitHub 项目

Vercel 设置自动部署 GitHub 项目 问题背景 最近 Vercel 调整了其部署政策&#xff0c;免费版用户无法继续使用自动部署功能&#xff0c;除非升级到 Pro 计划。但是&#xff0c;我们可以通过配置 Deploy Hooks 来实现同样的自动部署效果。 解决方案 通过设置 Vercel 的 Dep…

商业物联网:拥抱生产力的未来

在现代商业格局中&#xff0c;数据占据至高无上的地位。物联网&#xff08;IoT&#xff09;站在这场数字革命的前沿&#xff0c;将以往模糊不清的不确定因素转变为可衡量、可付诸行动的深刻见解。物联网技术为日常物品配备传感器与连接功能&#xff0c;使其能够实时收集并传输数…

金融租赁系统助力企业升级与风险管理的新篇章

内容概要 在当今的商业环境中&#xff0c;“金融租赁系统”可谓是企业成功的秘密武器。简单来说&#xff0c;这个系统就像一位聪明的财务顾问&#xff0c;帮助企业在资金和资源的运用上达到最优化。从设备采购到项目融资&#xff0c;它提供了一种灵活的方式&#xff0c;让企业…

梧桐数据库的高效索引技术研究及实现

1.基于LSM算法的高效索引研究 基于LSM&#xff08;Log-Structured Merge-Tree&#xff09;算法的高效索引研究主要是针对如何提高LSM算法在处理大规模数据时的查询效率而展开的。以下是几个可能的研究方向&#xff1a; &#xff08;1&#xff09;索引数据结构优化&#xff1a;…

java版CRM客户关系管理系统crm管理系统+客户+营销管理CRM平台

项目名称&#xff1a;CRM客户关系管理系统 功能模块及描述&#xff1a; 一、待办事项 今日需联系客户&#xff1a;显示当日需跟进的客户列表&#xff0c;支持查询和筛选。 分配给我的线索&#xff1a;管理分配给用户的线索&#xff0c;包括线索列表和查询功能。 分配给我的客…

Amazon商品详情API接口:电商创新与用户体验的驱动力

在电子商务蓬勃发展的今天&#xff0c;作为全球最大的电商平台之一&#xff0c;亚马逊&#xff08;Amazon&#xff09;凭借其强大的技术实力和丰富的商品资源&#xff0c;为全球用户提供了优质的购物体验。其中&#xff0c;Amazon商品详情API接口在电商创新与用户体验提升方面扮…

JVM-类文件结构

类文件结构 JVM 的“无关性” 谈论 JVM 的无关性&#xff0c;主要有以下两个&#xff1a; 平台无关性&#xff1a;任何操作系统都能运行 Java 代码 语言无关性&#xff1a; JVM 能运行除 Java 以外的其他代码 Java 源代码首先需要使用 Javac 编译器编译成 .class 文件&#xff…

pdf文档动态插入文字水印,45度角,旋转倾斜,位于文档中央,多行水印可插入中文

一行水印 /*** param inputFile 你的PDF文件地址* param outputFile 添加水印后生成PDF存放的地址* param waterMarkName 你的水印* return*/public static boolean waterMark(String inputFile,String outputFile, String waterMarkName){try {PdfReader reader new PdfRead…

【K8S问题系列 |18 】如何解决 imagePullSecrets配置正确,但docker pull仍然失败问题

如果 imagePullSecrets 配置正确&#xff0c;但在执行 docker pull 命令时仍然失败&#xff0c;可能存在以下几种原因。以下是详细的排查步骤和解决方案。 1. 检查 Docker 登录凭证 确保你使用的是与 imagePullSecrets 中相同的凭证进行 Docker 登录&#xff1a; 1.1 直接登录…

基于FPGA的2FSK调制-串口收发-带tb仿真文件-实际上板验证成功

基于FPGA的2FSK调制 前言一、2FSK储备知识二、代码分析1.模块分析2.波形分析 总结 前言 设计实现连续相位 2FSK 调制器&#xff0c;2FSK 的两个频率为:fI15KHz&#xff0c;f23KHz&#xff0c;波特率为 1500 bps,比特0映射为f 载波&#xff0c;比特1映射为 载波。 1&#xff09…

Android 应用测试的各种环境问题记录(Instrumentation测试)

报错记录 failed to configure packages targetSdkVersion&#xff08;未解决&#xff09; failed to configure com.demo.test.SettingsActivityTest.testOnCreate_withNullSavedInstanceState: Package targetSdkVersion34 > maxSdkVersion32 java.lang.IllegalArgumentE…