青训营项目中期总结(3)| 青训营

114 阅读4分钟

由于设定了自己关注自己,因此关注数和粉丝数都减一 在查询粉丝关注好友列表时,也排除自己

4个服务暴露出8个端口,采用nginx反向代理,统一在9000端口监听,再通过请求的路径来转发到对应的端口

七牛云流量超额了,打算使用minIO,搭建自己的分布式对象存储

MinIO

MinIO 是一个开源的对象存储服务器,它是一个高性能、分布式的存储系统,专门用于存储大规模的非结构化数据,如图片、视频、日志文件等。MinIO 具有以下特点:

  1. 对象存储:MinIO 是一个对象存储系统,它以对象(Object)的形式存储数据。每个对象可以是任意类型的文件,如图像、视频、文档等。
  2. 分布式架构:MinIO 可以以分布式的方式部署,可以跨多台服务器组成集群,实现数据的分布式存储和高可用性。
  3. 高性能:MinIO 设计用于提供高吞吐量、低延迟的数据存储和检索。它可以利用现代硬件和网络基础设施,实现高效的数据传输和处理。
  4. 开源:MinIO 是一个开源项目,代码开放,社区活跃。这使得用户可以根据自己的需求进行定制和扩展。
  5. 兼容性:MinIO 实现了 Amazon S3 协议,这意味着你可以使用 S3 协议来上传、下载和管理数据。这也使得 MinIO 可以兼容各种支持 S3 协议的工具和应用。
  6. 安全性:MinIO 支持数据加密、访问控制策略、预签名URL 等安全机制,可以确保数据的保密性和完整性。
  7. 轻量级部署:MinIO 的部署和管理相对轻量级,你可以在本地或云上快速搭建一个存储服务。
  8. 多种用途: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完成分片上传。