• SpringBoot整合MinIO


    MinIO简介

    MinIO是一款基于Go语言开发的高性能、分布式的对象存储系统,开源可商用。一开始就被设计为服务于私有云、公有云、混合云,因此在高可用、可扩展性、高性能方面有得天独厚的优势。

    MinIO完全实现了AWS S3 标准,在日常使用、扩展升级、迁移方面更易于管理,对于上层应用程序来说,存储和访问对象是统一的,即使MinIO服务迁移了,应用程序侧是无感知的。

    MinIO分三个版本,开源版、标准版、企业版,开源版本免费使用,后面两个为付费产品。MinIO支持多种部署环境:Kubernetes、Docker、Linux、MacOS、Windows

    Amazon S3 标准

    S3简介

    AWS S3 全称是 Simple Storage Service

    =_=*

    所以就 S3 了? 3S更确切把?

    简单的存储服务规范,实际就是一种指导思想,然后大家都按照这种要求来。比如规范要求Bucket 的名称不可以带下划线。

    基本概念

    • Bucket:桶是最顶层的结构,所有的文件都必须放在桶中,桶的名称需要保持唯一,没有对象存储数量限制
    • Object:桶中放的数据就是对象,由对象名称和对象值组成,对象名称可以很长,并可以划分path,对象包含一些元数据,如文件类型、创建时间、用户指定的元信息,对象可以设置标签,标签也是键值对结构,可以修改,标签的作用是可以结合权限控制对象的访问、生命周期的管理、数据分析等,单个文件最大5GB,超过需要使用
      multipart upload API (最大支持5TB)

    Server端部署

    以 CentOS(amd64架构) 为例

    下载

    打开天朝专属下载地址,在 /server/minio/release/linux-amd64/ 目录下有一个minio文件,这个文件是一个可执行,下载这个文件放到服务器上面

    运行

    官方推荐rpm安装,这种在有互联网的时候很友好,但是无互联网的环境就很麻烦,哪怕可以搭建临时存储库还是麻烦。

    本文下载的是可执行文件,方便操作和演示将直接使用 nohup 方式运行。

    将下载好的minio可执行文件赋予执行权限,并移动到 /usr/local/bin/ 下,这样全局就都可以访问这个可执行文件了,相关命令为:

    
    //赋予执行权限
    chmod +x minio
    
    //移动到 /usr/local/bin/ 目录下
    sudo mv minio /usr/local/bin/
    
    

    运行之前,需要创建一个文件夹用来存储上传的文件,本文在 /root 下创建了一个名为 minio 的目录。

    
    mkdir ~/minio
    
    

    启动 MinIO-Server

    
    nohup minio  server  ~/minio --console-address :9090 & 
    
    

    确认是否启动成功

    启动输出信息:

    
    WARNING: Detected Linux kernel version older than 4.0.0 release, there are some known potential performance problems with this kernel version. MinIO recommends a minimum of 4.x.x linux kernel version for best performance
    WARNING: Detected default credentials 'minioadmin:minioadmin', we recommend that you change these values with 'MINIO_ROOT_USER' and 'MINIO_ROOT_PASSWORD' environment variables
    MinIO Object Storage Server
    Copyright: 2015-2023 MinIO, Inc.
    License: GNU AGPLv3 //www.gnu.org/licenses/agpl-3.0.html>
    Version: RELEASE.2023-09-04T19-57-37Z (go1.19.12 linux/amd64)
    
    Status:         1 Online, 0 Offline.
    S3-API: http://xxx:9000  http://127.0.0.1:9000
    Console: http://xxx:9090 http://127.0.0.1:9090
    
    Documentation: https://min.io/docs/minio/linux/index.html
    Warning: The standard parity is set to 0. This can lead to data loss.
    
    

    启动完毕会占用两个端口:

    • 9090:webui
    • 9000:S3API 地址,SpringBoot程序通过此地址和MinIOServer交互

    本文仅做演示,不对 MinIO-Server 部署做过多介绍,实际生产环境中,推荐使用高可用的部署架构,参见:https://min.io/docs/minio/linux/operations/install-deploy-manage/deploy-minio-multi-node-multi-drive.html#deploy-minio-distributed

    常用API

    MinIOClientBuilder

    • endpoint:接收一个url的串或者okhttp3.HttpUrl

    • credentials:用户名密码或者AccessKey

    • region:接受S3服务的区域名称。如果指定,则所有操作都使用此区域,否则将按存储桶探测区域。

    • httpClient:自定义HTTPclient , 默认为OkHttp

    Bucket操作

    • bucketExists:桶是否存在
    • listBuckets:列出所有的桶
    • makeBucket:创建一个桶
    • removeBucket:删除一个桶

    Object操作

    • getPresignedObjectUrl:获取对象访问url
    • putObject:上传对象
    • uploadObject:上传对象
    • removeObject:删除对象

    SpringBoot整合

    pom

    
    <dependency>
        <groupId>io.miniogroupId>
        <artifactId>minioartifactId>
        <version>8.2.2version>
    dependency>
    
    

    配置MinIO客户端

    其中 credentials 需要提前在WebUI中创建Identity-Users或者AccessKeys

    
    package com.ramble.minio.config;
    
    import io.minio.MinioClient;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class MinIoConfig {
        @Bean
        public MinioClient initMinioClient() {
            MinioClient client = MinioClient.builder()
                    .endpoint("http://192.168.1.46:9000")
                    //Identity-Users
    //                .credentials("test", "test123456")
                    //AccessKeys
                    .credentials("zh10tpbzJtZX77FtCHyy", "dGz6nXICMOKAvabOc7UyVYmKz2hAiOTfT76Jzu0M")
                    .build();
            return client;
        }
    }
    
    
    

    Service

    封装一个 MinIOService ,提供常用的接口服务

    
    package com.ramble.minio.service;
    
    import io.minio.*;
    import io.minio.http.Method;
    import io.minio.messages.Bucket;
    import io.minio.messages.Item;
    import lombok.RequiredArgsConstructor;
    import lombok.SneakyThrows;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Service;
    import java.util.ArrayList;
    import java.util.List;
    
    @Slf4j
    @Service
    @RequiredArgsConstructor
    public class MinioService {
    
        private final MinioClient minioClient;
        
        /**
         * 查看bucket是否存在
         *
         * @param bucketName
         * @return
         */
        @SneakyThrows
        public Boolean existsBucket(String bucketName) {
            return minioClient.bucketExists(BucketExistsArgs.builder()
                    .bucket(bucketName)
                    .build());
        }
        
        /**
         * 创建存储bucket
         *
         * @return Boolean
         */
        @SneakyThrows
        public void makeBucket(String bucketName) {
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        }
        
        /**
         * 删除存储bucket
         *
         * @return Boolean
         */
        @SneakyThrows
        public void removeBucket(String bucketName) {
            minioClient.removeBucket(RemoveBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        }
        
        /**
         * 获取全部bucket
         */
        @SneakyThrows
        public List listBuckets() {
            return minioClient.listBuckets();
        }
        
        /**
         * 获取文件的url
         *
         * @param fileName
         * @return
         */
        @SneakyThrows
        public String getUrl(String bucketName, String fileName) {
            GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(fileName).method(Method.GET).build();
            return minioClient.getPresignedObjectUrl(build);
        }
        
        /**
         * 查看文件对象
         *
         * @return 存储bucket内文件对象信息
         */
        @SneakyThrows
        public List listObjects(String bucketName) {
            Iterable> results = minioClient.listObjects(
                    ListObjectsArgs.builder().bucket(bucketName).build());
            List items = new ArrayList<>();
            for (Result result : results) {
                items.add(result.get());
            }
            return items;
        }
        
        /**
         * 删除
         *
         * @param fileName
         * @return
         * @throws Exception
         */
        @SneakyThrows
        public void remove(String bucketName, String fileName) {
            minioClient.removeObject(RemoveObjectArgs.builder().
                    bucket(bucketName)
                    .object(fileName)
                    .build());
        }
        
    }
    
    
    

    Controller

    新建一个controller,测试常用的接口

    
    package com.ramble.minio.controller;
    
    import com.ramble.minio.service.MinioService;
    import io.minio.BucketExistsArgs;
    import io.minio.MakeBucketArgs;
    import io.minio.MinioClient;
    import io.minio.UploadObjectArgs;
    import io.minio.errors.MinioException;
    import io.minio.messages.Bucket;
    import io.minio.messages.Item;
    import lombok.RequiredArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import java.io.IOException;
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.util.List;
    
    @Slf4j
    @RestController
    @RequestMapping("/test")
    @RequiredArgsConstructor
    public class TestController {
    
        private final MinioClient minioClient;
        
        private final MinioService minioService;
        
        @GetMapping("/test2")
        public void test2() {
            Boolean existsBucket = minioService.existsBucket("person");
            minioService.makeBucket("person");
            minioService.makeBucket("person2");
            minioService.removeBucket("person2");
            List buckets = minioService.listBuckets();
            String url = minioService.getUrl("first-bucket", "锁屏幻灯片/0028.jpg");
            List items = minioService.listObjects("first-bucket");
            minioService.remove("first-bucket", "Win11_22H2_Chinese_Simplified_x64v2.iso");
        }
       
    }
    
    
    

    引用


    __EOF__

  • 本文作者: 一颗苹果
  • 本文链接: https://www.cnblogs.com/Naylor/p/17698878.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    Dubbo安装部署
    期末前端web大作业——名侦探柯南网页制作 Hbuiderx制作网页 静态HTML网页单页制作 dreamweaver网页设计与制作代码 web前端期末大作业
    亚马逊平台的优势有哪些?
    JAVA计算机毕业设计毕业生信息管理系统Mybatis+源码+数据库+lw文档+系统+调试部署
    Redis3.2.12版本服务器迁移
    私有云OpenStack保姆级教学
    电脑桌面便签工具选择哪一款?
    家用AIO系统架构图(Openwrt 群晖 IPV6 DDNS)
    【虚拟机】根据已有IP获取当前网段的主机范围
    其他算法和思想的题目
  • 原文地址:https://www.cnblogs.com/Naylor/p/17698878.html