springboot 本地/minio 附件下载优化

news2024/11/25 11:19:19

文章目录

  • 前言
  • 一、Direct buffer memory
    • 1.1 原因分析
    • 1.2 解决方案
  • 二、附件下载
    • 2.1 问题分析
    • 2.2 解决方案
      • 2.2.1 本地下载
      • 2.2.1 minio下载


前言

  1. 本地上传大文件内存溢出 Direct buffer memory
  2. 附件下载服务端传流给前端需要将流缓存完毕才可以下载,导致大文件下载系统崩溃

一、Direct buffer memory

后端服务采用nio本地上传到服务器指定目录,通过nginx代理提供下载

1.1 原因分析

Java8出现了NIO,缓存,通道,选择器。在 写NIO程序的时候,经常使用ByteBuffer来读或者写入数据,这是一种基于通道(
Channel)与缓冲区( Buffer)的I/0方式.它可以使用 Native函数库直接分配堆外内存,然后通过一个存做在Java里面的
DirectByteBuffer对作为这块内存的引用进行操作。可以提高性能,因为避免了在Java堆和 Native堆中来回复制数据。
ByteBuffer. allocate(capability)第一种方式是分配java堆内存,属于GC管理范围,由于需要进行拷贝,所以比较慢。
ByteBuffer. allocteDirect (capability)第一种方式是分配操作系统的本地内存,不属于GC管辖范围,由于不需要内存拷贝所以速度相对较快。但如果不断分配本地内存,堆内存很少使用,那么java虚拟机就不需要进行GC,
DirectByteBuffer对象们就不会被回收,这个时候堆内存充足,但本地内存可能已经使用光了,在尝试分配本地内存就会出0ut0fMemory
Error,那程序就直接奔溃了。

linux 清理内存命令echo 1 > /proc/sys/vm/drop_caches

1.2 解决方案

采用慎用nio,特别是对大数据流场景,这里改用普通io操作数据流(后续引发问题分析)

二、附件下载

2.1 问题分析

无论是本地下载还是minio下载都存在一个隐形问题。
前端blog请求后,要等服务端将整个附件流传输完毕后才可以下载,对大文件(600M)不友好,大概率卡死。
F12 可以看到接口响应的大小一直在上升,直到整个文件传输完毕浏览器才会响应。
F12 可以看到
我们可以看到互联网下载都是在浏览器下载管理器下载,那么我们如何实现?
在这里插入图片描述
实际上本地下载我们通过nginx代理后的地址可以直接访问文件地址进行下载,满足上述要求。但是这样的操作会导致附件下载绕过后端直接请求,无法防止盗链。minio上传无法通过nginx实现(不考虑下载到服务器nginx代理,这样不合理)。

2.2 解决方案

2.2.1 本地下载

nginx + 重定向X-Accel-Redirect
这个功能允许你在后端处理权限,日志或任何你想干的,Nginx提供内容服务给终端用户从重定向后的路径,因此可以释放后端去处理其他请求(直接由Nginx提供IO,而不是后端服务)。这个功能类似 X-Sendfile 。

具体步骤篇幅太长请移步链接

2.2.1 minio下载

  1. minio管理界面可以截取到下载路径,模拟他的下载即可

  2. 连接地址发现需要传入minio的登录token,下一步想办法获取token

  3. 高版本支持多用户,可创建临时用户获取token(8.4.3)

  4. 高版本管理界面下载路径变了,【minio ip port】+/api/v1/buckets/+【bucket】+/objects/download?prefix=【Base64.*encode(附件路径)】+\&token=* + *token*

  5. 直接访问上一步的url即可下载

    https://github.com/minio/minio-java/tree/release/examples

    public Credentials getCredentials() {
        int durationSeconds = 360000;//秒
        //创建签名对象
        AssumeRoleProvider provider = new AssumeRoleProvider(
                properties.getUrl(),
                properties.getAccessKey(),
                properties.getSecretKey(),
                durationSeconds,//默认3600秒失效,设置小于这个就是3600,大于3600就实际值
                "{\n" +
                        " \"Version\": \"2012-10-17\",\n" +
                        " \"Statement\": [\n" +
                        "  {\n" +
                        "   \"Effect\": \"Allow\",\n" +
                        "   \"Action\": [\n" +
                        "    \"s3:GetObject\",\n" +
                        "    \"s3:GetBucketLocation\",\n" +
                        "    \"s3:PutObject\"\n" +
                        "   ],\n" +
                        "   \"Resource\": [\n" +
                        "    \"arn:aws:s3:::test/*\"\n" +
                        "   ]\n" +
                        "  }\n" +
                        " ]\n" +
                        "}",
                properties.getRegion(),
                "arn:aws:s3:::*/*",
                "anysession",
                null,
                null);
        
        Credentials credentials = provider.fetch();
        return credentials;
    }
    public String downloadByLink(HttpServletRequest request, HttpServletResponse response, String fileId) {
        AttachmentPO po = attachmentService.findById(fileId);
        Credentials credentials = minioTemplate.getCredentials();
        String token = credentials.sessionToken();
        //为了统一前端访问路径,直接查客户端请求Referer minio是前端ng代理的minio实际访问
        String referer = request.getHeader("Referer");
        String url = referer + "minio/api/v1/buckets/" + po.getClientId() + "/objects/download?prefix=" + Base64.encode(po.getPath()) + "&token=" + token;
        return url;
    }

在这里插入图片描述

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

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

相关文章

C语言指针:深入理解与应用

C语言指针:深入理解与应用 指针作为C语言的核心概念之一,对于学习C语言的程序员来说具有重要意义。本文将详细介绍C语言指针的基本概念、运算符、指针与数组的关系、函数指针以及指针的常见应用场景等。通过阅读本文,你将对C语言指针有更深入…

【Java多线程进阶】线程池详解

前言 在大量的并发任务中,频繁的创建和销毁线程对系统的开销是非常大的,多个任务执行的速度也是非常慢的。因此,设计出一个好的 Java 线程池就可以减少系统的开销、使程序运行速度提升。在这篇博文中,我将介绍 Java 线程池概念以及…

RocketMq-主从集群搭建

目录 1.服务器列表 2.下载安装包 3.node1节点修改runserver.sh文件 4. 所有节点安装jdk 5. node1节点配置RocketMQ集群 1.配置node1节点borker-a的master配置文件 2.配置node2节点配置borker-a的slave borker-a-s节点 3.配置node3节点配置borker-b的master节点 4.配置…

【Python】Python系列教程--Python3 基本数据类型(五)

文章目录 前言多个变量赋值标准数据类型Number(数字)数值运算数值类型实例String(字符串)List(列表)Tuple(元组)Set(集合)Dictionary(字典&#x…

低代码开发重要工具:jvs-rules 规则引擎功能介绍(三)

一、JVS规则引擎的决策流可视化组成 决策流的可视化拼装 规则引擎是由多个组件组成的,这些组件共同协作实现规则的管理、执行和决策流的构建。 决策流:决策流是由多个业务节点连接而成的流程,用于实现复杂的业务逻辑。决策流中的业务节点按…

Rust安装手册

Rust 环境搭建 Rust 支持很多的集成开发环境(IDE)或开发专用的文本编辑器。 官方网站公布支持的工具如下(https://www.rust-lang.org/zh-CN/tools): 本教程将使用 Visual Studio Code 作为我们的开发环境&#xff08…

NIO之Selector解读

目录 Selector 简介 为什么会出现Selector Selector 和 Channel 关系 可选择通道(SelectableChannel) Channel 注册到 Selector 选择键(SelectionKey) Selector 的使用方法 Selector 的创建 注册 Channel 到 Selector 轮询查询就绪操作 停止选择的方法 Selector 简…

全志Tina Linux下如何编译glibc库

本文整理自问答:https://bbs.aw-ol.com/topic/3615/ make工具 注意由于AW服务器make版本为3.8.1,在编译glibc高版本时候不兼容,所以需要更新make工具。假如服务器make版本较高,可以不用更新make工具。 网址 http://ftp.gnu.org/…

chatgpt赋能python:Python函数介绍

Python函数介绍 函数是Python编程中最重要的概念之一。它是一段可重用代码的集合,通过一个名字来暴露出来,可以在Python程序的多个地方调用。函数可以接收任意数量的参数,也可以返回值。Python中函数定义使用关键字 def。 Python函数定义 …

ChatGPT教你学Python爬虫

“ chatgpt作为一个编程助手,虽然不能帮我们解决一个复杂的业务需求,但在处理一些具体工具类需求上,能够快速生成我们需要的代码,尤其对一些编程初学者,不仅能借助chatgpt快速完成自己的小工具,还能在与cha…

硬件 TCP/IP 协议栈

目录 全硬件的TCP/IP 协议栈简介以太网接入单片机方案以太网接口芯片CH395Q 简介以太网接口芯片CH395Q 命令简介以太网接口芯片CH395Q 寄存器配置与使用移植CH395Q 源码 TCP_Client 实验TCPClient 配置流程TCPClient 实验硬件设计程序设计下载验证 WebServer 实验WebServer 简介…

chatgpt赋能python:Python编程:如何写文件到指定目录

Python编程:如何写文件到指定目录 Python是一种高级编程语言,它具有简单易学、可读性高的特点,并且能够应用于各种领域,尤其是数据科学和机器学习领域。在Python中,我们可以通过编写代码实现将文件写入到指定目录中。…

JavaEE(系列18) -- 文件操作I/O

前言: 我们平时所说的文件都是指硬盘上的文件,而我们之前在JavaSE阶段代码绝大部分都是围绕内存展开的,定义个变量,其实就是内存上申请空间。 内存和硬盘的区别: 速度:内存比硬盘快很多。空间:内存空间比硬盘小。成本:内存比硬盘贵…

利用CiteSpace快速锁定领域内最新研究热点并制作精美的可视化专题图

【基于Citespace和vosviewer文献计量学相关论文 】 ​ 01 文献计量学方法与应用 1. 文献计量学方法基本介绍 2. 与其他综述方法区别联系 3. 各学科领域应用趋势近况 4. 主流分析软件优缺点对比 5. 经典高分10SCI思路复盘 6. 软件安装与Java环境配置 02 主题确定、数据检…

Power BI 如何高效管理度量值和字段

内容说明 背景需求: 当分析场景涉及大量数据和分析度量值时,为了更好的区分原始数据和用于分析的度量值,需要合理安排和管理数据字段。 本文总结了三种方法: 移动度量值位置创建字段文件夹:子文件夹和多个文件夹创建…

chatgpt赋能python:Python函数改名:为什么需要改名以及如何改名

Python函数改名:为什么需要改名以及如何改名 在Python编程中,函数是非常常见和重要的代码语句,用于完成特定的任务或操作。然而,在实际开发中,我们可能需要对已有函数进行改名,这个过程可能并不简单&#…

国产BI工具大比拼,帆软Fine BI和观远BI到底该怎么选型?

之前写了一篇关于BI如何选型的文章《「BI选型秘诀」BI工具不知道怎么选择?这张选型评分表你一定要收藏!》。 文章发布后,不少朋友私信我,想要我出个国产BI工具的测评,今天就开始第一期:帆软 VS 观远 仍旧…

el-form嵌套el-table编辑,校验信息显示在气泡框中

文章目录 概要整体架构流程技术名词解释技术细节 概要 提示:这里可以添加技术概要 正常情况下,el-table可编辑表格,如果输入框内容不合理的情况下,错误提示会显示在el-input下方对应。 但是,我不得不将错误提示放到el…

chatgpt赋能python:Python几行几列是什么?

Python几行几列是什么? Python几行几列是一款基于Python语言开发的优秀的划线工具。这个工具能够帮助开发者轻松创建、管理和分享自己的Python代码。Python几行几列是一款高效、易用的Python编辑器,它既可以用于快速编写Python代码,也可以用…