联犀 联犀
首页
使用指南
开发指南
技术分享
  • 中台接口 (opens new window)
  • 物联网接口 (opens new window)
在线体验 (opens new window)
  • gitee (opens new window)
  • github (opens new window)
  • 边缘网关-RHILEX (opens new window)
  • 边缘网关-opengw (opens new window)
首页
使用指南
开发指南
技术分享
  • 中台接口 (opens new window)
  • 物联网接口 (opens new window)
在线体验 (opens new window)
  • gitee (opens new window)
  • github (opens new window)
  • 边缘网关-RHILEX (opens new window)
  • 边缘网关-opengw (opens new window)
  • 应用开发

  • 后端开发

    • 服务开发

      • 服务初始化
      • 连接联犀服务
      • 中间件使用
      • 授权定义
      • swagger使用
      • 数据库使用
      • 第三方接入
      • 插槽使用
      • 数据分析模块使用
      • 消息队列
      • 分布式缓存
      • 定时任务
      • 分布式存储使用
        • 前置说明
          • oss
          • minio
          • bucket
        • 联犀oss定义
          • 初始化
          • 接口定义
        • 联犀文件上传
        • 联犀文件下载
        • minio运维
          • 数据迁移
          • 迁出
          • 迁入
        • 总结
    • 物联网

  • 开发指南
  • 后端开发
  • 服务开发
godLei6
2024-12-09
目录

分布式存储使用

联犀支持微服务,集群和单体模式的部署,要支持如此灵活的部署方式,文件存储也必须要能支持多种部署方式,如果使用本地文件存储的方式,那么就没办法进行横向拓展,所以联犀文件存储使用oss的方式进行文件存储,存储方式默认支持minio和阿里云oss两种oss的方式,本文讲述在联犀中如何正确的使用oss及minio.

# 前置说明

# oss

OSS(Object Storage Service)即对象存储服务。

它以对象的形式存储数据。每个对象包含数据、元数据(如日期、大小等)。和传统文件存储不同,它没有复杂的目录层级结构。OSS 具有海量存储能力,能轻松应对大规模数据。它可以通过网络访问,提供高可用、高可靠的数据存储解决方案。在互联网应用场景中非常实用,比如存储网站的图片、视频、用户文件等海量数据,许多云服务提供商都提供 OSS,是现代数据存储的重要方式。

# minio

Minio 是一款出色的高性能、分布式对象存储系统。

在存储方式上,它基于对象存储,每个对象含数据、元数据和唯一标识符,和传统存储方式有别,适合海量非结构化数据存储。其存储引擎高度优化,读写性能优异,通过纠删码技术保障数据可靠性和高效存储。

在架构方面,支持分布式部署,能灵活扩展节点,轻松应对大规模存储需求。兼容性良好,与亚马逊 S3 API 兼容,这让众多基于 S3 开发的工具能与之集成。并且它是开源的,在 GitHub 上有活跃社区,方便开发人员定制和获取支持。

应用场景广泛,在云存储服务中,可构建企业私有云存储,用于文件存储、备份和共享。在数据湖存储场景下,能存储各种原始数据,供数据科学家和分析师使用。对于容器存储,可为容器提供持久化存储,保障微服务架构下应用程序的数据存储和共享。

# bucket

在 Minio 等对象存储系统中,bucket(存储桶)是一个基本概念。它类似于文件系统中的文件夹,但又有所不同。bucket 是用于存储对象(如文件、图片等)的容器。可以将多个相关的对象放在一个 bucket 中进行管理,比如一个公司把所有用户头像放在一个名为 “user - avatars” 的 bucket 里。每个 bucket 有自己的名称,在一个存储系统中,bucket 名称是全局唯一的,通过它可以方便地组织和访问其中存储的对象。

# 联犀oss定义

# 初始化

配置文件定义位置: share/conf/oss.go

type OssConf struct {
	OssType             string `json:",default=minio,options=minio|aliyun"` //oss的类型
	AccessKeyID         string `json:",default=root,optional"`  //账号
	AccessKeySecret     string `json:",default=password,optional"`  //密码
	PublicBucketName    string `json:",default=ithings-public,optional"` //公开桶的名称
	TemporaryBucketName string `json:",default=ithings-temporary,optional"` //临时桶,30分钟有效期
	PrivateBucketName   string `json:",default=ithings-private,optional"` //私有桶的名称
	Location            string `json:",default=localhost:9000,optional"` // oss的地址
	UseSSL              bool   `json:",optional"` //是否使用ssl
	CustomHost          string `json:",default=/oss,env=OssCustomHost"` //带上host的返回前缀,支持环境变量
	CustomPath          string `json:",default=/oss,optional"` //相对路径返回的前缀
	ConnectTimeout      int64 //连接超时
	ReadWriteTimeout    int64 //读写超时
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

初始化: oss.NewOssClient(c.OssConf)

# 接口定义

联犀将不同的oss抽象出一组公共的接口提供给业务进行使用.

定义位置:share/oss/oss.go

type Handle interface {
	//提供带签名的上传url
	SignedPutUrl(ctx context.Context, filePath string, expiredSec int64, opKv common.OptionKv) (string, error)
	//提供带签名的下载url
	SignedGetUrl(ctx context.Context, filePath string, expiredSec int64, opKv common.OptionKv) (string, error)
	//删除文件
	Delete(ctx context.Context, filePath string, opKv common.OptionKv) error
	//上传本地文件
	Upload(ctx context.Context, filePath string, reader io.Reader, opKv common.OptionKv) (string, error)
	//获取文件信息
	GetObjectInfo(ctx context.Context, filePath string) (*common.StorageObjectInfo, error)
	//将文件下载到本地
	GetObjectLocal(ctx context.Context, filePath string, localPath string) error
	//列出符合前缀的文件列表
	ListObjects(ctx context.Context, prefix string) (ret []*common.StorageObjectInfo, err error)
	//获取私有桶
	PrivateBucket() Handle
	//获取公开桶
	PublicBucket() Handle
	//获取临时桶
	TemporaryBucket() Handle
	//从临时桶中将文件复制到选定桶的路径
	CopyFromTempBucket(tempPath, dstPath string) (string, error)
	//不带过期时间的获取文件url
	GetUrl(path string, withHost bool) (string, error)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 联犀文件上传

在所有业务系统中文件的操作是少不了的.如果设计的不好,就会导致到处都是文件上传的接口.如果都使用同一个上传接口,那么又会导致文件的混乱,不断增长和不可控制.

联犀在经历多次踩坑之后总结了一套通用且好用的方式.

  1. 初始化的时候,联犀在oss上会默认创建三个存储桶(bucket):
  • 临时桶: 文件有保存期限,并且上传只能上传到这个桶中
  • 私有桶: 当文件只能给有权限的人看的时候,文件会放到这个桶里,获取文件的时候要通过指定的链接才能拿到
  • 公开桶: 如果这个文件不在乎权限,如用户头像,ota固件升级包,那么放到这个桶里的文件只要知道url都可以获取
  1. 联犀提供了一个通用的上传接口,可以将文件上传到临时桶中,并返回文件存储的路径,这个接口所有服务和应用都可以使用.
  2. 前端拿到临时文件的路径后,路径作为业务接口的参数传递给业务后端,业务后端借助oss的方法将临时桶中的文件移动到私有桶或公开桶中.

至此,一个通用的上传流程就搞定了,下面是流程图示例:

代码示例(位置: things/service/dmsvr/internal/logic/productmanage/productInfoUpdateLogic.go:136):

if data.ProductImg != "" && data.IsUpdateProductImg == true { //如果填了参数且不等于原来的,说明修改头像,需要处理
		if old.ProductImg != "" {
			err := l.svcCtx.OssClient.PublicBucket().Delete(l.ctx, old.ProductImg, common.OptionKv{})
			if err != nil {
				l.Errorf("Delete file err path:%v,err:%v", old.ProductImg, err)
			}
		}
		nwePath := oss.GenFilePath(l.ctx, l.svcCtx.Config.Name, oss.BusinessProductManage, oss.SceneProductImg, fmt.Sprintf("%s/%s", data.ProductID, oss.GetFileNameWithPath(data.ProductImg)))
		path, err := l.svcCtx.OssClient.PublicBucket().CopyFromTempBucket(data.ProductImg, nwePath)
		if err != nil {
			return errors.System.AddDetail(err)
		}

		old.ProductImg = path
	}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

其中,我们需要关注 GenFilePath 这个函数,这个函数的签名如下:

func GenFilePath(ctx context.Context, svrName, business, scene, filePath string) string 
1
  • svrName:一般是我们的服务名,如core,路径的第一个就是服务名
  • business: 一般为一类业务的称呼,如产品管理,区域管理
  • scene: 场景,具体用在什么地方,如头像,配置文件等

同时如果ctx中带有租户号,也会放到文件的路径中,保证多租户的隔离.

# 联犀文件下载

文件下载有两种方式,一种是返回相对路径,一种是返回绝对路径,联犀默认都是返回相对路径,这种方式的好处是无需配置oss的返回地址,但是在类似设备ota升级这种场景,设备是需要获取绝对路径才可以使用,这种时候才需要进行绝对路径的配置.

相对路径的获取方式:

if pi.ProductImg != "" {
		dpi.ProductImg, err = svcCtx.OssClient.PublicBucket().GetUrl(pi.ProductImg, false)
		if err != nil {
			logx.WithContext(ctx).Errorf("%s.SignedGetUrl err:%v", utils.FuncName(), err)
		}
	}
1
2
3
4
5
6

绝对路径的获取方式:

svcCtx.OssClient.PublicBucket().GetUrl(files[0].FilePath, true)
1

绝对路径配置位置:

也可以使用环境变量的方式进行赋值,关键字是: OssCustomHost

# minio运维

# 后台

  • 访问地址为: http://127.0.0.1:9090/
  • 账号: root
  • 密码: password

# 数据迁移

# 迁出

#进入容器后执行
mc alias set local http://localhost:9000 root password
mc cp --recursive local/ ./ #私有桶迁出

# 退回宿主机后执行
docker cp ienv-minio:/file ./  # 将文件复制出镜像

1
2
3
4
5
6
7

# 迁入

将文件拷贝到需要迁入的服务器后

# 宿主机中执行
docker cp  ./ ienv-minio:/file  # 将文件复制进镜像

# 进入容器后执行
mc alias set local http://localhost:9000 root password  
mc cp --recursive ./* local
1
2
3
4
5
6

# 总结

通过以上方式,我们各个业务使用文件无需再单独定义自己的上传接口,仅需定义文件路径即可,实现通用的oss能力.

上次更新: 2024/12/09, 23:26:54
定时任务
消息推送

← 定时任务 消息推送→

Theme by Vdoing | Copyright © 2022-2025 昆明云物通科技有限公司|GNU | 滇ICP备2024043132号-1 |
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式