MinIO快速入门指南:构建自己的云存储服务
今日内容介绍,预计花费18分钟
云存储服务在现代应用中变得越来越重要,不仅对于数据备份和恢复,还对于大数据分析、静态网站托管等应用。而MinIO是一个开源的云存储服务器,它可以帮助你快速构建自己的云存储服务,无论是私有云还是公有云。
分布式文件系统(存储)方案:
云服务:
-
阿里云OSS -
七牛云 -
腾讯云存储 -
华为云存储
私有化服务:
-
阿里的FastDFS -
MinIO
私有化服务存储方式 | 优点 | 缺点 |
---|---|---|
FastDFS | 1.主备服务,高可用 2.支持主从文件,支持自定义扩展名 3.支持动态扩容 |
1.没有完备官方文档,近几年没有更新 2.环境搭建较为麻烦 |
MinIO | 1.性能高,准硬件条件下它能达到55GB/s的读、35GB/s的写速率 2.部署自带管理界面 3.MinIO.Inc运营的开源项目,社区活跃度高 4.提供了所有主流开发语言的SDK |
1,不支持动态增加节点 |
1. 什么是MinIO
MinIO基于Apache License v2.0开源协议的对象存储服务,可以为云存储的解决方案用来保存海量的图片,视频,文档。由于采用Golang实现,服务端可以工作在Windows,Linux, OS X和FreeBSD上。配置简单,基本是复制可执行程序,单行命令可以运行起来。
MinIO兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。
S3 ( Simple Storage Service简单存储服务)
MinIO基本概念:
-
bucket – 类比于文件系统的目录 -
Object – 类比文件系统的文件 -
Keys – 类比文件名
1.1.MinIO特点
-
数据保护:Minio使用Minio Erasure Code(纠删码)来防止硬件故障。即便损坏一半以上的driver,但是仍然可以从中恢复。
-
高性能:作为高性能对象存储,在标准硬件条件下它能达到55GB/s的读、35GB/s的写速率
-
可扩容:不同MinIO集群可以组成联邦,并形成一个全局的命名空间,并跨越多个数据中心
-
SDK支持:基于Minio轻量的特点,它得到类似Java、Python或Go等语言的sdk支持
-
有操作页面:面向用户友好的简单操作界面,非常方便的管理Bucket及里面的文件资源
-
功能简单:这一设计原则让MinIO不容易出错、更快启动
-
丰富的API:支持文件资源的分享连接及分享链接的过期策略、存储桶操作、文件列表访问及文件上传下载的基本功能等。
-
文件变化主动通知:存储桶(Bucket)如果发生改变,比如上传对象和删除对象,可以使用存储桶事件通知机制进行监控,并通过以下方式发布出去:AMQP、MQTT、Elasticsearch、Redis、NATS、MySQL、Kafka、Webhooks等。
2. Docker-Compose安装MinIO
【步骤一】:创建项目目录
mkdir -p /mydata/minio/data
mkdir -p /mydata/minio/minio
mkdir -p /mydata/minio/config
【步骤二】:配置MinIO的Docker Compose 配置文件docker-compose-minio.yml
# 可参考 https://docs.min.io/docs/minio-docker-quickstart-guide.html
version: '3'
services:
minio:
image: minio/minio:latest # 原镜像`minio/minio:latest`
container_name: minio # 容器名为'minio'
restart: unless-stopped # 指定容器退出后的重启策略为始终重启,但是不考虑在Docker守护进程启动时就已经停止了的容器
volumes: # 数据卷挂载路径设置,将本机目录映射到容器目录
- "/mydata/minio/data:/data"
- "/mydata/minio/minio:/minio"
- "/mydata/minio/config:/root/.minio"
environment: # 设置环境变量,相当于docker run命令中的-e
TZ: Asia/Shanghai
LANG: en_US.UTF-8
MINIO_PROMETHEUS_AUTH_TYPE: "public"
MINIO_ACCESS_KEY: "root" # 登录账号
MINIO_SECRET_KEY: "password" # 登录密码
command: server /data --console-address ":9001"
logging:
driver: "json-file"
options:
max-size: "100m"
ports: # 映射端口
- "9001:9001"
- "42330:42330"
- "9000:9000"
【步骤三】:通过docker-compose启动minio
docker-compose -f docker-compose-minio.yml -p minio up -d
注意:该命令和docker-compose-minio.yml在同级目录
【步骤四】:访问管理控制台
我们设置的对外访问端口是9001,在浏览器输入ip:9001
进行访问
http://192.168.150.102:9001
我们设置的账户密码 为 root/password
【步骤五】:创建一个桶
【步骤六】:设置bucket (桶)访问权限
将同的私有权限改为public
【步骤七】:点击进去可以上传文件
【步骤八】:访问上传文件
上传完成后可以通过地址+桶名+文件名访问注意:端口不是9001而是9000
http://192.168.150.102:9000/zbbmeta/test.jpg
3. SpringBoot快速入门Minio
【步骤一】创建项目
创建minio-learn,并导入对应依赖到pom.xml
-
完整项目结果
-
pom.xml 依赖
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.7.15</version>
</parent>
<groupId>com.zbbmeta</groupId>
<artifactId>minio-learn</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
</dependencies>
</project>
【步骤一】创建项目引导类
在java目录下创建com.zbbmeta.minio
包,在其包下创建MinIOApplication
引导类
package com.zbbmeta.minio;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author springboot葵花宝典
* @description: TODO
*/
@SpringBootApplication
public class MinIOApplication {
public static void main(String[] args) {
SpringApplication.run(MinIOApplication.class, args);
}
}
【步骤二】配置文件
在resources
目录下创建application.yml
文件,内容如下
server:
port: 8001
minio:
endpoint: http://192.168.150.102:9000
accessKey: root
secretKey: password
bucketName: zbbmeta # 你的是什么 这里就写什么
【步骤三】 配置读取类
在com.zbbmeta.minio.property
包下创建MinIOProperties
类,用于读取minio信息
package com.zbbmeta.minio.property;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author springboot葵花宝典
* @description: TODO
*/
@Data
@ConfigurationProperties(prefix = "minio")
public class MinIOProperties {
private String endpoint;
private String accessKey;
private String secretKey;
private String bucketName;
}
【步骤四】 配置MinioClient类
package com.zbbmeta.minio.config;
import com.zbbmeta.minio.property.MinIOProperties;
import io.minio.MinioClient;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author springboot葵花宝典
* @description: TODO
*/
@Configuration
@EnableConfigurationProperties(MinIOProperties.class)
public class MinIOConfig {
@Bean
public MinioClient minioClient(MinIOProperties minIOProperties){
MinioClient minioClient = MinioClient.builder()
.endpoint(minIOProperties.getEndpoint())
.credentials(minIOProperties.getAccessKey(), minIOProperties.getSecretKey())
.build();
return minioClient;
}
}
【步骤五】 创建Minio的Service服务类
在com.zbbmeta.minio.service
包下创建MinIOService
类
package com.zbbmeta.minio.service;
import com.zbbmeta.minio.property.MinIOProperties;
import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.UUID;
/**
* @author springboot葵花宝典
* @description: TODO
*/
@Service
public class MinIOService {
@Autowired
private MinioClient minioClient;
@Autowired
private MinIOProperties properties;
/**
* 上传文件
* @param file
* @return
*/
public String upload(MultipartFile file) {
// 原文件名
String originalFilename = file.getOriginalFilename();
// 获取文件的后缀
String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
// 构造新的文件名,名字不重复
String objectName = UUID.randomUUID().toString() + suffix;
// 上传文件
try {
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.contentType(file.getContentType())
.stream(file.getInputStream(), file.getSize(), -1)
.bucket(properties.getBucketName())
.object(objectName)
.build();
minioClient.putObject(putObjectArgs);
} catch (Exception e) {
throw new RuntimeException("上传文件失败: " + e.getMessage());
}
return properties.getEndpoint() + "/" + properties.getBucketName() + "/" + objectName;
}
/**
* 上传文件
* @param name
* @param inputStream
* @param contentType
* @return
*/
public String upload(String name,InputStream inputStream,String contentType){
// 上传文件
try {
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.contentType(contentType)
.stream(inputStream, inputStream.available(), -1)
.bucket(properties.getBucketName())
.object(name)
.build();
minioClient.putObject(putObjectArgs);
} catch (Exception e) {
throw new RuntimeException("上传文件失败: " + e.getMessage());
}
return properties.getEndpoint() + "/" + properties.getBucketName() + "/" + name;
}
/**
* 删除文件
* @param url
*/
public void delete(String url){
String objectName = url.replace(properties.getEndpoint()+"/","")
.replace(properties.getBucketName()+"/","");
RemoveObjectArgs args = RemoveObjectArgs.builder()
.bucket(properties.getBucketName())
.object(objectName)
.build();
try {
minioClient.removeObject(args);
} catch (Exception e) {
throw new RuntimeException("删除文件失败: " + e.getMessage());
}
}
/**
* 下载文件
* @param url
* @return
*/
public InputStream download(String url){
String objectName = url.replace(properties.getEndpoint()+"/","")
.replace(properties.getBucketName()+"/","");
GetObjectArgs args = GetObjectArgs.builder()
.bucket(properties.getBucketName())
.object(objectName)
.build();
InputStream inputStream = null;
try {
inputStream = minioClient.getObject(args);
} catch (Exception e) {
throw new RuntimeException("下载文件失败: " + e.getMessage());
}
return inputStream;
}
}
【步骤六】 创建Minio的FileController接口类
在com.zbbmeta.minio.controller
包下创建FileController接口类
package com.zbbmeta.minio.controller;
import com.zbbmeta.minio.service.MinIOService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
* @author springboot葵花宝典
* @description: TODO
*/
@RestController
@RequestMapping("/minio/file")
public class FileController {
@Autowired
private MinIOService minIOService;
@PostMapping("/upload")
public ResponseEntity<String> upload(MultipartFile file) {
String url = minIOService.upload(file);
return ResponseEntity.ok(url);
}
@DeleteMapping
public ResponseEntity delete(String url) {
minIOService.delete(url);
return ResponseEntity.ok("删除成功");
}
}
【步骤七】 使用postman测试
-
上传测试
-
删除测试
4. minio 上传文件失败报错
如果报以下错误:
The difference between the request time and the server‘s time is too large.
原因:linux服务器时区的问题(因为虚拟机挂起后,时间也就停了)
解决方案:
-
-
查看系统时间、硬件时间
# date // 查看系统时间
#hwclock // 查看硬件时间
-
2.时间服务器上的时间同步的方法 安装ntpdate工具
# yum -y install ntp ntpdate
-
3.设置系统时间与网络时间同步
# ntpdate cn.pool.ntp.org
-
4.将系统时间写入硬件时间
hwclock --systohc
原文始发于微信公众号(springboot葵花宝典):MinIO快速入门指南:构建自己的云存储服务
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/182696.html