微服务超大Excel文件导出方案优化
1、在导出Excel时经常会碰到文件过大,导出特别慢
2、微服务限制了请求超时时间,文件过大情况必然超时
优化思路:
1、文件过大时通过文件拆分、打包压缩zip,然后上传到oss,并设置有效期(30天过期)
2、把同步下载改成异步
3、文件生成完成,更新任务状态
4、通过oss的下载链接下载文件
5、多模块复用,只需要实现各自查询Excel业务数据的接口即可
以下是部分参考代码:


public class TxnETExecutor extends AbstractExportTaskExecutor {private final MposScene mposScene;private final OssService ossService;@Overridepublic boolean support(int taskType) {return ExportTaskType.MPOS_TXN_BILL_EXPORT.ordinal() == taskType;}@Overridepublic int getFileSize(String reqBody, String audClientId, Long groupId) {TxnMposBillItemFindReq req = JSON.parseObject(reqBody, TxnMposBillItemFindReq.class);req.setAudClientId(audClientId);req.setLoginGroupId(groupId);req.setPage(1);req.setPageSize(1);req.setDiffStatus(true);Pageable pageable = mposScene.findByChannelBillItem(req);return pageable.getTotalPages().intValue();}public void execute(Long taskId, int fileSize, String reqBody, String audClientId, Long groupId) {TxnMposBillItemFindReq req = JSON.parseObject(reqBody, TxnMposBillItemFindReq.class);req.setAudClientId(audClientId);req.setLoginGroupId(groupId);req.setPage(1);req.setDiffStatus(true);int pageSize = Math.min(fileSize, DEFAULT_PAGE_SIZE);req.setPageSize(pageSize);Pageable pageable = mposScene.findByChannelBillItem(req);Long totalPages = pageable.getTotalPages();List<Map<String, Object>> first = parse(pageable.getItems());ByteArrayOutputStream outputStream = WebFluxUtils.buildExcelOutputStream(first, null);if (totalPages <= 1) {OssPutObjectResp objectResp = upload(audClientId, "xlsx", new ByteArrayInputStream(outputStream.toByteArray()));String fileUrl = objectResp.getFileUrl();update(CashierExportTaskUpdateReq.newBuilder().setId(taskId).setFileStatus(ExportTaskFileStatus.SUCCESS.ordinal()).setFileFormat("xlsx").setFileProgressRate("100%").setFileUrl(fileUrl).build());return;}Map<String, ByteArrayOutputStream> files = new HashMap<>();files.put(String.format("渠道对账单[%s-%s].xlsx", 1, totalPages), outputStream);for (int i = 2; i <= totalPages; i++) {req.setPage(i);Pageable pageableExportMore = mposScene.findByChannelBillItem(req);ByteArrayOutputStream j = WebFluxUtils.buildExcelOutputStream(parse(pageableExportMore.getItems()), null);files.put(String.format("渠道对账单[%s-%s].xlsx", i, totalPages), j);}Path tmp = zip(files);if (tmp == null) {update(CashierExportTaskUpdateReq.newBuilder().setId(taskId).setFileStatus(ExportTaskFileStatus.FAIL.ordinal()).setFileFormat("zip").setFileProgressRate("100%").build());return;}InputStream inputStream;try {inputStream = Files.newInputStream(tmp);} catch (IOException e) {e.printStackTrace();update(CashierExportTaskUpdateReq.newBuilder().setId(taskId).setFileStatus(ExportTaskFileStatus.FAIL.ordinal()).setFileFormat("zip").setFileProgressRate("100%").build());return;}try {OssPutObjectResp objectResp = upload(audClientId, "zip", inputStream);update(CashierExportTaskUpdateReq.newBuilder().setId(taskId).setFileStatus(ExportTaskFileStatus.SUCCESS.ordinal()).setFileFormat("zip").setFileProgressRate("100%").setFileUrl(objectResp.getFileUrl()).build());} catch (Exception e) {e.printStackTrace();update(CashierExportTaskUpdateReq.newBuilder().setId(taskId).setFileStatus(ExportTaskFileStatus.FAIL.ordinal()).setFileFormat("zip").setFileProgressRate("100%").build());} finally {try {Files.delete(tmp);} catch (IOException ignore) {}}}private List<Map<String, Object>> parse(Collection<TxnMposBillItemFindResp> items) {List<Map<String, Object>> result = new ArrayList<>();if (items == null || items.isEmpty()) {throw FibException.ofNotFound("暂无数据");}items.forEach(item -> {Map<String, Object> map = new LinkedHashMap<>();map.put("创建时间", item.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));map.put("批次号", item.getBatchNo());map.put("交易时间", item.getTransTime());map.put("交易月份", item.getTransMonth());map.put("平台订单号", item.getServerOrderId());......result.add(map);});return result;}private OssPutObjectResp upload(String audClientId, String suffix, InputStream inputStream) {return ossService.putObject(OssPutObjectReq.newBuilder().setBucketName(DEFAULT_BUCKET).setAudClientId(audClientId).setDirectoryPath("***").setSuffix(suffix).build(), inputStream);}
}
效果图:


相关文章:
微服务超大Excel文件导出方案优化
1、在导出Excel时经常会碰到文件过大,导出特别慢 2、微服务限制了请求超时时间,文件过大情况必然超时 优化思路: 1、文件过大时通过文件拆分、打包压缩zip,然后上传到oss,并设置有效期(30天过期) 2、把…...
论文阅读之Multimodal Chain-of-Thought Reasoning in Language Models
文章目录 简介摘要引言多模态思维链推理的挑战多模态CoT框架多模态CoT模型架构细节编码模块融合模块解码模块 实验结果总结 简介 本文主要对2023一篇论文《Multimodal Chain-of-Thought Reasoning in Language Models》主要内容进行介绍。 摘要 大型语言模型(LLM…...
灯塔:CSS笔记(2)
一 选择器进阶 后代选择器:空格 作用:根据HTML标签的嵌套关系,,选择父元素 后代中满足条件的元素 选择器语法:选择器1 选择器2{ css } 结果: *在选择器1所找到标签的后代(儿子 孙子 重孙子…...
基于Springboot的志愿服务管理系统(有报告)。Javaee项目,springboot项目。
演示视频: 基于Springboot的志愿服务管理系统(有报告)。Javaee项目,springboot项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构…...
保姆级讲解 Stable Diffusion
目录 本文讲解思路介绍 一、引入 二、Diffusion Model 三、原文的摘要和简介 四、Stable Diffusion 4.1、组成模块 4.2、感知压缩 4.3、条件控制 五、图解 Stable Diffusion 5.1、潜在空间的扩散 5.2、条件控制 5.3、采样 5.4、Diffusion Model 与 Stable Diffusion …...
HTML二识
图片,音频,视频标签 标签描述<img>定义图片<audio>定义音频<video>定义视频 定义图片: src:规定显示图片的URL(统一资源定位符)height:定义图像的高度 单位:px…...
[BUUCTF]-PWN:starctf_2019_babyshell解析(汇编\x00开头绕过+shellcode)
查看保护 查看ida 这里就是要输入shellcode,但是函数会有检测。 在shellcode前面构造一个以\x00机器码开头的汇编指令,这样就可以绕过函数检查了。 完整exp: from pwn import* context(log_leveldebug,archamd64) pprocess(./babyshell)she…...
uniapp 手写 简易 时间轴 组件
一、案例如图 该案例设计条件: 左侧时间 和竖线、点、内容都是居中对其的,上下时间点中间要有一段距离 二、编写逻辑 1. 布局结构:一共三个元素,左侧是时间和黑点,中间是线条,右侧是内容 2. 样式难点&#…...
实现HttpServletRequest下多次获取流数据
HttpServletRequest下多次获取流数据 背景示例错误的尝试全局替换执行顺序 背景 众所周知request的输入流只能读取一次,不能重复读取。而在HttpServletRequest中,获取请求体数据的流(通过getInputStream()方法)默认只能被读取一…...
uviewplus在uniapp中的配置使用
版本: "uview-plus": "^3.1.45"在page.json中配置: "easycom": {"autoscan": true,"custom": {"^u--(.*)": "uview-plus/components/u-$1/u-$1.vue","^up-(.*)": "uview-plus/componen…...
C++11 新特性之future和packaged_task
C11 新特性之future #include <iostream> #include <thread> #include <future> #include <chrono>void test(std::promise<int>& probj){std::this_thread::sleep_for(std::chrono::seconds(5));probj.set_value(20); }int main(){std::pr…...
Flutter APP下载更新
由于我做的项目不是放在APP商店(公司内部用)的,一些flutter的第三方库不合适我,我需要用的是从网上下载再安装(从服务下),网上也找了花了我好几天时间。不全又乱,这我自己做一下备份…...
Pinctrl子系统_04_Pinctrl子系统主要数据结构
引言 本节说明Pinctrl子系统中主要的数据结构,对这些数据结构有所了解,也就是对Pinctrl子系统有所了解了。 前面说过,要使用Pinctrl子系统,就需要去配置设备树。 以内核面向对象的思想,设备树可以分为两部分&#x…...
设计模式(十):抽象工厂模式(创建型模式)
Abstract Factory,抽象工厂:提供一个创建一系列相关或相互依赖对 象的接口,而无须指定它们的具体类。 之前写过简单工厂和工厂方法模式(创建型模式),这两种模式比较简单。 简单工厂模式其实不符合开闭原则,即对修改关闭…...
计算机网络概论01
计算机系统基础知识 基本组成 计算机系统由硬件和软件组成。 硬件由五大部分,他们分别是: 运算器 执行算数运算和逻辑运算控制器 控制cpu的工作,决定了计算机运行过程的自动化。包括指令控制逻辑、时序控制逻辑、总线控制逻辑和中断控制逻辑…...
新零售SaaS架构:订单履约系统架构设计(万字图文总结)
什么是订单履约系统? 订单履约系统用来管理从接收客户订单到将商品送达客户手中的全过程。 它连接了上游交易(客户在销售平台下单环)和下游仓储配送(如库存管理、物流配送),确保信息流顺畅、操作协同&…...
Hive SQL 开发指南(三)优化及常见异常
在大数据领域,Hive SQL 是一种常用的查询语言,用于在 Hadoop上进行数据分析和处理。为了确保代码的可读性、维护性和性能,制定一套规范化的 Hive SQL 开发规范至关重要。本文将介绍 Hive SQL 的基础知识,并提供一些规范化的开发指…...
Spring Boot 自动装配的原理!!!
SpringBootApplication SpringBootConfiguration:标识启动类是一个IOC容器的配置类 EnableAutoConfiguration: AutoConfigurationPackage:扫描启动类所在包及子包中所有的组件,生…...
Linux运维_Bash脚本_编译安装Wayland-1.22.0
Linux运维_Bash脚本_编译安装Wayland-1.22.0 Bash (Bourne Again Shell) 是一个解释器,负责处理 Unix 系统命令行上的命令。它是由 Brian Fox 编写的免费软件,并于 1989 年发布的免费软件,作为 Sh (Bourne Shell) 的替代品。 您可以在 Linu…...
Python数字类型
文章目录 Python数字类型1. 数字类型1.1 数字类型概述1.2 整数类型1.3 浮点数类型1.4 复数 2. 数字类型的操作2.1 内置的数值运算操作符2.2 内置的数值运算函数2.3 内置的数字类型转换函数 思考与练习 Python数字类型 1. 数字类型 1.1 数字类型概述 数字是自然界计数活动的抽…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...
