.net core集成Minio,构建一个文件存储的基础设施

背景

先简单介绍下MinIO吧,官方给的介绍是它是一种高性能、S3 兼容的对象存储。它专为大规模 AI/ML、数据湖和数据库工作负载而构建,并且它是由软件定义的存储。不需要购买任何专有硬件,就可以在云上和普通硬件上拥有分布式对象存储。

MinIO拥有开源 GNU AGPL v3 和商业企业许可证的双重许可。

翻译一下,就是好使,能白嫖,能私有化部署。

这里提到的S3,是亚马逊提供的对象存储服务,S3兼容性是云原生应用程序的硬性要求,像国内流行的阿里云对象存储(OSS),腾讯云对象存储(COS),都是兼容S3的。

之所以要搭建私有化的对象存储服务,主要考虑是2个,一是原始的文件存储方案并不安全,也不能实现高可用,而且在使用场景上有很多局限,比如某个资源想要增加访问权限,或者想定期删除,又或者想使访问权限定期关闭,那就要在代码层面增加很多逻辑,非常不友好。而使用MinIO的话,这些都会变得非常简单。

在一个考虑是因为MinIO的可扩展性非常强大,且提供了丰富的API接口,只要条件允许,我甚至很方便的可以自建一个无限大的云存储服务出来,配合CDN等边缘加速技术,可以高效支撑团队内几乎所有涉及文件存储和访问的场景。

真正建立属于自己团队的存储基础设施。

安装

MinIO的安装过程,官方文档(MinIO | S3 Compatible Storage for AI)上有非常详细的说明,我这里还是简单的镜像一下。

官方文档里,分别提供了Kubernetes,Docker,Linux,macOS,Windows,5种环境的安装方案,我使用过docker,Linux,windows这三种,这里就贴一下Linux的安装方案,还是在WSL2环境下。

  • 下载文件
wget https://dl.min.io/server/minio/release/linux-amd64/archive/minio_20240913202602.0.0_amd64.deb -O minio.deb
sudo dpkg -i minio.deb
  • 启动服务
mkdir ~/minio
minio server ~/minio --console-address :9001

启动完成后,我们会看到这样的界面⬇️

其中,webui给出的链接是可以直接访问的

输入控制台给出的账号密码,就可以登录进去了。

注意,这里介绍的这是基于开发或者测试环境的快速部署方案,如果要在生产环境中来部署MinIO集群,那不是本文讨论的范围,感兴趣的可以参照官方文档的详细说明。

传送门👉:

MinIO Object Storage for Linux — MinIO Object Storage for Linux

对接

安装SDK

找一个测试项目或者新建个项目,安装上MinIO的sdk。

我这里还是用的上次的测试项目,项目文件长这样⬇️

  <ItemGroup><PackageReference Include="Dapper" Version="2.1.35" /><PackageReference Include="DotNetCore.CAP" Version="8.2.0" /><PackageReference Include="DotNetCore.CAP.Dashboard" Version="8.2.0" /><PackageReference Include="DotNetCore.CAP.Kafka" Version="8.2.0" /><PackageReference Include="DotNetCore.CAP.PostgreSql" Version="8.2.0" /><PackageReference Include="Minio" Version="6.0.3" /></ItemGroup>

注入服务

引入sdk后,在配置文件中增加一个类似这样的配置,如果是测试阶段在代码中直接配置也行。

"MinioSettings": {"Endpoint": "{宿主机分配给wsl的ip}:9000","AccessKey": "在minio面板中获取","SecretKey": "在minio面板中获取","UseSSL": false
}

这里面用到的accessKey和secretKey,涉及到访问权限,如果你了解过AWS的IAM相关知识点,就一目了然了。

这里我们不讨论这个话题,直接去获取相关的配置信息

在这个页面去创建这样一个access key即可。

或者我们也可以到Identity栏目,配置用户信息,用户组,组权限等信息,也可以生成一个更加具体的access key。

补充完配置信息后,就可以去项目中注入服务了。

关键代码如下

var minioSetting = builder.Configuration.GetSection("MinioSettings").Get<MinioSettings>();
builder.Services.AddMinio(x =>
{x.WithEndpoint(minioSetting.Endpoint).WithCredentials(minioSetting.AccessKey, minioSetting.SecretKey).WithSSL(minioSetting.UseSSL).Build();
});

这里,因为我们是在测试阶段,SSL协议可以先关掉,降低一些心智负担。

编写接口

服务注入完成后,就可以来编写一个测试接口了。

这里为了方便,我直接创建了一个支持分片上传的接口。

[HttpPost]
public async Task<IActionResult> Upload(FilePartModel model)
{try{  if (model.file == null || model.file.Length <= 0)return BadRequest("No file found.");await CreateBucketIfNotExists(model.bucket);using (var stream = model.file.OpenReadStream()){await _minioClient.PutObjectAsync(new PutObjectArgs().WithBucket(model.bucket).WithObject(model.savedFileName).WithContentType(model.contentType).WithObjectSize(stream.Length).WithStreamData(stream));Console.ForegroundColor = ConsoleColor.Yellow;Console.WriteLine($"{model.savedFileName} is uploaded successfully");Console.ForegroundColor = ConsoleColor.White;}if (model.merged){var listArgs = new ListObjectsArgs().WithBucket(model.bucket).WithPrefix(model.uploadId).WithRecursive(true).WithVersions(false);using (var mergedStream = new MemoryStream()){await foreach (var obj in _minioClient.ListObjectsEnumAsync(listArgs).ConfigureAwait(false)){var partStream = await _minioClient.GetObjectAsync(new GetObjectArgs().WithBucket(model.bucket).WithObject(obj.Key).WithCallbackStream((stream) =>{stream.CopyTo(mergedStream);}));await _minioClient.RemoveObjectAsync(new RemoveObjectArgs().WithBucket(model.bucket).WithObject(obj.Key));}// 将合并后的流写入到MinIOmergedStream.Seek(0, SeekOrigin.Begin);await _minioClient.PutObjectAsync(new PutObjectArgs().WithBucket(model.bucket).WithObject(model.savedFileName).WithContentType(model.contentType).WithObjectSize(mergedStream.Length).WithStreamData(mergedStream));}}var respData = new FileResponseDto(){fileIndex = model.chunkIndex,Completed = model.completed,path = "未完成",};if (model.completed){// 上传完成后返回一个临时的访问链接,有效期24小时PresignedGetObjectArgs args = new PresignedGetObjectArgs().WithBucket(model.bucket).WithObject(model.savedFileName).WithExpiry(60 * 60 * 24);string temporaryUrl = await _minioClient.PresignedGetObjectAsync(args);            respData.path = temporaryUrl;}                return Json(_resp.success(respData, "上传成功"));}catch (Exception ex){Console.WriteLine($"Failed to upload part {model.chunkIndex} to MinIO: {ex.Message}");}return Json(_resp.error("上传失败"));
}

简单说明一下,我这里因为是测试,所以分段代码和合并代码的逻辑写到了一起,实际情况中,可以引入一些其他的流程或方法来拆解这个接口。比如,上传分段文件是一个单独的接口,合并文件又是一个单独的接口,还可以引入缓存或者队列结构,当文件上传完成后,发布一个事件,来完成一些数据库的写入业务等等。

编写前端代码

关于大文件上传的前端代码,市面上有很多方案,也可以使用js的原生技术来实现,这里由于逻辑点较多,不在赘述前端部分的实现。

我个人也曾在2021年的博客中聊到过大文件的上传,传送门👉:一个支持断点续传的大文件分片上传的小模块_dotnet_为自己带盐_InfoQ写作社区

效果

这是上传小文件的效果

小文件

这是上传大文件的效果

大文件

再看下minio面板上的传输记录

总结

至此,在开发环境下,就完成了一个简单的,支持各种文件上传的功能。

在系统内部搭建一个基于MinIO的存储集群可以带来多个方面的优势,包括但不限于以下几点

  1. MinIO支持多租户架构,可以配置为高可用(HA)模式,意味着即便某个节点出现问题,系统仍可以继续运行而不丢失数据,这是传统的文件存储方式无法比拟的。
  2. MinIO设计用于高性能存储,支持对象存储协议如S3 API,可以提供高速的数据访问速度。对于需要快速读写大量数据的应用场景来说,这是一个重要的优点。
  3. MinIO支持水平扩展,可以通过增加更多的节点来扩展存储容量和吞吐量。
  4. 相比于使用第三方云服务提供商的服务,自己搭建MinIO集群可能会更经济实惠,尤其是当数据量非常大或者有特定的安全性和合规性要求时
  5. 自建存储集群可以更好地控制数据的位置和安全性,这对于需要遵守严格数据保护法律或行业标准的企业来说是一个关键因素
  6. 自己管理存储集群允许对环境进行深度定制,以满足特定的工作负载需求或者集成现有的工具和技术栈。

好了,基本就这样了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/431776.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【动态规划-多重背包】【hard】力扣2585. 获得分数的方法数

考试中有 n 种类型的题目。给你一个整数 target 和一个下标从 0 开始的二维整数数组 types &#xff0c;其中 types[i] [counti, marksi] 表示第 i 种类型的题目有 counti 道&#xff0c;每道题目对应 marksi 分。 返回你在考试中恰好得到 target 分的方法数。由于答案可能很…

【线程】POSIX信号量---基于环形队列的生产消费者模型

信号量概念 这篇文章是以前写的&#xff0c;里面讲了 System V的信号量的概念&#xff0c;POSIX信号量和SystemV信号量作用相同&#xff0c;都是用于同步操作&#xff0c;达到无冲突的访问共享资源目的。 但POSIX可以用于线程间同步。 信号量的概念 POSIX信号量的接口 初始化…

基于yolov8的红外小目标无人机飞鸟检测系统python源码+onnx模型+评估指标曲线+精美GUI界面

【算法介绍】 基于YOLOv8的红外小目标无人机与飞鸟检测系统是一项集成了前沿技术的创新解决方案。该系统利用YOLOv8深度学习模型的强大目标检测能力&#xff0c;结合红外成像技术&#xff0c;实现了对小型无人机和飞鸟等低空飞行目标的快速、准确检测。 YOLOv8作为YOLO系列的…

光伏开发:一分钟生成光伏项目报告

传统光伏项目报告的编制往往需要收集大量数据、进行复杂计算与分析&#xff0c;耗时长且易受人为因素影响。自动生成光伏项目报告&#xff0c;依托大数据、云计算、人工智能等先进信息技术&#xff0c;实现了对光伏项目关键参数的快速分析、评估与预测。 一、核心功能与流程 1…

进程间通信 (一)【管道通信(上)】

目录 1. 概况2. 管道通信的原理2.1 初步理解2.2 深入理解 1. 概况 是什么&#xff1a;两个及以上的进程实现数据层面的交互&#xff0c;称为进程间的通信。 因为进程独立性的存在&#xff0c;所以一个进程无法直接访问另一个进程的数据&#xff0c;即便是父子进程&#xff0c;子…

使用 KuboardSpray 安装kubernetes_v1.23.1

ps:亲测有效,十分方便,记录下来 pps:下面文档来自官网 使用 KuboardSpray 安装kubernetes_v1.23.1 #Kuboard-Spray Kuboard-Spray 是一款可以在图形界面引导下完成 Kubernetes 高可用集群离线安装的工具&#xff0c;开源仓库的地址为 Kuboard-Spray (opens new window) 安…

git push出错Push cannot contain secrets

报错原因&#xff1a; 因为你的代码里面包含了github token明文信息&#xff0c;github担心你的token会泄漏&#xff0c;所以就不允许你推送这些内容。 解决办法&#xff1a; 需要先把代码里面的github token信息删除掉&#xff0c;并且删掉之前的历史提交&#xff0c;只要包…

【深海王国】初中生也能画的电路板?目录合集

Hi٩(๑ ^ o ^ ๑)۶, 各位深海王国的同志们&#xff0c;早上下午晚上凌晨好呀~辛勤工作的你今天也辛苦啦 (o゜▽゜)o☆ 今天大都督为大家带来系列文章《初中生也能画的电路板》&#xff0c;帮你一周内快速入门PCB设计&#xff0c;手把手教你从元器件库添加、电路原理图绘制、…

go 运行报错missing go.sum entry for module providing package

运行&#xff1a; #清理go.mod中不再需要的模块&#xff0c;并且会添加缺失的模块条目到go.sum中 go mod tidy

前端vue-实现富文本组件

1.使用wangeditor富文本编辑器 工具网站&#xff1a;https://www.wangeditor.com/v4/ 下载安装命令&#xff1a;npm i wangeditor --save 成品如下图&#xff1a; 组件实现代码 <template><div><!-- 富文本编辑器 --><div id"wangeditor">…

《热血江湖》v23巅峰对决游戏程序(真端+最新官方版本)

《热血江湖》v23巅峰对决游戏程序&#xff08;真端最新官方版本&#xff09; 下载地址&#xff1a; 通过网盘分享的文件&#xff1a;【游戏】《热血江湖》v23巅峰对决游戏程序&#xff08;真端最新官方版本&#xff09; 链接: https://pan.baidu.com/s/18svlGuFnPM9ccwEAb7oBMw…

python-获取浏览器静态/动态素材

f12浏览器中 1&#xff1a;静态爬取 2.动态资源图片获取。斗鱼 3获取视频-抖音 一长串&#xff0c;最后一个http就是视频

相亲交友系统小程序:都市青年的新社交选择

在当今社会&#xff0c;都市青年面临着诸多挑战&#xff0c;其中之一就是如何在繁忙的工作和生活中找到理想的伴侣。相亲交友系统小程序应运而生&#xff0c;成为了都市青年的新社交选择。它不仅简化了传统相亲流程&#xff0c;还利用现代科技手段&#xff0c;如人工智能和大数…

【C++掌中宝】用最少的话让你全方位理解内联函数

文章目录 引言1. 什么是内联函数2. 工作原理3. 内联函数的编程风格4. 使用限制5. 内联函数与宏的比较6. 优缺点7. 何时使用内联函数8. 补充9. 总结结语 引言 在C编程中&#xff0c;函数的调用开销是程序运行效率的一个重要影响因素。为了解决频繁调用函数时的性能问题&#xf…

计算机视觉必备模型YOLO系列模型的知识点,提供YOLOv1-v8模型结构与代码实例

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下计算机视觉必备模型YOLO系列模型的知识点&#xff0c;提供YOLOv1-v8模型结构与代码实例。本文全面介绍了计算机视觉领域中必备的YOLO系列模型&#xff0c;详细梳理了YOLOv1至YOLOv8模型的结构及其演变过程。文章内容…

linux设置常见开机自启动命令

本文介绍了三种开机自启的方式&#xff0c;重点介绍使用systemctl的方式自启动的 方式一、修改 /etc/rc.d/rc.local 文件 /etc/rc.d/rc.local 文件会在 Linux 系统各项服务都启动完毕之后再被运行。所以你想要自己的脚本在开机后被运行的话&#xff0c;可以将自己脚本路径加到…

SQL - 进阶语法(二)约束

1. SQL约束 约束用于约束表中的数据规则&#xff0c;如若存在违反行为&#xff0c;行为会被约束终止。 • NOT NULL 确保列不能有NULL值 如果添加一行新的数据&#xff0c;不能有null值&#xff0c;否则无法添加 新建表格 CREATE TABLE new_table( ID int NOT NULL, NAME …

C语言中易混淆概念的关键字

最快的关键字---- register register&#xff1a; 这个关键字请求编译器尽可能的将变量存在 CPU 内部寄存器中而不是通过内 存寻址访问以提高效率。注意是尽可能&#xff0c;不是绝对。你想想&#xff0c;一个 CPU 的寄存器也就那么 几个或几十个&#xff0c;你要是定义了很多很…

【环境踩坑系列】centos7安装python3.10.X

前言 虽然centOS8已经发布了相当一段时间了&#xff0c;但是基于稳定性、成熟的社区等原因&#xff0c;大家在选择centOS作为服务器操作系统的时候仍然会选择centOS7作为首选。但是centOS7自带的是python2.7.5&#xff0c;当前大量的python程序要用到的又是python3&#xff0c…

day-60 字符串中最多数目的子序列

思路 由题目可以得出&#xff0c;当字符串开头插入pattern[0]或在字符串结尾插入pattern[1]这两种情况中的一种所得到的子序列数目一定是最多的 解题过程 我们可以遍历字符串&#xff0c;统计pattern[0]的个数&#xff0c;每当遇到一个pattern[1]时&#xff0c;序列数就会加上…