一、Minio介绍

Minio 是在 GNU Affero 通用公共许可证 v3.0 下发布的高性能对象存储。 它是与 Amazon S3 云存储服务兼容的 API。 非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。
Minio是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。

2、数据存储方式

Minio使用纠删码erasure code和校验码checksum。

纠删码是一种恢复丢失和损坏数据的数学算法, Minio采用Reed-Solomon code将对象拆分成N/2数据和N/2 奇偶校验块。 这就意味着如果是12块盘,一个对象会被 分成6个数据块、6个奇偶校验块,你可以丢失任意6块盘(不管其是存放的数据块还 是奇偶校验块),你仍可以从剩下的盘中的数据进行恢复

此种纠删码的数据恢复方式是对象级别的,恢复效率更高,速度更快。能够更好的提高性能和尽可能的使用硬件加速。

3、数据组织结构

对象: 类似于hash表中的表项:它的名字相当于关键字,它的内容相当于“值”。

桶: 是若干个对象的逻辑抽象,是盛装对象的容器。

租户: 用于隔离存储资源。在租户之下可以建立桶、存储对象。

用户: 在租户下面创建的用于访问不同桶的账号。可以使用MinIO提供的mc命令设置不用用户访问各个桶的权限。

在minio中支持多租户的访问模式

4、**minio的架构模式

minio是一个去中心化的无共享架构,,对象数据被打散存放在不同节点的多块硬盘,对外提供统一命名空间访问,并通过Web负载均衡器或DNS轮询(DNS round-robin)在各服务器之间实现负载均衡。

某个节点宕机后,并不会影响整体的使用,当宕机节点重启后,其他节点会自动重连此节点。

而统一的命名空间,决定了无论访问那一个节点,均可以采用一样的数据访问方式。

且文件自带分布式锁的管理,当获取n/2+1个节点的回应为“是”后,才能获取锁。(类似于读写锁,写锁仅能一个写入者获得)

5、**数据存储结构

文件存储于指定的bucket(桶)下,每个都会生成一个对象文件,其中包括了纠删文件和检查文件(用于存储和恢复文件信息)。同时集群会复制相关文件到各个节点的各个数据盘中。

文档地址 docs.minio.org.cn/docs/

docs.minio.org.cn/docs/master…

1、单机部署

1)下载及安装

wget dl.min.io/server/mini…

chmod +x minio

MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password ./minio server /mnt/data --console-address ":9001"

//注:可直接使用./minio server /data启动

nohup ./minio server   ./minio/data > /minio/data/minio.log 2>&1 &

2、集群部署

测试环境集群地址:192.168.0.5:9000    192.168.0.6:9000

#导入配置,账号密码需要一致,所有节点的

export MINIO_ACCESS_KEY=minioadmin

export MINIO_SECRET_KEY=minioadmin

#每个节点都需要配置文件夹,且必须是空的,每个节点都得运行此命令,注意每个节点的minio版本得一致(加& 后台启动)

./minio server http://192.168.0.5/home/minio/data6 http://192.168.0.5/home/minio/data7 http://192.168.0.5/home/minio/data1 http://192.168.0.5/home/minio/data8]http://192.168.0.5/home/minio/data2 http://192.168.0.5/home/minio/data9 http://192.168.0.6/home/minio/data6 http://192.168.0.6/home/minio/data7 http://192.168.0.5/home/minio/data1 http://192.168.0.6/home/minio/data8 http://192.168.0.5/home/minio/data2 http://192.168.0.6/home/minio/data9 > /home/minio/minio.log --console-address ":9001" 2>&1 &

在minio中,有几个概念:

1)account

这个会生成 access_key和secret_key 是用来调用minio接口的,无法使用api接口进行生成,且不可用此账户登录后台

2)user

用户信息,自己设定access_key和secret_key,可用于登录后台管理界面,可用于调用minio接口。此账户不可以用api接口生成

3)group

用户组,用户可以不设置权限,直接使用组权限,但不可以通过接口进行创建,也不能通过接口将用户加入用户组

4)buckets

桶,用于存储文件的一个分区。可以用api接口生成,且可修改策略,设置是否允许可读、可写。

user用户可与buckets绑定,用于操作此桶,user有自己设置的策略。

1、权限设置

1)每个app或者平台首先先申请minio平台的access_key和secret_key用于调用接口

2)根据登录的用户先查找自己是否有属于自己的buckets桶(用用户code+appcode做桶名),调用public boolean bucketExists(BucketExistsArgs args) 方法,判断桶是否存在,不存在就创建public void makeBucket(MakeBucketArgs args),其中objectLock表示桶是否私有

3)上传文件上传到自己的桶里面,不能放到别人的桶里。public ObjectWriteResponse putObject(PutObjectArgs args)

4)取文件:只能取自己的桶里的文件public GetObjectResponse getObject(GetObjectArgs args)

5)可以有一个系统账户的身份,可以取所有桶的文件

2、可以单独给桶设置策略

当操作的用户没有设置策略,且不属于某个组时,桶策略生效

用户的策略权限>组的策略权限>桶策略权限

3、用户不设置权限,组设置权限

给用户组设置权限,但是用户不单独设置读写策略,使用用户调用接口时,使用组的权限进行校验。

用户的策略权限>组的策略权限

4、桶Access Policy类型

1)public:文件可以直接用  ip:port/桶名/文件名   进行访问

2)private:文件需要通过minioClient.getPresignedObjectUrl接口获取一个有使用期限的地址,默认七天(最大七天)

3)可以通过装客户端应用,使用命令配置桶的权限:

./mc config host add minio http://ip:port 【access_key】 【secret_key】

./mc  policy  set  【需要的权限,如download  下载   public  共有】  minio/【bucketName】  //设置需要开放下载的bucket, 注意需要带minio   浏览器访问, 注意不需要带minio

5、policy的内容格式

"Version" : "2012-10-17" , //版本,固定的版本
"Id" : "ExamplePolicy01" , //策略id
"Statement" :[ //策略描述主体内容
"Sid" : "ExampleStatement01" , //描述id
"Effect" : "Allow" , //Allow允许  Deny禁止
"Principal" :{
"AWS" : "arn:aws:iam::123456789012:user/Dave" //被允许访问语句中的操作和资源的帐户或用户。在存储桶策略中,委托人是作为此权限接收者的用户、账户、服务或其他实体  格式:arn:aws:iam:: account-number-without-hyphens :user/ username
"Action" :[   //行为没操作
"s3:GetObject" ,//获取文件对象信息

"s3:PutObject", //上传文件对象

"s3:DeleteObject", //删除文件对象

"s3:ListBucketMultipartUploads", //获取桶中所有的存储对象

"s3:ListMultipartUploadParts", //获取桶中所有部分上传的存储对象
"s3:ListBucket" //获取所有的存储桶

"Condition" :{ //条件限制 StringEquals  StringNotEquals  StringLike StringNotLike IpAddress NotIpAddress
"IpAddress" :{
"aws:SourceIp" : "192.0.2.0/24"
"NotIpAddress" :{
"aws:SourceIp" : "192.0.2.188/32"
"Resource" :[
"arn:aws:s3:::awsexamplebucket1/" , //资源arn:partition:service:region:namespace:relative-id 如例:操作awsexamplebucket桶中的对象资源
"arn:aws:s3:::awsexamplebucket1"

详细可参考: docs.aws.amazon.com/AmazonS3/la…

四、实现方案设计

1、流程图

2、逻辑梳理

1)minio的用户权限和桶权限(策略)都是针对外部访问minio限定的,无法实际控制业务端的处理。此部分需要业务端自我完善,遂加表dy_file用于存储文件信息

2)每个平台(或应用)层级的创建两个桶,一个public桶,一个private桶。

公有桶里的文件通过:ip:port/文件名称  可以直接访问到

私有通的文件只能通过:presignedGetObject获取临时的访问地址,或者使用有权限的user进行下载访问

3)过大的文件,整体传递到服务端会消耗大量内存(如:2G的飞车apk安装包),但是可以通过presignedPutObject方法生成一个临时上传地址,客户端可使用这个地址直接访问minio服务进行上传,不经过服务端上传。

4)可以设置桶规则,限定此桶只能开放给那个用户使用( "AWS" : "arn:aws:iam::123456789012:user/Dave" ),从而在后期,对外开放能力,使每个平台可以使用自己的账户进行维护文件信息。

1)用户上传文件,通过不同的接口标识上传的文件是上传到public桶还是private桶(桶名:平台code/应用code - public/private)

2)每个用户的文件在桶下建立一个文件夹,文件名为:用户code

3)上传完成后的文件统一返回文件code保存,若有特殊要求,可返回文件地址(私有的生成临时访问地址)

4、代码实现

1)创建minio客户端对象

MinioClient minioClient = MinioClient.builder().endpoint(server).credentials(accessKey, secretKey).build();

2) 判断桶是否存在

boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketTemp).build());

3) 创建桶

minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketTemp).objectLock(true).build());

4) 上传文件

minioClient.putObject(PutObjectArgs
.builder()
.bucket(bucketTemp)
.object("多层级的目录可以用这样的方式:first/second/"+newFileName)
.stream(file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType())
.build());

5) 下载文件

InputStream stream =

minioClient.getObject(

GetObjectArgs.builder()

.bucket("my-bucketname")

.object("my-objectname")

.offset(offset)

.length(len)

.ssec(ssec)

.build()

6) 设置桶策略

String config="{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":[" "]},"Action":["s3:GetObject"],"Resource":["arn:aws:s3:::"+bucketsName+"/ "]}]}\n";
minioClient.setBucketPolicy( SetBucketPolicyArgs.builder().bucket(bucketsName).config(config).build());

7) 查询桶策略

String config =  minioClient.getBucketPolicy(GetBucketPolicyArgs.builder().bucket(bucketsName).build());

8) 临时访问文件的地址

String url =  minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketsName)
.object(objectName)
.expiry(2, TimeUnit.DAYS)
.build());

9) 临时上传文件的地址

Map<String, String> reqParams = new HashMap<String, String>();
reqParams.put("response-content-type", "application/json");
String url =  minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.PUT)
.bucket(bucketsName)
.object(objectName)
.expiry(1, TimeUnit.DAYS)
.extraQueryParams(reqParams)
.build());

1、 桶名名称规则

l 存储桶名称的长度必须介于 3 到 63 个字符之间。

l 存储桶名称只能由小写字母、数字、点 (.) 和连字符 (-) 组成。

l 存储桶名称必须以字母或数字开头和结尾。

l 存储桶名称不得格式化为 IP 地址(例如,192.168.5.4)。

l 存储桶名称不得以前缀 开头xn--。

l 存储桶名称不得以后缀 结尾-s3alias。此后缀是为接入点别名保留的。有关更多信息,请参阅 为访问点使用存储桶式别名

l Bucket 名称在一个分区内必须是唯一的。分区是一组 Region。AWS 目前有三个分区:(aws标准区域)、 aws-cn(中国区域)和aws-us-gov(AWS GovCloud [美国] 区域)。

l 与 Amazon S3 Transfer Acceleration 一起使用的存储桶的名称中不能包含点 (.)

2、 遇到的问题

Q1:导入配置的方法

A1:使用export MINIO_ACCESS_KEY=<ACCESS_KEY  export MINIO_SECRET_KEY=<SECRET_KEY> 命令可以设置默认的access_key和secret_key

在/root/.minio目录下,创建config.json的文件,内容为

"version": "10",

"aliases": {

"local": {

"url": " http://localhost:9000 ",

"accessKey": "",

"secretKey": "",

"api": "S3v4",

"path": "auto"

Q2:集群模式下的存储盘的创建

A2:在命令后面加&进行后台运行,但是集群运行时,需要每个盘都是空的,所以在外部创建一个同意的minio.log文件记录日志,这样每个盘都是空的,创建集群时不会报错

Q3:集群创建,不同节点之间连接不上

A3:当时两个节点的minio版本不一致,导致连接不上,重新下载后可连接

Q4:本地代码JVM内存不足,导致大文件(>1G时)本地无法完整的接取文件,导致JVM崩了

A4:可以使用接口生成一次性上传地址,这样可以直接从 客户端——>minio服务端进行文件传输,不用在经过业务服务端

Q5:桶策略、用户策略还有用户组策略的设置和生效优先级

A5:通过控制变量,设置不用权限的桶、用户、用户组得到结论:用户>用户组>桶策略

策略内容和设置基本一致,请参考policy的内容格式的内容

Q6:如何使部分文件可以直接对外访问,另外一部分有访问限制

A6:public属性策略的桶,可以直接使用服务的ip:port+文件地址访问   private的只能通过接口生成临时地址进行访问,最大有效期7天

Q7:断点续传和分片传输是否可以实现

A7:单个对象的最大大小限制在5TB。putObject在对象大于5MiB时,自动使用multiple parts方式上传。这样,当上传失败时,客户端只需要上传未成功的部分即可(类似断点上传)。

Q8:文件传输的大小和传输的速率

A8:单个文件最大可传输5TB的文件,功能强大。  效率:

通过接口传输:

5713ms(200M+的文件)

14608ms(450M+的文件)

客户端直接传输:

大概一分半钟(2GB文件)

Q9:文件存储格式及集群中的数据同步

A9:小文件只有一个xl.mate文件,包括了数据和纠偏码校验码     大文件会存在 数据片:part.1 和 xl.mate文件,且数据片被均分到不同的存储空间。在上传完文件后,集群个数据存储盘会同步相关数据,生成等分的校验块和数据块

且删除一般的内容后,数据正常访问,且可恢复(此处使用了8个盘,删除4个后,正常访问,删除5个后,文件无法访问)

Q10:设置minio的启动端口和后台端口

A10: --console-address=”:9001” 设置后台界面的端口   --address = “IP:PORT”设置访问端口

参考文章:

www.sohu.com/a/391960620…

blog.csdn.net/shijinghan1…

  •