文件下载时利用redis的队列模式顺序下载文件,防止多文件任务下载导致OOM
1、controller层控制
@Resourceprivate RedissonClient redissonClient;@Slf4j
@Service
public class CustomerSettlementExportServiceImpl implements ICustomerSettlementExportService {
/*** 文件加入队列顺序导出** @param pubFileExportList 参数* @return 结果*/public AjaxResult pubFileExport(List<PubFileExport> pubFileExportList) {if (CollectionUtils.isEmpty(pubFileExportList)) {return AjaxResult.error("客户信息不能为空!");}RQueue<String> queue = redissonClient.getQueue("downloadQueue:file:export");for (PubFileExport pubFileExport : pubFileExportList) {try {queue.add(JSONObject.toJSONString(pubFileExport));} catch (Exception e) {log.error("加入队列失败=", e);return AjaxResult.error("添加导出任务到队列失败!");}}return AjaxResult.success();}
}
以下代码是通过定时任务拉取队列进行文件下载
@Slf4j
@Service
public class FileDownloadServiceImpl implements IFileDownloadService {@Resourceprivate ICustomerSettlementExportService customerSettlementExportService;@Resourceprivate IPubFileExportService pubFileExportService;@Resourceprivate RedisTemplate<String, String> redisTemplate;@Resourceprivate RedissonClient redissonClient;@Scheduled(fixedRate = 10000)public void processDownloadsInit() {// 提前过滤掉特定 IP 地址if (isLocalIp()) {return;}RLock lock = null;try {lock = redissonClient.getLock(BmsConstants.QUEUE_KEY_LOCK);boolean isOrderLock = lock.tryLock(10, TimeUnit.SECONDS);if (!isOrderLock) {// 当前任务未执行完,不能获取锁log.error("未能获取分布式锁,当前任务未执行完或有其他实例正在执行");return;}// 阻塞获取队列中的任务String exportTask = redisTemplate.opsForList().rightPop(BmsConstants.QUEUE_KEY, 10, TimeUnit.SECONDS);if (exportTask != null) {log.info("队列文件下载开始=" + DateUtils.getTime());handleDownload(exportTask);log.info("队列文件下载结束=" + DateUtils.getTime());}} catch (Exception e) {log.error("队列文件下载异常=", e);} finally {safeUnlock(lock);}}/*** 执行队列文件下载** @param exportTask 导出参数*/private void handleDownload(String exportTask) {try {PubFileExport pubFileExport = JSONObject.parseObject(exportTask, PubFileExport.class);// 实际的文件下载逻辑if (pubFileExport.getExportStartTime() == null|| pubFileExport.getExportEndTime() == null|| StringUtils.isBlank(pubFileExport.getClientCode())) {log.error("客户数据文件下载的参数为空请检查!");return;}AjaxResult ajaxResult = customerSettlementExportService.exportSheets(pubFileExport);pubFileExportService.updateExportAllExcel(ajaxResult, pubFileExport.getGid(), pubFileExport.getFinalUrl());} catch (Exception e) {log.error("执行队列文件下载异常=", e);}}/*** 检查是否为本地 IP 地址** @return 是否为本地 IP 地址*/private boolean isLocalIp() {try {InetAddress localAddress = InetAddress.getLocalHost();String ip = localAddress.getHostAddress();return ip.startsWith("192.168");} catch (Exception e) {log.error("获取本地 IP 地址异常=", e);return false;}}/*** 安全释放锁** @param lock 锁对象*/private void safeUnlock(RLock lock) {if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {try {lock.unlock();} catch (Exception e) {log.error("释放锁异常=", e);}}}}
3、解析下代码
这段代码实现了文件下载任务的队列管理和处理。
主要功能包括:
任务入队:将多个文件导出任务加入Redis队列。
定时任务处理:每隔10秒从队列中取出任务并执行文件下载。
分布式锁控制:确保同一时间只有一个实例处理任务,避免重复执行。
本地IP过滤:防止本地IP地址触发任务。
控制流图(CFG)
flowchart TD
A[开始] --> B{是否为本地IP}
B -->|是| E[结束]
B -->|否| C[获取分布式锁]
C --> D{是否获取成功}
D -->|否| F[记录日志并结束]
D -->|是| G[从队列取任务]
G --> H{是否有任务}
H -->|否| I[释放锁并结束]
H -->|是| J[处理下载任务]
J --> K[记录开始时间]
K --> L[调用下载逻辑]
L --> M[记录结束时间]
M --> N[释放锁并结束]
详细说明
任务入队 (pubFileExport 方法):
检查任务列表是否为空。
将每个任务序列化后加入Redis队列。
定时任务处理 (processDownloadsInit 方法):
检查是否为本地IP地址,如果是则直接返回。
尝试获取分布式锁,如果失败则记录日志并返回。
从Redis队列中取出任务,如果有任务则调用处理方法。
记录任务开始和结束时间,并释放锁。
处理下载任务 (handleDownload 方法):
反序列化任务参数。
检查参数是否完整,如果不完整则记录错误并返回。
调用客户结算导出服务进行文件下载,并更新导出状态。
辅助方法:
isLocalIp:检查当前IP是否为本地IP。
safeUnlock:安全释放分布式锁。
相关文章:
文件下载时利用redis的队列模式顺序下载文件,防止多文件任务下载导致OOM
1、controller层控制 Resourceprivate RedissonClient redissonClient;Slf4j Service public class CustomerSettlementExportServiceImpl implements ICustomerSettlementExportService { /*** 文件加入队列顺序导出** param pubFileExportList 参数* return 结果*/public Aja…...
第13章:Python TDD完善货币加法运算(二)
写在前面 这本书是我们老板推荐过的,我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后,我突然思考,对于测试开发工程师来说,什么才更有价值呢?如何让 AI 工具更好地辅助自己写代码,或许…...
两份PDF文档,如何比对差异,快速定位不同之处?
PDF文档比对是通过专门的工具或软件,自动检测两个PDF文件之间的差异,并以可视化的方式展示出来。这些差异可能包括文本内容的修改、图像的变化、表格数据的调整、格式的改变等。比对工具通常会标记出新增、删除或修改的部分,帮助用户快速定位…...
ESP-Skainet语音唤醒技术,设备高效语音识别方案,个性化交互应用
在当今数字化、智能化飞速发展的时代,物联网(IoT)与人工智能(AI)的深度融合正在重塑我们的生活和工作方式。 在智能家居的生态系统中,语音唤醒技术不仅能够为用户提供个性化的服务,还能通过定制…...
地图:nuxt3高德地图简单使用 / nuxt2 + amap
一、官方网站 JS API 安全密钥使用-基础-进阶教程-地图 JS API 2.0 | 高德地图API 二、使用 2.1、创建应用 2.2、添加key,得到key值 2.3、nuxt3项目 引入amap 2.4、pages/map.vue <template><div class"container"><div id"map-co…...
走进DevOps:让开发与运维齐头并进
引言:开发与运维的“世纪和解” 还记得那些年,开发人员总是埋头写代码,然后甩手交给运维去部署,仿佛是把热山芋扔给别人。而运维呢,总是默默承受着系统崩溃、服务停机的风险,直到某一天他们终于忍不住咆哮&…...
力扣动态规划-5【算法学习day.99】
前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向(例如想要掌握基础用法,该刷哪些题?建议灵神的题单和代码随想录)和记录自己的学习过程,我的解析也不会做的非常详细,只会提供思路和一些关…...
LLM(3) : 浏览器录制16K的音频并上传到后端
可被阿里云[qwen-audio-asr]大模型识别 HTML <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>录音并上传</title></head><body><button id"recordButton">开始/停…...
PyTorch使用教程(13)-一文搞定模型的可视化和训练过程监控
一、简介 在现代深度学习的研究和开发中,模型的可视化和监控是不可或缺的一部分。PyTorch,作为一个流行的深度学习框架,通过其丰富的生态系统提供了多种工具来满足这一需求。其中,torch.utils.tensorboard 是一个强大的接口&…...
服务器日志自动上传到阿里云OSS备份
背景 公司服务器磁盘空间有限,只能存近15天日志,但是有时需要查看几个月前的日志,需要将服务器日志定时备份到某个地方,需要查询的时候有地方可查。 针对这个问题,想到3个解决方法: 1、买一个配置比较低…...
树莓派学习
飞书:https://hi06pny1nlj.feishu.cn/docx/GYsMdth7ooNlbJx8zBDcdbcPnec?fromfrom_copylink csdn:https://blog.csdn.net/qq_41685627/article/details/145250576 基础工作 安装和部署 1.1 树莓派三种连接电脑的方式 https://blog.csdn.net/weixin…...
NestJS中实现注入多个实现了同一个接口的Service
在NestJS中有一种场景,在注入的时候需要将多个实现了同一个接口的service都注入到系统里,而NestJS中默认时没有这种注入,此时我们可以使用一个变通的provider来实现这一功能。 看下面例子,假定我们有一个OSService接口࿰…...
Qt按钮美化教程
前言 Qt按钮美化主要有三种方式:QSS、属性和自绘 QSS 字体大小 font-size: 18px;文字颜色 color: white;背景颜色 background-color: rgb(10,88,163); 按钮边框 border: 2px solid rgb(114,188,51);文字对齐 text-align: left;左侧内边距 padding-left: 10…...
基于单片机的多功能蓝牙语音智能台灯(论文+源码)
1总体方案设计 通过需求分析,本设计多功能蓝牙语音智能台灯的系统框图如图2.1所示,系统架构包括主控制器STM32F103单片机、HC-06蓝牙通信模块、LU-ASR01语音识别模块、OLED液晶、LED灯、按键等器件,在使用时用户可以通过手机APP、语音识别、…...
第15章:Python TDD应对货币类开发变化(二)
写在前面 这本书是我们老板推荐过的,我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后,我突然思考,对于测试开发工程师来说,什么才更有价值呢?如何让 AI 工具更好地辅助自己写代码,或许…...
算法随笔_13: 有效三角形的个数
上一篇:算法随笔_12:最短无序子数组-CSDN博客 题目描述如下: 给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。 示例 1: 输入: nums [2,2,3,4] 输出: 3 解释:有效的组合是: 2,3,4 (使用第一个 2) 2,3,4 (使用第二个 2) 2,2,3 算法…...
WSL 2 自动更新 虚拟 IP 到 window hosts
window下的wsl2 开发中使用到 域名映射,但是WSL2 每次启动都会被分配一个虚拟的 ip 地址,每次启动虚拟ip 都不一样,导致要频繁 更改 window 的 hosts 文件,太麻烦了,所以写一个自动执行的 .sh 脚本,每次启动…...
我在广州学Mysql 系列——触发器的使用
ℹ️大家好,我是练小杰,这周是春节前的最后一周了,现在一双手数都能数得过来了!! 本播客将学习MYSQL中触发器的相关概念以及基础命令~~ 回顾:👉【MYSQL视图相关例题】 数据库专栏👉【…...
【useCallback Hook】在多次渲染中缓存组件中的函数,避免重复创建函数
文章目录 什么是 useCallback?基本语法 为什么需要 useCallback?示例1. 避免子组件重复创建函数2. 作为 useEffect 的依赖项 注意事项总结 在 React 开发中,性能优化是一个重要的主题。随着应用规模的增长,组件的重新渲染可能会变…...
2025/1/20 学习Vue的第三天
玩性太大了玩得也不开心,天天看电视刷视频。 内心实在空洞。 最近天天看小红书上的外国人,结实外国友人(狗头)哈哈哈认识了不少人,有埃及的有美国的,还有天天看菲利普吃糖葫芦哈哈哈哈哈一个阳光的德国大男…...
YOLOv12官版镜像实战:手把手教你验证COCO数据集,小白也能轻松上手
YOLOv12官版镜像实战:手把手教你验证COCO数据集,小白也能轻松上手 1. 环境准备与快速部署 1.1 镜像环境概览 YOLOv12官版镜像已经预装了所有必要的运行环境,开箱即用。主要配置包括: Python 3.11环境PyTorch 2.5深度学习框架C…...
【AutoSAR】详解PDUR模块
所谓梦想,就是让你感到痛苦的事情不再发生。一、前言在学习AUTOSAR通信栈时,我们会遇到多种PDU相关的缩写,如L-PDU、N-PDU、I-PDU等。理解这些缩写及其相互关系、以及它们与OSI七层模型的对应关系,对于掌握通信部分至关重要。接下…...
OpenClaw学术研究流:Phi-3-mini-128k-instruct自动生成论文综述
OpenClaw学术研究流:Phi-3-mini-128k-instruct自动生成论文综述 1. 为什么需要自动化文献综述 每次开始新的研究课题时,最让我头疼的就是文献综述环节。作为独立研究者,我常常需要花费数周时间阅读上百篇论文,手动整理关键观点和…...
使用Dify对接自己开发的mcp
先要有自己开发的mcp,然后部署到服务器 如何开发自己的mcp:Java使用spring Ai集成的mcp开发自己的mcp-CSDN博客 使用Dify对接mcp服务 Dify如何接入MCP工具_dify如何使用mcp工具-CSDN博客 基本上都差不多, 只说一点:如果一直报…...
如何快速搭建个人数字图书馆:Talebook私有书库终极指南
如何快速搭建个人数字图书馆:Talebook私有书库终极指南 【免费下载链接】talebook 一个简单好用的个人书库 项目地址: https://gitcode.com/gh_mirrors/ta/talebook 想要拥有一个属于自己的数字图书馆吗?Talebook是一个基于Calibre的简单好用的个…...
千问3.5-27B流式响应:OpenClaw实现长任务实时进度反馈
千问3.5-27B流式响应:OpenClaw实现长任务实时进度反馈 1. 为什么需要流式响应 上周我尝试用OpenClaw对接千问3.5-27B模型处理一份200页的PDF文档转换任务,结果遇到了一个尴尬场景——在飞书机器人对话窗口输入指令后,整整15分钟没有任何反馈…...
LeetCode 3655. 区间乘法查询后的异或2 解题报告(Python)
LeetCode 3655. 区间乘法查询后的异或2 解题报告(Python) 前言 本题是 LeetCode 第 3655 号问题,属于一道结合了根号分治、差分思想与模运算的综合应用题。题目要求在一个数组上执行大量区间“跳跃式”乘法操作,并最终返回所有元素…...
【51 单片机入门到进阶】08 入门:51单片机定时器0/1使用详解
1,定时器中断核心基础总览 定时器中断:定时器计数溢出时,硬件自动触发中断,CPU 暂停主程序执行中断服务函数,是单片机定时控制、延时、周期任务的核心方式。中断名称中断号入口地址核心控制寄存器中断标志定时器 0 中断…...
AI时代的算法思维:大经典排序学习驯
引言 在现代软件开发中,性能始终是衡量应用质量的重要指标之一。无论是企业级应用、云服务还是桌面程序,性能优化都能显著提升用户体验、降低基础设施成本并增强系统的可扩展性。对于使用 C# 开发的应用程序而言,性能优化涉及多个层面&#x…...
ESP32/8266利用闪存文件系统创建 Web服务实现交互控制
ESP32/8266利用SPIFFS(闪存文件系统)创建 Web服务实现交互控制 ✨从ESP8266 Arduino Core 2.7.0版本开始被官方标记为“已弃用”,并推荐使用LittleFS作为替代方案。 在本教程中,将展示如何构建一个web服务,以提供存储在ESP32/8266文件系统中的HTML和CSS文件,创建的HTML和CS…...
