Github 标星 32K+Star,16 分钟搭建高性能的文件服务器!

2022-04-25 16:11:11 浏览数 (1)

点击上方“芋道源码”,选择“设为星标”

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 10:33 更新文章,每天掉亿点点头发...

源码精品专栏

  • 原创 | Java 2021 超神之路,很肝~
  • 中文详细注释的开源项目
  • RPC 框架 Dubbo 源码解析
  • 网络应用框架 Netty 源码解析
  • 消息中间件 RocketMQ 源码解析
  • 数据库中间件 Sharding-JDBC 和 MyCAT 源码解析
  • 作业调度中间件 Elastic-Job 源码解析
  • 分布式事务中间件 TCC-Transaction 源码解析
  • Eureka 和 Hystrix 源码解析
  • Java 并发源码
  • 1. MinIO 简介
  • 2. MinIO Server 安装
  • 3. MinIO Client 命令行工具
  • 4. Spring Boot 实战
  • 666. 彩蛋

本文在提供完整代码示例,可见 https://github.com/YunaiV/SpringBoot-Labs 的 lab-72-minio 目录。 原创不易,给点个 Star 嘿,一起冲鸭!

1. MinIO 简介

MinIO 是一个基于 Go 实现的高性能、兼容 S3 协议的对象存储。它采用 GNU AGPL v3 开源协议,项目地址是 https://github.com/minio/minio,官网是 https://min.io。

它适合存储海量的非结构化的数据,例如说图片、音频、视频等常见文件,备份数据、容器、虚拟机镜像等等,小到 1 KB,大到 5 TB 都可以支持。

国内阿里巴巴、腾讯、百度、华为、中国移动、中国联通等企业在使用 MinIO,甚至不少商业公司二次开发 MinIO 来提供商业化的云存储产品。

疑问:为什么越来越少使用 FastDFS 实现文件存储服务呢? 部署运维复杂、无官方文档、缺乏长期维护的团队、性能较差、未提供 Docker & Kubernetes 集成方案等等原因。

本文,艿艿将带你使用 MinIO 来自建一个文件存储服务,并在 Spring Boot 项目中上传图片到 MinIO 中。

基于 Spring Boot MyBatis Plus Vue & Element 实现的后台管理系统 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能。 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

2. MinIO Server 安装

由于 MinIO 是 Go 写的,所以就一个运行程序,因此安装部署 MinIO 就非常简单。

在文档 https://min.io/download 中,有 Windows、Linux、MacOS、Docker、Kubernetes、Source 六种安装方式。

下面,我们来安装下 MinIO,你可以选择适合你的方式。

2.1 快速安装

2.1.1 Windows

需要在 Windows PowerShell 中执行。

代码语言:javascript复制
Invoke-WebRequest -Uri "https://dl.min.io/server/minio/release/windows-amd64/minio.exe" -OutFile "C:minio.exe" ## 国外资源,龟速下载
setx MINIO_ROOT_USER admin
setx MINIO_ROOT_PASSWORD password
C:minio.exe server F:Data --console-address ":9001" ## F:Data 存储目录;--console-address 是 UI 界面的端口
2.1.2 Linux
代码语言:javascript复制
wget https://dl.min.io/server/minio/release/linux-amd64/minio ## 国外资源,龟速下载
chmod  x minio
MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password ./minio server /Users/yunai/minio --console-address ":9001" ## /Users/yunai/minio 存储目录;--console-address 是 UI 界面的端口

2.1.3 MacOS

代码语言:javascript复制
wget https://dl.min.io/server/minio/release/darwin-amd64/minio ## 国外资源,龟速下载
chmod  x minio
MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password ./minio server F:Data --console-address ":9001" ## F:Data 存储目录;--console-address 是 UI 界面的端口
2.1.4 Docker

① Windows:

代码语言:javascript复制
docker run -p 9000:9000 -p 9001:9001 -e "MINIO_ACCESS_KEY=admin" -e "MINIO_SECRET_KEY=password" minio/minio server /data --console-address ":9001" # /Users/yunai/minio 存储目录;--console-address 是 UI 界面的端口

② Linux 或 MacOS:

代码语言:javascript复制
docker run -p 9000:9000 -p 9001:9001 -e "MINIO_ACCESS_KEY=admin" -e "MINIO_SECRET_KEY=password" minio/minio server /Users/yunai/minio --console-address ":9001" ## /Users/yunai/minio 存储目录;--console-address 是 UI 界面的端口

2.2 访问 UI 界面

使用浏览器访问 http://127.0.0.1:9001 地址,访问 MinIO 内置的 UI 界面。

输入账号 admin,密码 password 进行登录,成功进入首页。

UI 首页

2.3 新建存储桶

点击 [Create Bucket] 按钮,新建一个 Bucket 存储桶,用于稍后文件的上传。

Create Bucket

2.4 添加 readonly 访问规则

默认配置下,访问存储桶是需要请求授权的。但是在实际场景下,我们往往希望允许直接访问,此时就需要添加一条 readonly 访问规则。

① 点击右上角的 [Configure Bucket] 设置图标,然后选择 [Access Rules] 菜单。

Access Rules

② 点击 [Add Access Rule] 按钮,添加一条 Prefix 为 / Access 为 readonly 的规则。

Add Access Rule

2.5 上传文件

点击 [Upload] 按钮,点击 [Upload File] 选项,选择一个图片上传。

Upload File

2.6 访问文件

文件的访问地址的格式为 <http://127.0.0.1:9000/{bucket}/{name}>,注意是 9000 端口。

我们刚上传的文件 {bucket} 是 yudaoyuanma,{name} 是 822aebded6e6414e912534c6091771a4.jpg,所以最终的访问路径是 http://127.0.0.1:9000/yudaoyuanma/822aebded6e6414e912534c6091771a4.jpg。

访问文件

基于微服务的思想,构建在 B2C 电商场景下的项目实战。核心技术栈,是 Spring Boot Dubbo 。未来,会重构成 Spring Cloud Alibaba 。 项目地址:https://github.com/YunaiV/onemall

3. MinIO Client 命令行工具

MinIO Client (mc) 是 MinIO 提供的命令行工具,用于访问 MinIO Server。它的命令设计的非常棒,和我们在使用 ls、cat、cp、mirror、diff、find 等 Unix 命令基本接近,主要如下:

代码语言:javascript复制
ls       列出文件和文件夹
mb       创建一个存储桶或一个文件夹
cat      显示文件和对象内容
pipe     将一个 STDIN 重定向到一个对象或者文件或者 STDOUT
share    生成用于共享的 URL
cp       拷贝文件和对象
mirror   给存储桶和文件夹做镜像
find     基于参数查找文件
diff     对两个文件夹或者存储桶比较差异
rm       删除文件和对象
events   管理对象通知
watch    监听文件和对象的事件
policy   管理访问策略
session  为 cp 命令管理保存的会话
config   管理 mc 配置文件
update   检查软件更新
version  输出版本信息

例如说,使用 mc ls 列出有哪些 Bucket 存储桶:

mc 示例

考虑到你对 MinIO Client 可能不是很感兴趣,艿艿就暂时不过多啰嗦。感兴趣的话,可以看看如下文档:

  • MinIO Client 安装:https://min.io/download
  • MinIO Client 命令:https://docs.min.io/minio/baremetal/reference/minio-mc.html

4. Spring Boot 实战

示例代码对应仓库:lab-72-minio 。

接下来,我们来新建一个 Spring Boot 项目 lab-72-minio ,实现文件的上传与删除的功能。

4.1 引入依赖

pom.xml 文件中,引入 MinIO 相关依赖。

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lab-72-minio</artifactId>

    <dependencies>
        <!-- 实现对 Spring MVC 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- MinIO 客户端 -->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.2.2</version>
        </dependency>
    </dependencies>

</project>

注意,如果引入的 Minio 的版本过高,例如说 8.3.7,会报依赖的冲突:

代码语言:javascript复制
2022-03-19 11:29:59.954 ERROR 77692 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

An attempt was made to call a method that does not exist. The attempt was made from the following location:

    io.minio.S3Base.<clinit>(S3Base.java:98)

The following method did not exist:

    okhttp3.RequestBody.create([BLokhttp3/MediaType;)Lokhttp3/RequestBody;

The calling method's class, io.minio.S3Base, was loaded from the following location:

    jar:file:/Users/yunai/.m2/repository/io/minio/minio/8.3.7/minio-8.3.7.jar!/io/minio/S3Base.class

The called method's class, okhttp3.RequestBody, is available from the following locations:

    jar:file:/Users/yunai/.m2/repository/com/squareup/okhttp3/okhttp/3.14.9/okhttp-3.14.9.jar!/okhttp3/RequestBody.class

The called method's class hierarchy was loaded from the following locations:

    okhttp3.RequestBody: file:/Users/yunai/.m2/repository/com/squareup/okhttp3/okhttp/3.14.9/okhttp-3.14.9.jar


Action:

Correct the classpath of your application so that it contains compatible versions of the classes io.minio.S3Base and okhttp3.RequestBody

4.2 MinIOConfiguration

新建 MinIOConfiguration 配置类,创建 MinioClient Bean。代码如下:

代码语言:javascript复制
package cn.iocoder.springboot.lab72.config;

import io.minio.MinioClient;
import org.springframework.context.annotation.*;

@Configuration
public class MinIOConfiguration {

    @Bean
    public MinioClient minioClient() {
        // Minio 配置。实际项目中,定义到 application.yml 配置文件中
        String endpoint = "http://127.0.0.1:9000";
        String accessKey = "admin";
        String secretKey = "password";

        // 创建 MinioClient 客户端
        return MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
    }

}

4.3 FileController

新建 FileController 类,实现文件上传与删除的 RESTful API 接口。代码如下:

代码语言:javascript复制
package cn.iocoder.springboot.lab72.controller;

import io.minio.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.UUID;

@RestController
@RequestMapping("/file")
public class FileController {

    @Resource
    private MinioClient minioClient;

    // Minio 配置。实际项目中,定义到 application.yml 配置文件中
    private String endpoint = "http://127.0.0.1:9000";
    private String bucket = "yudaoyuanma";

    /**
     * 上传文件
     */
    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file) throws Exception {
        // 上传
        String path = UUID.randomUUID().toString(); // 文件名,使用 UUID 随机
        minioClient.putObject(PutObjectArgs.builder()
                .bucket(bucket) // 存储桶
                .object(path) // 文件名
                .stream(file.getInputStream(), file.getSize(), -1) // 文件内容
                .contentType(file.getContentType()) // 文件类型
                .build());
        // 拼接路径
        return String.format("%s/%s/%s", endpoint, bucket, path);
    }

    /**
     * 删除文件
     */
    @DeleteMapping("/delete")
    public void delete(@RequestParam("path") String path) throws Exception {
        minioClient.removeObject(RemoveObjectArgs.builder()
                .bucket(bucket) // 存储桶
                .object(path) // 文件名
                .build());
    }

}

4.4 MinIOApplication

新建 MinIOApplication 启动类。代码如下:

代码语言:javascript复制
package cn.iocoder.springboot.lab72;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MinIOApplication {

    public static void main(String[] args) {
        SpringApplication.run(MinIOApplication.class, args);
    }

}

4.5 简单测试

① 执行 MinIOApplication 启动 Spring Boot 项目。

② 使用 Postman 调用 /file/upload 接口,进行文件的上传。

上传文件

上传成功后,我们获得了文件的访问 URL 地址,可以使用浏览器直接访问。

访问文件

同时在 MinIO 后台界面,也可以查询到该文件。

文件

③ 使用 Postman 调用 /file/delete 接口,进行文件的删除。

删除文件

666. 彩蛋

未来是过去历史的一再重演,技术圈也是一样。

  • 2009 年,Oracle 公司收购 Sun,将 MySQL 收入囊中;同年,MySQL 之父 Widenius 离开 Sun,发布 MariaDB 产品。
  • 2011 年,RedHat 公司收购 Gluster,将 GlusterFS 纳入麾下;2014 年,Gluster 创始人发布 Minio 产品。

最后,推荐下艿艿在 https://github.com/YunaiV/ruoyi-vue-pro 实现的文件模块,支持 S3(MinIO、阿里云、腾讯云、华为云、七牛云等等)、磁盘、数据库等多种存储器。感兴趣的话,可以看看 https://doc.iocoder.cn/file 文档。



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

已在知识星球更新源码解析如下:

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

代码语言:javascript复制
文章有帮助的话,在看,转发吧。谢谢支持哟 (*^__^*)

0 人点赞