在BlogCore中,上传附件到SeeweedFS分布式文件服务器

一、认识SeaweedFS

Seaweedfs是一个简单,高扩展性的分布式文件系统,是由Golang开发的分布式存储开源项目,它是用来存储文件的系统,并且与使用的语言无关,任何语言,任何框架都可以以它为文件存储,它的设计原理主要来源于一篇基于 Facebook 的图片存储系统的论文:

https://www.usenix.org/legacy/event/osdi10/tech/full_papers/Beaver.pdf,

感兴趣的可以看看,扩展思维。

它的两个目标分别是:

存储数十亿级的文件

快速响应文件。

seaweedfs选择以键值对(key->file)的实现方式。

seaweedfs的中心节点(center master)并不会管理所有文件的元数据而仅仅管理文件卷(file volmume),文件及其元数据的管理是由volume server实现的。这可以缓解center master的并发压力,并且将文件元数据分配到volume server可以实现更快的文件访问(只需一次磁盘读取操作)。

二、架构原理

下面,我们借助官网和网上的资料,来看看SeaweedFS的整体架构设计原理。前提是小伙伴已经使用过了,可能更好理解。看不懂没问题,看完本文操作成功后,再来看原理和论文就有些感悟了。

通常,分布式文件系统将每个文件拆分为块,中央主服务器保持文件名,到块句柄的块索引以及每个块服务器具体的块。

该架构非常简单。实际数据存储在存储节点的卷上。一个卷服务器可以有多个卷,并且都可以支持基本的读写访问。所有卷由主服务器管理。主服务器包含卷ID到卷服务器映射。这是相当静态的信息,可以轻松缓存。

在每个写入请求上,主服务器还会生成一个file key,这是一个不断增长的64位无符号整数。由于写入请求通常不如读取请求频繁,因此一台主服务器应该能够很好地处理并发

这种设计方案优点固然很多,但是主要的缺点是中央主服务器无法高效地处理许多小文件,并且由于所有读请求都需要通过块主服务器,所以对于许多高并发用户来说可能无法很好地扩展。

主服务器(master server)和卷服务器(volmue server) 。

三、搭建SeaweedFS环境(二进制方式)

(1)、安装GO环境

下载go语言包

sudo wget https://storage.googleapis.com/golang/go1.9.2.linux-amd64.tar.gz

解压到指定目录,并添加环境变量


sudo tar -C /usr/local -xzf go1.9.2.linux-amd64.tar.gz

添加环境变量

sudo vi /etc/profile

#工作目录
export GOPATH=/opt/go
#解压目录
export GOROOT=/usr/local/go
export GOARCH=386
export GOOS=linux
export GOBIN=$GOROOT/bin
export GOTOOLS=$GOROOT/pkg/tool/
export PATH=$PATH:$GOBIN:$GOTOOLS

source /etc/profile

在这里插入图片描述
(2)、安装git、mercurial


sudo yum install -y mercurial git

在这里插入图片描述
(3)、安装seaweedfs

下载安装seaweedfs地址

如果下载失败,可以手动下载


sudo wget  https://github.com/chrislusf/seaweedfs/releases/download/0.96/linux_amd64.tar.gz
sudo tar -zxvf linux_amd64.tar.gz

在这里插入图片描述
(4)、配置运行seaweedfs

进入解压目录,以守护进程启动seaweedfs的主服务及集群

(在启动前,先要创建相应的目录,/data/fileData,/data/t_v1,/data/t_v2,/data/t_v3)

sudo nohup ./weed master -mdir=/data/fileData -port=9333 -defaultReplication="001" -ip="150.158.44.198" >>/data/fileData/server_sfs.log &
sudo ./weed volume -dir=/data/t_v1 -max=5 -mserver="150.158.44.198:9333" -port=9080 -ip="150.158.44.198" >>/data/t_v1_sfs.log &
sudo ./weed volume -dir=/data/t_v2 -max=5 -mserver="150.158.44.198:9333" -port=9081 -ip="150.158.44.198" >>/data/t_v2_sfs.log &
sudo ./weed volume -dir=/data/t_v3 -max=5 -mserver="150.158.44.198:9333" -port=9082 -ip="150.158.44.198" >>/data/t_v3_sfs.log &

在这里插入图片描述
将上面的ip地址换为你的ip即可,默认可设为localhost。volume多少可以根据自己的情况添加。mdir、dir是指定文件存储路径。

一个 MasterServer 对应三个 VolumeServer ,设置复制模式为 “001” , 也就是在相同 Rack 下复制副本为一份,也就是总共有两份

说明
defaultReplication
000 不备份, 只有一份数据
001 在相同的rackj里备份一份数据
010 在相同数据中心内不同的rack间备份一份数据
100 在不同的数据中心备份一份数据
200 在两个不同的数据中心各复制2110 在不同的rack备份一份数据, 在不同的数据中心备份一次
如果数据备份类型是 xyz形式
各自的意义
x 在别的数据中心备份的份数
y 不相同数据中心不同的racks备份的份数
z 在别的服务器相同的rack的备份份数
访问服务器ip地址:9333,可以看到如下界面

在这里插入图片描述
四、搭建SeaweedFS环境(docker方式)

准备系统环境

docker 
docker-compose

下载seaweedfs源码并安装


1)git clone https://github.com/chrislusf/seaweedfs.git
2)cd seaweedfs/docker
3)docker build -t sunsl/seaweedfs .
4)# 修改docker-compose.yml中的 image 为 sunsl/seaweedfs
5)docker-compose up

整个过程很简单,就不多说了,效果和二进制安装是一样的。

五、seaweedfs在net core中的使用

可以先看看基本使用,很简单。

----查看是否启动成功

curl -X POST http://127.0.0.1:9333/dir/assign

----上传文件

curl -F file=@/test/101-1225-064124-39-20180613013100012.png

http://127.0.0.1:9333/submit

----在浏览器输入地址查看已上传的文件

http://127.0.0.1:9333/1,027bf4fdc5

----删除已上传的文件

curl -X DELETE http://127.0.0.1:9333/3,034537622c

————————————————

接下来我们在BlogCore中进行封装

1、配置文件配置参数


"Seaweed": [
    {
      "BaseUrl": "http://150.158.44.198:9333",
      "DirAssign": "/dir/assign",
      "routingKey": "ActUpload"
    }
  ]

2、文件上传

上传文件,支持同名的修改,

就是传同一个fid,可以直接覆盖原来的文件。

[HttpPost]
[AllowAnonymous]
public async Task<MessageModel<string>> UploadPicSeaweed()
{
    var data = new MessageModel<string>();

    IFormFileCollection files = Request.Form.Files;
    if (files == null || !files.Any()) { data.msg = "请选择上传的文件。"; return data; }

    FormFile picfile = files[0] as FormFile;
    var stream = picfile.OpenReadStream();
    var bytes = new byte[stream.Length];
    await stream.ReadAsync(bytes, 0, bytes.Length);

    var Configuration = (Appsettings.app<SeaweedVo>("Seaweed"))?.FirstOrDefault();
    var fileInfo = await GetUploadFileUrlAsync();
    var url = $"{fileInfo.PublicUrl}/{fileInfo.Fid}";
    var uploadResponse = await UploadFileAsync(url, bytes);

    data.response = fileInfo.Fid;
    data.msg = "上传成功";
    data.success = true;
    return data;
}

private async Task<SeaweedFSDirAssignModel> GetUploadFileUrlAsync()
{
    using var client = _httpClientFactory.CreateClient();
    var Configuration = (Appsettings.app<SeaweedVo>("Seaweed"))?.FirstOrDefault();
    var url = $"{Configuration.BaseUrl}{Configuration.DirAssign}";
    var response = await client.GetAsync(url);
    var body = await response.Content.ReadAsStringAsync();
    var json = JsonConvert.DeserializeObject<SeaweedFSDirAssignModel>(body);

    return json;
}

private async Task<SeaweedFSUploadResponse> UploadFileAsync(string url, byte[] context)
{
    using var client = _httpClientFactory.CreateClient();
    using var multipartContext = new MultipartFormDataContent();
    multipartContext.Add(
        new ByteArrayContent(
            context
        ),
        "file"
    );

    var fileUrl = $"{url}";
    var response = await client.PostAsync(fileUrl, multipartContext);
    var body = await response.Content.ReadAsStringAsync();
    var json = JsonConvert.DeserializeObject<SeaweedFSUploadResponse>(body);

    return json;
}

1、获取publicurl与fid

在这里插入图片描述
2、根据第一步的url提交文件

在这里插入图片描述
3、根据第一步的fid,查看详情

在这里插入图片描述
3、文件下载

这里就是上边的预览的封装

[HttpGet]
 [AllowAnonymous]
 public async Task<FileStreamResult> DownPicSeaweed([FromServices] IWebHostEnvironment environment, string imgname, string type = "")
 {
     using var httpClient = _httpClientFactory.CreateClient();
     var errStream = new MemoryStream(System.Text.Encoding.Default.GetBytes("访问的资源不存在!"));
     try
     {

         var configSeaWeed = (Appsettings.app<SeaweedVo>("Seaweed"))?.FirstOrDefault();
         var callback = $"{configSeaWeed.BaseUrl}/{imgname}";
         // 支持添加header
         //httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
         var httpResponse = await httpClient.GetAsync(new Uri(callback));
         var filestreamObj = await httpResponse.Content.ReadAsStreamAsync();
         var contenttype = httpResponse.Content?.Headers?.ContentType?.ObjToString();
        

         return File(filestreamObj, contenttype);
     }
     catch (Exception e)
     {
         Console.WriteLine("DownPicSeaweed:err:" + e.Message + e.StackTrace);
         return File(errStream, "application/json");
     }
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值