对象存储可以说是存储界备受瞩目的“网红”选手。谈到对象存储,不能不提及“桶”(Bucket)和“对象”(Object)这两个概念。对象包含数据和元数据,每个对象都有一个唯一的“身份码”(对象ID)和“接入码”(Key),只有当“码”经过认证后,才能通过基于http协议的RESTful接口进行访问。不同于块存储和文件存储,对象是存在“桶”里的,桶就像万能的“百宝袋”,支持文件、照片、视频等不同类型的对象,而且再多的数据都能装得下。
一、Minio 介绍
MinIO 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。
- MinIO 提供高性能、与S3 兼容的对象存储系统,让你自己能够构建自己的云储存服务。
- MinIO原生支持Kubernetes,它可用于每个独立的公共云、每个 Kubernetes 发行版、私有云和边缘的对象存储套件。
- MinIO是软件定义的,不需要购买其他任何硬件,在 GNU AGPL v3 下是 100% 开源的。
二、Minio 安装(docker)
1、拉取最新版的Minio镜像: docker pull minio/minio:latest
2、创建存放Minio必要配置的文件目录
# 创建根目录minio
mkdir -p /data/minio
# 创建用于存放Minio外部挂载的配置文件目录和存储上传文件的目录
mkdir -p /data/minio/{data,config}
3、创建Minio容器并运行
首先关闭防火墙或者放行9000和9001端口,然后运行下面命令部署minio,用户名为:admin,密码为:minio123!
docker run -p 9000:9000 -p 9001:9001 \
-d --restart=always --user=root --privileged=true \
-e "MINIO_ROOT_USER=admin" \
-e "MINIO_ROOT_PASSWORD=minio123!" \
-v /data/minio/data:/data \
-v /data/minio/config:/root/.minio \
--name=minio minio/minio server /data --console-address ":9001" --address ":9000"
4、访问 http//:ip:9000,查看minio首页,使用之前定义的用户名和密码进行登录
5、创建访问密钥
三、Go 客户端配置minio
1、安装依赖
go get github.com/minio/minio-go
2、初始化minio
根据实际环境来修改下面初始化minio的相关参数,minioAccessKey和minioSecretKey是之前在web界面创建的访问密钥。
首先声明了一些变量用于设置MinIO连接的相关参数。其中"minioUrl"表示MinIO服务的URL地址,"minioPort"表示MinIO服务的端口号,"minioAccessKey"和"minioSecretKey"分别表示访问MinIO服务的Access Key和Secret Key。
然后,通过调用minio.New方法创建了一个MinIO客户端的实例"minioClient"。在创建客户端时,传入了MinIO服务的地址和端口号,并使用credentials.NewStaticV4方法创建了一个静态的认证凭证对象,其中包含了Access Key和Secret Key。
如果连接过程中发生错误,将通过log.Fatalln方法打印错误信息并退出程序。否则,打印"minio服务初始化完成!"的日志信息,并返回nil表示没有发生错误。
package main
import (
"context"
"fmt"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"log"
"net/url"
"strconv"
"time"
)
var minioClient *minio.Client // 定义全局的 MinIO 客户端对象
// 初始化minio
func InitMinio() (err error) {
minioUrl := ""
minioPort := "9000"
minioAccessKey := ""
minioSecretKey := ""
// 根据配置文件连接minio
minioClient, err = minio.New(minioUrl+":"+minioPort, &minio.Options{Creds: credentials.NewStaticV4(minioAccessKey, minioSecretKey, "")})
if err != nil {
log.Fatalln("minio服务连接失败:", err.Error())
}
log.Println("minio服务初始化完成!")
return nil
}
3、创建存储桶
在创建存储桶的之前,我们需要通过minioClient.BucketExists() 方法判断存储桶是否已经存在,如果存储桶已经存在,则代码提示用户存储桶已经存在了,跳过创建过程,如果不存在,则可以通过minioClient.MakeBucket()来创建我们需要的存储桶
// 判断存储桶是否存在
bucketName := ""
location := ""
var b bool
b, err = minioClient.BucketExists(context.Background(), bucketName)
if err != nil {
log.Fatalln("存储桶判断是否存在失败:", err.Error())
}
if b {
return nil
} else {
// 存储桶不存在
err = minioClient.MakeBucket(context.Background(), bucketName, minio.MakeBucketOptions{Region: location})
if err != nil {
log.Fatalln("存储桶创建失败:", err)
}
log.Println("存储桶创建成功!")
}
4、上传文件
需要接收4个参数::minioClient(MinIO客户端实例)、bucketName(桶名称)、objectName(对象名称)和filePath(文件路径),并返回两个值:objectURL(对象的访问链接)和err。
首先我们声明了一些变量用于设置MinIO连接的相关参数。其中"minioUrl"表示MinIO服务的URL地址,"minioPort"表示MinIO服务的端口号。
然后,通过调用minioClient的FPutObject方法将指定的文件(filePath)上传到指定的桶(bucketName)中,并指定对象的名称(objectName)。上传操作使用了context.Background()作为上下文,并且没有设置额外的上传选项(minio.PutObjectOptions{})。
如果上传过程中发生错误,将通过log.Fatalln方法打印错误信息并退出程序。
接着,根据MinIO服务的地址、端口号、桶名称和对象名称构建了对象的访问链接(objectURL)。使用fmt.Sprintf方法将这些参数拼接成一个URL,并通过url.PathEscape对对象名称进行转义,以确保URL的正确性。
最后,返回对象的访问链接(objectURL)和nil表示没有发生错误。
// 上传文件
func uploadObject(minioClient *minio.Client, bucketName, objectName, filePath string) (objectURL string, err error) {
minioUrl := ""
minioPort := "9000"
_, err = minioClient.FPutObject(context.Background(), bucketName, objectName, filePath, minio.PutObjectOptions{})
if err != nil {
log.Fatalln("文件上传失败:", err.Error())
}
// 返回文件链接
objectURL = fmt.Sprintf("http://%s:%s/%s/%s", minioUrl, minioPort, bucketName, url.PathEscape(objectName))
return objectURL, nil
}