1. 对象存储服务MinIO
1.1 MinIO简介
MinIO基于Apache License v2.0开源协议的对象存储服务,可以做为云存储的解决方案用来保存海量的图片,视频,文档。由于采用Golang实现,服务端可以工作在Windows,Linux, OS X和FreeBSD上。配置简单,基本是复制可执行程序,单行命令可以运行起来。
MinIO兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。
S3 ( Simple Storage Service简单存储服务)
基本概念
- bucket – 类比于文件系统的目录
- Object – 类比文件系统的文件
- Keys – 类比文件名
官网文档:http://docs.minio.org.cn/docs/
1.2 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等。
1.3 开箱使用
1.3.1 安装启动
我们提供的镜像中已经有minio的环境,并自动启动。
我们可以使用docker-compose进行环境部署和启动,docker-compose.yml文件内容如下:
version: "3"
services:
minio:
image: minio/minio:RELEASE.2020-08-26T00-00-49Z
container_name: minio
privileged: true
volumes:
- /root/common/data/minio/data:/data
ports:
- "9001:9000"
environment:
MINIO_ACCESS_KEY: minio
MINIO_SECRET_KEY: minio123
command: server /data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
在docker-compose.yml所在目录下执行命令
docker-compose up
1.3.2 管理控制台
假设我们的服务器地址为192.168.200.128,我们在地址栏输入:http://192.168.200.128:9001/ 即可进入登录界面。
Access Key为minio Secret_key 为minio123 进入系统后可以看到主界面
点击右下角的“+”号 ,点击下面的图标,创建一个桶
输入桶名称
1.4 代码解析
以下代码来自lkd_vms_service(售货机微服务)
(1)在该项目中pom.xml添加以下依赖:
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>7.1.0</version>
</dependency>
(2)在售货机服务配置里添加MinIO配置节如下内容:
minio:
accessKey: minio
secretKey: minio123
bucket: lkd
endpoint: http://192.168.200.128:9001
readPath: http://192.168.200.128:9001
(3)配置映射类MinIOConfig
package com.lkd.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties("minio")
@Data
public class MinIOConfig {
private String accessKey;
private String secretKey;
private String bucket;
private String endpoint;
private String readPath;
}
(4)在lkd_vms_service
项目中新增包名com.lkd.file
,在该包下创建文件管理类,用来接受并存储文件:
package com.lkd.file;
import com.lkd.config.MinIOConfig;
import com.lkd.exception.LogicException;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
@Slf4j
@Component
public class FileManager {
@Autowired
private MinIOConfig minIOConfig;
/**
* 上传文件到MinIO
* @param file
* @throws NoSuchAlgorithmException
* @throws IOException
* @throws InvalidKeyException
*/
public String uploadFile(MultipartFile file) {
try {
MinioClient minioClient = buildMinioClient();
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.object(file.getOriginalFilename())
.contentType(file.getContentType())
.stream(file.getInputStream(),file.getSize(),-1) // partSize -1表示整体(不分片)上传
.bucket(minIOConfig.getBucket())
.build();
minioClient.putObject(putObjectArgs);
StringBuilder sbPhotoPath = new StringBuilder(minIOConfig.getReadPath());
sbPhotoPath.append(file.getOriginalFilename());
return sbPhotoPath.toString();
}catch (Exception ex){
log.error("minio put file error.",ex);
throw new LogicException("上传文件失败");
}
}
private MinioClient buildMinioClient(){
return MinioClient
.builder()
.credentials(minIOConfig.getAccessKey(),minIOConfig.getSecretKey())
.endpoint(minIOConfig.getEndpoint())
.build();
}
}
(5)修改原来SkuController
中的文件上传的方法uploadSkuImage
,调用FileManager
的方法如下:
/**
* 文件上传
* @param file
* @return
*/
@PostMapping(value = "/fileUpload")
@ResponseBody
public String uploadSkuImage(@RequestParam("fileName") MultipartFile file){
return fileManager.uploadFile(file);
}
1.5 测试
1.5.1 postman测试文件上传
1.5.2 常见错误
如果上传失败,显示的错误是
io.minio.errors.ErrorResponseException: The difference between the request time and the server’s time is too large.(请求时间和当前时间之间的差异太大)
那是由于当前的服务器时间不同步的问题,具体解决方法:
时间服务器上的时间同步的方法
(1)安装ntpdate工具
# yum -y install ntp ntpdate
(2)设置系统时间与网络时间同步
# ntpdate cn.pool.ntp.org
(3)将系统时间写入硬件时间
# hwclock --systohc