最近想配置一款可以存储文件的服务器,如果使用阿里云OSS、七牛云、腾讯云需要收取比较高的费用,为了节约成本,考虑使用免费开源的软件进行部署,然后对fastDFS和MiniO进行了对比:
一:安装部署(运维)复杂度
fastDFS分布式服务部署完成,需要具备以下的知识:
linux基础的目录操作
常用的分布式主从原理
C语言代码的编译
nginx安装部署
nginx插件的使用(防盗链)
如果仅仅是上面的这些基础知识,安排几个程序员学一学还好说。主要是fastdfs的部署结构之复杂,如果我长时间不回顾,自己都会忘了这复杂的架构是怎么回事。
当我看到MinIO的安装过程之后,以及分布式的部署命令之后(分布式MinIO快速入门),放弃fastDFS的决心就已经做出了一大半。
说白了:FastDFS的部署不过是零件的组装过程,需要你去理解fastDFS的架构设计,才能够正确的安装部署。MinIO在安装的过程是黑盒的,你不用去深入关注它的架构,也不需要你进行零件组装,基本上可以做到开箱即用。普通的技术人员就能够参与后期运维。
二:文档
我觉得从我知道fastDFS开始,也有十年了。竟然没有官方文档,所有的文档全是某某公司的自己总结的文档,或者是某某网友自己总结的文档。
从这点上看fastDFS真的是一败涂地,当然阿里余庆大神在做这个项目的时候可能也没有考虑到后来会有这么多人用。即使用的人多了,在余庆大神眼里可能觉得这只是自己开发的一个小玩具,没有继续深入运营的必要。
三:开源项目运营组织
fastdfs是阿里余庆做的一个个人项目,在一些互联网创业公司中有应用,没有官网,不活跃,6个contributors。目前已经很少做更新。
MinIO目前是由2014年在硅谷创立的公司MinIO.Inc运营的开源项目,社区论坛的活跃度目前也非常的不错。
四:UI界面
我们都知道fastDFS默认是不带UI界面的,MinIO有比较丰富的UI界面
五:性能
MinIO号称是世界上速度最快的对象存储服务器。在标准硬件上,对象存储的读/写速度最高可以达到183 GB/s和171 GB/s。关于fastDFS我曾经单线程测试写了20万个文件,总共200G,大约用时10个小时。总体上是很难达到MinIO“号称的”以G为单位的每秒读写速度。
六:容器化支持
MinIO提供了与k8s、etcd、docker等容器化技术深度集成方案,可以说就是为了云环境而生的。这点是FastDFS不具备的。
七:丰富的SDK支持
fastDFS目前提供了 C 和 Java SDK ,以及 PHP 扩展 SDK。下图是MinIO提供的SDK支持,MinIO几乎提供了所有主流开发语言的SDK以及文档。同志们,重要的是文档。
八:AWS S3标准兼容
Amazon的S3 API是对象存储领域的事实标准。MinIO是S3兼容性的事实上的标准,是第一个采用API和第一个添加对S3 Select支持的标准之一。包括微软Azure在内的750多家公司使用MinIO的S3网关,这一数字超过了业内其他公司的总和。
文档地址:MinIO | The MinIO Quickstart Guide
安装包下载地址: https://dl.minio.io/server/minio/release/windows-amd64/minio.exe
一、安装部署
1、下载安装包(下载地址在上面)
2、放到磁盘中,后面会以这个文件进行服务器安装
3、磁盘新建一个目录用于存放上传文件,比如我创建的为:Data
4、运行控制台程序:切换到安装包所在目录(后面部分为存储路径), 输入命令:minio.exe server C:\minio\Data
5、打开浏览器,访问:http://127.0.0.1:9000 用户名和密码默认为:minioadmin,主界面如下
二、注册成window服务
- 下载winsw,下载地址:Releases · winsw/winsw · GitHub
CSDN下载地址:https://download.csdn.net/download/feritylamb/86394140
2. 将WinSW-net461.exe复制到自定义的目录,并重命名为自己想命名的服务名称minio-server.exe
-
同目录下创建minio-server.xml。特别注意,xml和exe必须同名
-
配置minio-server.xml文件
5.新建run.bat文件,内容如下:
set MINIO_ACCESS_KEY=admin
set MINIO_SECRET_KEY=12345678
minio.exe server C:\minio\Data
带密码带自己定义端口9991启动命令:
set MINIO_ACCESS_KEY=admin
set MINIO_SECRET_KEY=12345678
minio.exe server --address:9991 C:\minio\Data
- 使用minio-server.exe install安装服务
安装服务命令:minio-server.exe install
启动服务命令:minio-server.exe start
停止服务命令:minio-server.exe stop
移除服务命令:sc delete minio-server
xml配置文件如下:
minio-server
minio-server
minio文件存储服务器
%BASE%\minio.exe
server “%BASE%\data”
%BASE%\logs
10240
yyyyMMdd
00:00:00
5
yyyyMMdd
注:如果启动不成功,可以把以上description里面的中文去掉
三、C#文件上传下载
public async void testupload()
{
try
{
MinioClient minio = new MinioClient(“127.0.0.1:9000”, “minioadmin”, “minioadmin”);
//桶名称
string buckName = “202110001”;
//判断桶是否存在,如果不存在则创建桶,否则上传文件会异常
var exists = await MinioHelper.BucketExists(minio, buckName);
if (!exists)
{
//创建桶
await MinioHelper.MakeBucket(minio, buckName);
}
//上传文件(桶下面可以自定义文件夹。如:1027/20211027001.jpg 则会创建一个1027文件夹)
var result = await MinioHelper.FPutObject(minio, buckName, “1027/20211027001.png”, “E:\202110271417.png”);
//下载文件地址:192.168.90.128:9000+桶名称+文件名称
}
catch (Exception ex)
{
string str = ex.Message;
}
}
四、minio文件操作帮助类
public class MinioHelper
{
#region 操作存储桶
/// <summary>创建存储桶
/// 创建存储桶
/// </summary>
/// <param name="minio">连接实例</param>
/// <param name="bucketName">存储桶名称</param>
/// <param name="loc">可选参数</param>
/// <returns></returns>
public async static Task<bool> MakeBucket(MinioClient minio, string bucketName, string loc = "us-east-1")
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
throw new Exception(string.Format("存储桶[{0}]已存在", bucketName));
}
else
{
await minio.MakeBucketAsync(bucketName, loc);
flag = true;
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return flag;
}
/// <summary>列出所有的存储桶
/// 列出所有的存储桶
/// </summary>
/// <param name="minio">连接实例</param>
/// <returns></returns>
public async static Task<Tuple<bool, Minio.DataModel.ListAllMyBucketsResult>> ListBuckets(MinioClient minio)
{
bool flag = false;
var list = new Minio.DataModel.ListAllMyBucketsResult();
try
{
list = await minio.ListBucketsAsync();
flag = true;
//foreach (var bucket in list.Buckets)
//{
// Console.WriteLine($"{bucket.Name} {bucket.CreationDateDateTime}");
//}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return Tuple.Create(flag, list);
}
/// <summary>检查存储桶是否存在
/// 检查存储桶是否存在
/// </summary>
/// <param name="minio">连接实例</param>
/// <param name="bucketName">存储桶名称</param>
/// <returns></returns>
public async static Task<bool> BucketExists(MinioClient minio, string bucketName)
{
bool flag = false;
try
{
flag = await minio.BucketExistsAsync(bucketName);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return flag;
}
/// <summary>删除一个存储桶
/// 删除一个存储桶
/// </summary>
/// <param name="minio">连接实例</param>
/// <param name="bucketName">存储桶名称</param>
/// <returns></returns>
public async static Task<bool> RemoveBucket(MinioClient minio, string bucketName)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{