springcloud:对象存储组件MinIO(十六)

news2024/11/29 12:54:55

0. 引言

在实际开发中,我们经常会面临需要存储文档、存储图片等文件存储需求,并且在分布式架构下,文件又需要实现各节点共享,类似于共享文件夹类的需求,在分布式服务器中创建共享文件夹成本较大,甚至当需要跨机房访问时就不满足了,此时我们需要一个第三方的组件,来实现这类对象存储

也就出现了OSS、OBS、minIO、hdfs这类对象存储组件,今天,我们主要来学习免费开源的MinIO组件

1. minio简介

MinIO是一个使用go语言开发的,开源的对象存储组件,能够提供高性能、高可用的数据存储能力,支持分布式部署,提供数据加密、访问控制、版本控制、生命周期管理和事件通知等功能。它还支持高级特性,如分片上传和分片下载,以提高大文件的处理效率。

官方文档:https://www.minio.org.cn/

在这里插入图片描述

2. minio安装

minio支持docker安装,压缩包安装,这里我们为了安装方便,采用docker安装,如果使用的是mac,也可以使用brew工具安装,具体可参考官网文档:https://github.com/minio/minio

1、下载镜像

docker pull minio/minio

2、创建数据映射目录

mkdir -p /Library/software/dockerdata/minio/data

3、创建容器

注意这里我安装的版本是RELEASE.2023-01-02T09-40-09Z

docker run -p 9000:9000 -p 9090:9090 \
 --name minio \
 -e "MINIO_ACCESS_KEY=minioadmin" \
 -e "MINIO_SECRET_KEY=minioadmin" \
 -v /Library/software/dockerdata/minio/data:/data \
 minio/minio server \
 /data --console-address ":9090" -address ":9000"

4、登陆 localhost:9090,输入账号/密码: minioadmin / minioadmin
在这里插入图片描述

3. minio管理端介绍

管理端默认通过9090端口进入:http://ip:9090/

其中比较常用的菜单包括:

  • Object Browser: 对象管理页面,minio中所有的桶和桶中的文件都可以在这个页面查看,这里的桶 bucket,大家可以简单的理解为文件夹
    在这里插入图片描述- Buckets: 桶管理页面,用于管理桶相关的配置,比如桶的访问权限、桶的生命周期(桶中文件保留几天)
    在这里插入图片描述
  • Identity: 权限管理页面,可以创建用户、分组,并设置对应权限等
    在这里插入图片描述
  • Monitoring: 监控页面,监控显示minio的各类健康、状态、日志信息
    在这里插入图片描述

4. minio客户端使用

1、添加pom依赖

<dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.5.3</version>
</dependency>

<dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.10.0</version>
</dependency>

2、增加配置文件

minio:
  # minio地址
  endpoint: http://localhost:9000
  # 账户
  username: minioadmin
  # 密码
  password: minioadmin
  defaultBucketName: test

3、创建配置类,用于生成MinioClient

/**
 * @author benjamin_5
 * @Description minio配置类
 * @date 2023/8/5
 */
@Configuration
public class MinioConfig {

    @Value("${minio.endpoint}")
    private String endpoint;

    @Value("${minio.username}")
    private String username;

    @Value("${minio.password}")
    private String password;

    @Value("${minio.defaultBucketName}")
    private String defaultBucketName;

    @Bean
    public MinioClient minioClient(){
        return MinioClient.builder().credentials(username, password).endpoint(endpoint).build();
    }

}

4、创建一个返回实体类,方便规范返回信息

@Data
public class MinioReturn {

    /**
     * 文件地址
     */
    private String path;

    /**
     * 原始文件名
     */
    private String inputName;

    /**
     * 最终文件名
     */
    private String outPutName;

}

5、创建MinioTemplate类,用来书写minio工具类

@Component
public class MinioTemplate {

    @Autowired
    private MinioClient minioClient;

    private static final String SLASH = "/";

    @Value("${minio.defaultBucketName}")
    private String defaultBucketName;

    @Value("${minio.endpoint}")
    private String endpoint;

    /**
     * 创建桶
     *
     * @param bucketName
     * @throws Exception
     */
    public void makeBucket(String bucketName) throws Exception {
        BucketExistsArgs args = BucketExistsArgs.builder().bucket(bucketName).build();
        if (!minioClient.bucketExists(args)) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     * 上传文件
     *
     * @param file
     * @return
     * @throws Exception
     */
    public MinioReturn putFile(MultipartFile file) throws Exception {
        return putFile(file, file.getOriginalFilename(), defaultBucketName);
    }

    public MinioReturn putFile(MultipartFile file, String fileName, String bucketName) throws Exception {
        if (bucketName == null || bucketName.length() == 0) {
            bucketName = defaultBucketName;
        }
        makeBucket(bucketName);
        minioClient.putObject(PutObjectArgs.builder()
                .bucket(bucketName)
                .object(fileName)
                .stream(file.getInputStream(), file.getSize(), -1)
                .contentType(file.getContentType())
                .build());
        return new MinioReturn(fileLink(bucketName, fileName), file.getOriginalFilename(), fileName);
    }

    /**
     * 删除文件
     *
     * @param bucketName
     * @param fileName
     * @throws Exception
     */
    public void removeFile(String bucketName, String fileName) throws Exception {
        minioClient.removeObject(RemoveObjectArgs.builder()
                .bucket(bucketName == null || bucketName.length() == 0 ? defaultBucketName : bucketName)
                .object(fileName)
                .build());
    }

    @SneakyThrows
    private String fileLink(String bucketName, String fileName) {
        return endpoint.concat(SLASH).concat(bucketName).concat(SLASH).concat(fileName);
    }

    private String getFileName(String fileName) {
        return getFileName(null, fileName);
    }

    private String getFileName(String prefix, String fileName) {
        String fileNamePre = fileName;
        String fileType = "";
        int index = fileName.lastIndexOf(".");
        if (index > 0) {
            fileNamePre = fileName.substring(0, index);
            fileType = fileName.substring(index);
        }
        String name = UUID.randomUUID().toString().replace("-", "");
        if (!org.springframework.util.StringUtils.isEmpty(fileNamePre)) {
            name = fileNamePre + "-" + name + fileType;
        }
        if (!StringUtils.isEmpty(prefix)) {
            name = prefix + "-" + name;
        }
        return name;
    }


}

6、书写控制类,用于测试

@RestController
@RequestMapping("minio")
@AllArgsConstructor
public class MinioController {

    private final MinioTemplate minioTemplate;

    @PostMapping("/upload")
    @ResponseBody
    public MinioReturn upload(MultipartFile file) throws Exception {
        return minioTemplate.putFile(file);
    }

    @PostMapping("/remove")
    @ResponseBody
    public String remove(String fileName, String bucketName) throws Exception{
        minioTemplate.removeFile(bucketName, fileName);
        return "success";
    }

}

7、调用上传接口,如下图所示,调用成功

在这里插入图片描述
我们查看minio中,自动创建了桶,并且文件也上传成功了

在这里插入图片描述
同样再测试一下删除接口

在这里插入图片描述
查看minio中删除成功

在这里插入图片描述

5. 应用场景

    1. 静态资源存储

如在官网、门户、首页等网站,我们经常需要加载一些静态资源,如图片、js文件、视频文件等,一些我们可以直接存放到nginx加载,另一方面我们也可以存放到minio中,通过minio进行访问

要通过minio访问的前提是记得把桶权限设置为public

在这里插入图片描述
上述代码创建的桶默认是private的,如果想要通过客户端代码调整桶权限的话,可以通过minioClient.setBucketPolicy方法,设置完后可以通过返回的地址进行访问,如下所示(如果想要通过外网访问,给对应的内网地址端口做个外网映射即可)

在这里插入图片描述

开启权限public会有个安全问题,那就是当你访问桶路径时,会发现会把所有桶下的文件列出来,这样只要再拼接上文件名就能访问所有文件了

在这里插入图片描述

要解决这个问题,只需要将权限设置为custom,然后将"s3:ListBucket"取消即可

在这里插入图片描述
再次访问会发现权限禁止,而加上文件名后是可以正常查看的
在这里插入图片描述

当然如果在旧版本中是不支持直接在minio管理页面中直接设置的,你可以通过下载s3browser https://s3browser.com/,连接上minio后,右键在Edit Bucket Policy中设置

在这里插入图片描述

    1. 文件暂存

某些时候,涉及组件或系统间传输文件时,直接通过接口传输效率太慢且及时性不足,或者用户其实收到后不需要马上查看这些文件,这时我们就可以把文件暂存到minio中,发送一个文件地址给客户,客户收到这个地址可以再进行下载。
既然是文件暂存,那么就希望能自动删除,实现自动删除有两种方法,一种是通过书写shell脚本,直接删除指定路径下的文件,minio在服务器上存储的文件就是直接放在文件夹下,没有特殊处理,所以直接删除即可,第二种就是使用minio提供的生命周期管理,在Buckets-Lifecycle中可以设置,同时这个也可以在客户端中创建桶时就设置,通过minioClient.setBucketLifecycle();方法

在这里插入图片描述

    1. 解放带宽压力

某些时候,涉及接口文件传输时,直接传输占用大量带宽,导致并发上不去,而客户可能也不需要马上使用到传输的文件,只是需要马上知道一个状态或者其他信息,这时就可以通过将文件上传到minio, 而发送一个文件地址给客户,这样将文件状态通知和下载分步进行。
这里某的同学可能会想,下载不还是要占用带宽吗,怎么说是节约带宽资源呢,这是因为一般接口调用追求耗时,我们一般会把接口服务的带宽部署为性能更高的,价格自然更贵,而文件下载服务的没有那么高的延迟要求,就单独拉一根性能相对没那么强的,也就更便宜的,这样自然减少了带宽费用

6. 总结

至此,我们针对minio的快速上手就完成了, 文中只是描述了minio最常用的方法,还有更多方法、指令等待大家自己探索学习。

文中演示源码见如下地址:https://gitee.com/wuhanxue/wu_study/tree/master/demo/minio_demo

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

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

相关文章

Java课题笔记~ 不使用 AOP 的开发方式(理解)

Step1&#xff1a;项目 aop_leadin1 先定义好接口与一个实现类&#xff0c;该实现类中除了要实现接口中的方法外&#xff0c;还要再写两个非业务方法。非业务方法也称为交叉业务逻辑&#xff1a; doTransaction()&#xff1a;用于事务处理 doLog()&#xff1a;用于日志处理 …

第一天 什么是CSRF ?

✅作者简介&#xff1a;大家好&#xff0c;我是Cisyam&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Cisyam-Shark的博客 &#x1f49e;当前专栏&#xff1a; 每天一个知识点 ✨特色专…

【小沐学C++】C++ 基于CMake构建工程项目(Windows、Linux)

文章目录 1、简介2、下载cmake3、安装cmake4、测试cmake4.1 单个源文件4.2 同一目录下多个源文件4.3 不同目录下多个源文件4.4 标准组织结构4.5 动态库和静态库的编译4.6 对库进行链接4.7 添加编译选项4.8 添加控制选项 5、构建最小项目5.1 新建代码文件5.2 新建CMakeLists.txt…

neo4j查询语言Cypher详解(二)--Pattern和类型

Patterns 图形模式匹配是Cypher的核心。它是一种用于通过应用声明性模式从图中导航、描述和提取数据的机制。在MATCH子句中&#xff0c;可以使用图模式定义要搜索的数据和要返回的数据。图模式匹配也可以在不使用MATCH子句的情况下在EXISTS、COUNT和COLLECT子查询中使用。 图…

Java Map集合详解 :HashMap类

Map 是一种键-值对&#xff08;key-value&#xff09;集合&#xff0c;Map 集合中的每一个元素都包含一个键&#xff08;key&#xff09;对象和一个值&#xff08;value&#xff09;对象。用于保存具有映射关系的数据。 Map 集合里保存着两组值&#xff0c;一组值用于保存 Map …

FAST协议详解1 不同数据类型的编码与解码

一、概述 FAST协议里不同的数据类型在编码时有非常大的区别&#xff0c;比如整数只需要将二进制数据转为十进制即可&#xff0c;而浮点数则需要先传小数点位数&#xff0c;再传一个整数&#xff0c;最后将二者结合起来才是最终结果。本篇使用openfast自设了一些数据并编码成FA…

一文了解 Android Auto 车载开发~

作者&#xff1a;牛蛙点点申请出战 背景 我的的产品作为一个海外音乐播放器&#xff0c;在车载场景听歌是一个很普遍的需求。在用户反馈中&#xff0c;也有很多用户提到希望能在车上播放音乐。同时车载音乐也可以作为提升用户消费时长一个抓手。 出海产品&#xff0c;主要服务…

[国产MCU]-BL602开发实例-定时器

定时器 文章目录 定时器1、BL602定时器介绍2、定时器驱动API介绍3、定时器使用实例3.1 单次计时3.2 持续计时通用定时器,用于定时,当时间到达我们所设置的定时时间会产生定时中断,可以用来完成定时任务。本文将详细介绍如何使用BL602的定时器功能。 1、BL602定时器介绍 BL6…

vscode自动添加注释说明

1. 安装vscode 双击安装程序,默认安装即可(如:VSCodeSetup-x64-1.70.2.exe) 2. 安装doxygen文档生成插件 1> 打开vscode软件,点击左侧插件管理菜单 2> 点击右上角’…‘按钮,选择’Install from VSIX’(联网状态可以直接搜索doxygen下载安装) 3> 选择doxygen离线安装…

torchvision.datasets数据加载失败

torchvision.datasets数据加载失败 如何使用torchvision.datasets进行自动下载数据失败&#xff0c;可以使用手动下载数据 Ctrl点击可以进入相关包文件&#xff0c;查找下载地址&#xff1a;https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz 手动下载之后解压&#x…

【Spring】(四)Bean 的作用域和生命周期

文章目录 前言一、Bean 的作用域1.1 被修改的 Bean 案例1.2 作用域的定义1.3 Bean 的六种作用域1.4 Bean 作用域的设置 二、Spring 的执行流程 和 Bean 的生命周期2.1 Spring 的执行流程2.2 Bean 的生命周期2.3 Bean 生命周期的演示 前言 Bean 是 Spring 框架中的一个核心概念…

Benchmarking Augmentation Methods for Learning Robust Navigation Agents 论文阅读

论文信息 题目&#xff1a;Benchmarking Augmentation Methods for Learning Robust Navigation Agents: the Winning Entry of the 2021 iGibson Challenge 作者&#xff1a;Naoki Yokoyama, Qian Luo 来源&#xff1a;arXiv 时间&#xff1a;2022 Abstract 深度强化学习和…

AssetBundleBrowser导入报错解决方案

第一次导入AssetBundleBrowser遇到报错有 Assets\Scenes\AssetBundles-Browser-master\AssetBundles-Browser-master\Tests\Editor\ABModelTests.cs(13,7): error CS0246: The type or namespace name Boo could not be found (are you missing a using directive or an assem…

24届近5年杭州电子科技大学自动化考研院校分析

今天给大家带来的是杭州电子科技大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、杭州电子科技大学 学校简介 杭州电子科技大学&#xff08;Hangzhou Dianzi University&#xff09;&#xff0c;简称“杭电”&#xff0c;位于杭州市&#xff0c;是浙江省人民政…

Containerd容器镜像管理

1. 轻量级容器管理工具 Containerd 2. Containerd的两种安装方式 3. Containerd容器镜像管理 4. Containerd数据持久化和网络管理 1、Containerd镜像管理 1.1 Containerd容器镜像管理命令 docker使用docker images命令管理镜像单机containerd使用ctr images命令管理镜像,con…

消息队列 -封装数据库的操作

前言 上一篇博客我们写了, 关于交换机, 队列,绑定, 写入数据库的一些建库建表的操作 这一篇博客中,我们将建库建表操作,封装一下实现层一个类来供上层服务的调用 , 并在写完该类之后, 测试代码是否完整 实现封装 在写完上述的接口类 与 xml 后, 我们想要 创建一个类 ,来调用…

Neety与IO模型简介

Netty与IO模型简介 1、Netty 是由 JBOSS 提供的一个 Java 开源框架&#xff0c;现为 Github 上的独立项目。 2、Netty 是一个异步的、基于事件驱动的网络应用框架&#xff0c;用以快速开发高性能、高可靠性的网络 IO 程序。 3、Netty 主要针对在 TCP 协议下&#xff0c;面向…

2023牛客暑期多校训练营7-c-Beautiful Sequence

思路&#xff1a; &#xff0c;则有&#xff0c;也就是说只要知道A1就可以求任意A。由于A是升序排列&#xff0c;所以对于任意&#xff0c;二进制所包含1的最高位第k位来说&#xff0c;表明与第k位相反&#xff0c;要大一些&#xff0c;所以它的第k位为1&#xff0c;的第k位为…

echarts 柱状图 实例

实例效果&#xff1a; 代码&#xff1a; draw(data1, data2,data3) {var option {// backgroundColor: rgb(10,36,68),tooltip: {trigger: axis,axisPointer: {type: shadow,},formatter: function (params: any, ticket: any, callback: any) {const item params[0];var str…

关于“为爱发电”的一些说明~~

对不起&#xff0c;兄弟们&#xff0c;收费了。。 1. 为什么设置收费 emm...混口饭吃。 也是大龄程序员积在极探索挣钱之路。 2. 都有哪些服务 本专栏的手把手教学资料工程文件&#xff0c;但是近期忙于CMN&#xff0c;可能没时间答疑和讨论&#xff0c;见谅。 另外&#xff0…