由于设定了自己关注自己,因此关注数和粉丝数都减一 在查询粉丝关注好友列表时,也排除自己
4个服务暴露出8个端口,采用nginx反向代理,统一在9000端口监听,再通过请求的路径来转发到对应的端口
七牛云流量超额了,打算使用minIO,搭建自己的分布式对象存储
MinIO
MinIO 是一个开源的对象存储服务器,它是一个高性能、分布式的存储系统,专门用于存储大规模的非结构化数据,如图片、视频、日志文件等。MinIO 具有以下特点:
- 对象存储:MinIO 是一个对象存储系统,它以对象(Object)的形式存储数据。每个对象可以是任意类型的文件,如图像、视频、文档等。
- 分布式架构:MinIO 可以以分布式的方式部署,可以跨多台服务器组成集群,实现数据的分布式存储和高可用性。
- 高性能:MinIO 设计用于提供高吞吐量、低延迟的数据存储和检索。它可以利用现代硬件和网络基础设施,实现高效的数据传输和处理。
- 开源:MinIO 是一个开源项目,代码开放,社区活跃。这使得用户可以根据自己的需求进行定制和扩展。
- 兼容性:MinIO 实现了 Amazon S3 协议,这意味着你可以使用 S3 协议来上传、下载和管理数据。这也使得 MinIO 可以兼容各种支持 S3 协议的工具和应用。
- 安全性:MinIO 支持数据加密、访问控制策略、预签名URL 等安全机制,可以确保数据的保密性和完整性。
- 轻量级部署:MinIO 的部署和管理相对轻量级,你可以在本地或云上快速搭建一个存储服务。
- 多种用途:MinIO 可以用于多种场景,包括备份、归档、数据湖、内容分发等。
MinIO 的架构和功能使其成为存储海量数据的理想选择,尤其适用于需要高性能、分布式和可扩展的存储解决方案。无论是个人开发者还是企业,都可以使用 MinIO 来构建强大的数据存储和管理系统。
本机创建minIO服务器
docker pull minio/minio:RELEASE.2021-06-17T00-10-46Z
docker run -p 9000:9000 --name minio -e "MINIO_ACCESS_KEY=taozixun" -e "MINIO_SECRET_KEY=taozixun" -v D:\test2\minio\data:/data -v D:\test2\minio\config:/root/.minio minio/minio:RELEASE.2021-06-17T00-10-46Z server /data
快速上传及生成访问链接
import (
"bytes"
"context"
"doushen_by_liujun/internal/common"
"fmt"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"log"
"math"
"time"
)
func Upload(ctx context.Context, video []byte, fileName string) error {
useSSL := false
//初始化客户端
client, _ := minio.NewCore(common.UploadPath, &minio.Options{
Creds: credentials.NewStaticV4(common.MinIOAccessKey, common.MinIOSecretKey, ""),
Secure: useSSL,
})
//检查桶是否存在,不存在就创建
exists, _ := client.BucketExists(ctx, common.MinIOBucketName)
if !exists {
_ = client.MakeBucket(ctx, common.MinIOBucketName, minio.MakeBucketOptions{})
}
//设置成公开访问
policy := `{"Version": "2012-10-17","Statement": [{"Action": ["s3:GetObject"],"Effect": "Allow","Principal": {"AWS": ["*"]},"Resource": ["arn:aws:s3:::` + common.MinIOBucketName + `/*"],"Sid": ""}]}`
_ = client.SetBucketPolicy(ctx, common.MinIOBucketName, policy)
if len(video) <= 5*1024*1024 {
// 文件大小小于等于 5MB,直接上传整个视频
_, err = client.PutObject(ctx, common.MinIOBucketName, fileName, bytes.NewReader(video), int64(len(video)), "", "", minio.PutObjectOptions{ContentType: "video/mp4"})
if err != nil {
return err
}
} else {
// 文件大小大于 5MB,使用分片上传
err = uploadInParts(ctx, client, video, common.MinIOBucketName, fileName)
if err != nil {
return err
}
}
//文件形式上传
//_, err = client.FPutObject(ctx, bucketName, fileName, filePath, minio.PutObjectOptions{})
log.Println("文件访问地址为")
objectURL := "http://" + common.UploadPath + "/" + common.MinIOBucketName + "/" + fileName
log.Println(objectURL)
return nil
}
func uploadInParts(ctx context.Context, client *minio.Core, videoData []byte, bucketName, fileName string) error {
partSize := int64(5 * 1024 * 1024) // 5MB
totalParts := int(math.Ceil(float64(len(videoData)) / float64(partSize)))
// 开始分片上传
uploadID, err := client.NewMultipartUpload(ctx, bucketName, fileName, minio.PutObjectOptions{ContentType: "video/mp4"})
if err != nil {
return err
}
var uploadedParts []minio.CompletePart
for partNumber := 1; partNumber <= totalParts; partNumber++ {
start := (partNumber - 1) * int(partSize)
end := int64(start) + partSize
if end > int64(len(videoData)) {
end = int64(len(videoData))
}
partData := videoData[start:end]
// 上传分片
part, err := client.PutObjectPart(ctx, common.MinIOBucketName, fileName, uploadID, partNumber, bytes.NewReader(partData), int64(len(partData)), minio.PutObjectPartOptions{})
if err != nil {
return err
}
uploadedParts = append(uploadedParts, minio.CompletePart{PartNumber: partNumber, ETag: part.ETag})
}
// 完成分片上传
_, err = client.CompleteMultipartUpload(ctx, bucketName, fileName, uploadID, uploadedParts, minio.PutObjectOptions{ContentType: "video/mp4"})
if err != nil {
return err
}
fmt.Printf("Uploaded %s using multipart upload\n", fileName)
return nil
}
其中公开访问策略 JSON 代码段的含义解释如下:
-
"Version": "2012-10-17":策略语法版本。 -
"Statement":策略陈述部分的开始。"Action": ["s3:GetObject"]:允许的操作是从存储桶中获取对象。"Effect": "Allow":允许指定的操作。"Principal": {"AWS": ["*"]}:设置允许的主体。"AWS": ["*"]表示允许任何主体。"Resource": ["arn:aws:s3:::+ bucketName +/*"]:指定适用的资源,这里是存储桶中的所有对象。"Sid": "":陈述的唯一标识符。
最后,通过调用 client.SetBucketPolicy(context.Background(), bucketName, policy) 来将策略应用到存储桶。
如果前端传来的视频是字节流格式
videoData := []byte{} // 将您的视频数据填充在这里
// 将 []byte 数据上传到
MinIO n, err := minioClient.PutObject(context.Background(), bucketName, objectName, bytes.NewReader(videoData), int64(len(videoData)), minio.PutObjectOptions{})
MinIO支持分片上传,大小在5M和5G之间,先NewMultipartUpload创建一个分片上传,获取整体ID,PutObjectPart上传每个分片,其中携带当前分片的iD(1,2,3,4),最后调用CompleteMultipartUpload完成分片上传。