使用seaweedfs搭建一个图片服务器 (下)

上一篇文章详细讲解了怎么使用,这里完整的搭建一个图片服务器,并且列出使用的命令,详细的文档请看上一篇文章(https://www.jianshu.com/p/5e8dfb98fd86)和官方wiki(https://github.com/chrislusf/seaweedfs/wiki)。

1.架构

我们先了解一个概念:见附录

一个master:

作为cluster管理一个DataCenter名叫imgdatacenter1(抽象的概念);
imgdatacenter1包含一个机柜 rack名叫imgrack1(抽象的概念);
imgrack1机柜里面有一个DataNode名叫datanode1(可以认为DataNode是一个volume server );

cd /home1/seaweeddir  //这是我的测试目录,你这里选择你自己的目录
mkdir {mtmp,vtmp1,vtmp2,ftmp,mountdir}  //大括号内千万别多空格,否则会出现问题
weed master -ip=localhost -port=9333 -mdir=./mtmp (mtmp是你自定义的保存生成的序列文件id的文件夹)

一个DataNode:(datanode1只是抽象的名字没有实质的代码赋值,下面通过地址来区分DataNode)

就是上面的datanode1,定义里面有10个volume,collection不先设置,DataCenter和rack都用下面的指令指定:

weed volume  -dataCenter=imgdatacenter1 -rack=imgrack1  -ip=localhost -port=9991 -dir=./vtmp1 -max=10 -mserver=localhost:9333

此时就在名为imgdatacenter1的dataCenter中的名为imgrack1的rack里添加了一个地址为localhost:9991的volume server。

一个filer服务器

weed scaffold -config=filer -output=.      //先生成filer.toml文件

默认使用leveldb保存映射关系,打开filer.toml文件修改保存映射文件的文件夹为ftmp(自定义)


image.png

然后启动filer服务

weed filer -ip=localhost -port=8888  -master=localhost:9333 

本地映射filer

mountdir 是本地任意目录,filer.path后面跟你想映射的filer中的目录,可以直接映射根目录。

sudo weed mount -filer=localhost:8888 -dir=/home1/seaweeddir/mountdir -filer.path=/  
//sudo weed mount -filer=localhost:8888 -dir=~/folder_on_seaweedfs -filer.path=/home/chris -collection=chris

关闭挂在需要关闭mount并且手动umont ~/mdir目录,如果一般用户失败请使用root用户

2.验证

我们验证下我们的服务启动状态,
此时有一个DataCenters名为imgdatacenter1,一个Racks名为imgrack1,一个DataNodes地址是localhost:9991,且该DataNode的Volumes个数为0,等我们新增文件的时候就会发现volumes个数才会增加

//这种返回表示master启动成功且作为了leader
curl "http://localhost:9333/cluster/status?pretty=y"
{
  "IsLeader": true,
  "Leader": "localhost:9333"
}

//此时有一个DataCenters名为imgdatacenter1,一个Racks名为imgrack1,一个DataNodes地址是localhost:9991,且该DataNode的Volumes个数为0
curl "http://localhost:9333/dir/status?pretty=y"
{
  "Topology": {
    "DataCenters": [
      {
        "Free": 10,
        "Id": "imgdatacenter1",
        "Max": 10,
        "Racks": [
          {
            "DataNodes": [
              {
                "Free": 10,
                "Max": 10,
                "PublicUrl": "localhost:9991",
                "Url": "localhost:9991",
                "Volumes": 0
              }
            ],
            "Free": 10,
            "Id": "imgrack1",
            "Max": 10
          }
        ]
      }
    ],
    "Free": 10,
    "Max": 10,
    "layouts": null
  },
  "Version": "1.10"
}

本地操作的方式往服务器新增一个文件

cd /home1/image/mountdir
cp /home1/image/1.jpg ./

我们查看下系统状态,(详细数据参见附录:上传文件后的系统状态)
此时我们发现地址为localhost:9991的datanode的Volumes数量变成了7个,说明当前新增了7个volume,因为我们之前设置的volume最大个数时10,所有最多还能再新增3个volume。
我们再看layouts,发现已经不是之前的null了,而是出现了一个名为""的collection,有七个可以写的volume。
这是因为如果我们没有指定collection的时候,默认所有数据都保存在名为""的collection中

我们查看下文件上传后volumeserver的状态
我们发现id为4的volume的filecount为1,说明该文件上传到了这里。

我们你再看下filer的状态
多了个1.jpg文件

我们再看下我们的挂载目录

ls /home1/seaweeddir/mountdir/
1.jpg

此时说明我们上传文件就成功了

此时我们可以操作本地文件系统中的目录/home1/seaweeddir/mountdir,来操作我们的图片服务器。
然而批量操作本地文件系统的mount文件夹时不是并发的,需要经过fuse层,要想并发操作就需要直接操作filer服务。

通过filer服务器做一些文件操作

使用命令上传

curl -F [email protected] "http://localhost:8888/javascript/new_name.js"    # upload the file with a different name

本地批量上传文件

使用weed filer.copy file_or_dir1 [file_or_dir2 file_or_dir3] http://localhost:8888/path/to/a/folder/ (多线程且绕过fuse层)
我在本地/home1/image/staff 下有大量的图片,这里上传到filer服务器的mystaff下,我们查看/home1/seaweeddir/mountdir/下,会发现多了个staff目录,且目录下也全部拷贝了图片。

weed filer.copy /home1/image/staff http://localhost:8888/mystaff

删除文件

curl -X DELETE http://localhost:8888/path/to/file

删除文件夹

curl -X DELETE http://localhost:8888/path/to/dir?recursive=true

一些注意事项

1.关闭volume mount时需要手动sudo mount -l /home1/seaweeddir/mountdir目录,否则该目录会导致终端卡死。
2.删除操作不会马上清空磁盘,要想实时清空未使用的空间,请执行
curl "http://localhost:9333/vol/vacuum"

使用fid操作文件在filer的显示

curl http://localhost:9333/dir/assign
{"fid":"7,03a0146c8ac8","url":"localhost:9991","publicUrl":"localhost:9991","count":1}

curl -F file=@/home1/image/1.jpg http://localhost:9991/7,03a0146c8ac8 //在filer中找不到,因为filer服务没有保存映射关系,所有想使用filer,就得使用filer上传文件,否则只能通过fid获取信息。
curl -F file=@/home1/image/1.jpg "http://localhost:8888/javascript/2.jpg"//在filer的javascript目录下多了个2.jpg

weed download -server="localhost:9333" -dir="D:\data3" 4,012d48fa67 //可以通过fid下载文件

结尾

到这里一个图片服务器就搭建起来了,
真正要熟悉使用seaweedfs需要仔细阅读官方wiki,并且查看源码和实现依赖的论文来了解实现原理。
剩余的像数据备份,服务器云备份等请看官网wiki:
https://github.com/chrislusf/seaweedfs/wiki/Failover-Master-Server
https://github.com/chrislusf/seaweedfs/wiki/Amazon-S3-API
https://github.com/chrislusf/seaweedfs/wiki/Async-Replication-to-another-Filer

总结

cd /home1/seaweeddir 
mkdir {mtmp,vtmp1,vtmp2,ftmp,mountdir} 
weed scaffold -config=filer -output=. 
vim filer.toml (修改leveldb的dir为"./ftmp")
weed master -ip=localhost -port=9333 -mdir=./mtmp
weed volume  -dataCenter=imgdatacenter1 -rack=imgrack1  -ip=localhost -port=9991 -dir=./vtmp1 -max=10 -mserver=localhost:9333
weed filer -ip=localhost -port=8888  -master=localhost:9333 -collection=test
sudo weed mount -filer=localhost:8888 -dir=/home1/seaweeddir/mountdir -filer.path=/   -collection=test
//关闭服务后执行 sudo umount -l /home1/seaweeddir/mountdir 取消挂载
//此时就可以使用filer通过web操作文件了,而且也可以通过/home1/seaweeddir/mountdir本地操作文件了。
//或者这么理解,sudo weed mount只能用sudo umount -l 取消挂载,而不是直接kill进程。

附录:

其他上传下载的命令

weed upload -master=localhost:9333 file1 [file2 file3]
weed upload -master=localhost:9333 -dir=one_directory -include=*.pdf
//指定几个fid下载到本地one_directory中
weed download -server=localhost:9333 -dir=one_directory fid1 [fid2 fid3 ...]
//导出id为7的volume到/dir/name.tar,/tmp是volume保存的地址,只导出比2006-01-02T15:04:05新的文件
weed export -dir=/tmp -volumeId=7 -o=/home1/seaweeddir/exp2/name.tar -fileNameFormat={{.Name}} -newer='2006-01-02T15:04:05'

一些概念

1.topology 是树状结构,DataNode 是树的叶子节点, DataCenter 和 Rack 是树的非叶子节点, DataCenter 是 Rack 的父母节点。
2.在 MasterServer 维护的拓扑结构里, 是把 VolumeServer 的相关信息存储在 DataNode 里,每次查找对应的DataNode,都需要从 DataCenter -> Rack -> DataNode 依次找下去。
3."fid":"1,01f96b93eb" 就是 Fid,Fid 由三个部分组成 【VolumeId, NeedleId, Cookie】 组成

    VolumeId: 1 32bit 存储的物理卷的Id 
    NeedleId: 01 64bit 全局唯一NeedleId,每个存储的文件都不一样(除了互为备份的)。
    Cookie: f96b93eb 32bit Cookie值,为了安全起见,防止恶意攻击

4.VolumeId 是由 MasterServer 分配给 VolumeServer, 每个 VolumeServer 都维护个 n 个 Volume , 每个Volume 都有一个专属 VolumeId,之后会细说。 Needle 属于 Volume 里面的一个单元
5.dir 就是该 Volume 所在的目录,
6.Collection 很有用,每个 Volume 只能对应同一个 Collection,不同 Collection 的图片存储在不同 Volume,所以同一个 Volume 只能针对某一个 Collection ,而 同一个 Collection 的图片可能分布在不同的 Volume
7.Replication 和 Topology 严重相关,比如在 001 模式,即在同一个 rack 中的不同 DataNode 中备份一份。假设在 rack1 中含有 DataNode1, DataNode2, DataNode3 三个数据节点中【随机】选出两个数据节点, 比如选出 DataNode1, DataNode2 然后同时写入这两个数据节点。 假设 rack1 只有一个数据节点的时候,而备份模式是 001 模式, 则无法正常备份,服务会报错。
8.VolumeServer 启动时, 未申请任何 Volume,当第一次 /dir/assign 的时候, 会分配 Volume
9.每个 VolumeServer 默认的 Volume 大小是 7 。默认情况下,当一个 VolumeServer 使用的磁盘超过 7 *30G = 210G 之后, 该 VolumeServer 属于只读状态, MasterServer 不会再分配新的 Fid 给它。
10.每个 MasterServer 通过 Topology 维护多个 VolumeServer 。
11.每个 VolumeServer 维护多个 Volume 。
12.每个 Volume 包含多个 Needle ,Needle 即文件。
13.多台 VolumeServer 之间的多机备份实现是强一致性。
14.多台 MasterServer 之间的主从关系是是通过 goraft 实现。

collection的说明

如果我们没有指定collection的时候,默认所有数据都保存在名为""的collection中,
0.按照collection删除

Delete Collection
curl "http://localhost:9333/col/delete?collection=xxx&pretty=y"

1.预申请volume的时候指定collection

//预申请4个属于名为turbo的collection 的volume
curl "http://localhost:9333/vol/grow?collection=turbo&count=4"

2.添加filer时指定collection

//此时所有通过filer新增的数据都在名为myfiler的collection中
weed filer -ip=localhost -port=8888  -master=localhost:9333  -collection=myfiler
  1. mount时指定collection
//只挂在指定collection
weed mount -filer=localhost:8888 -dir=~/folder_on_seaweedfs -filer.path=/home/chris -collection=chris

4.其他

curl "http://127.0.0.1:9333/dir/assign?collection=pictures"
curl -F @file=./hello1.txt http://10.0.40.58:9333/submit?collection=test_crash
weed upload -collection myfiles -master=localhost:9333 XXX.txt

上传文件后的系统状态

curl "http://localhost:9333/dir/status?pretty=y"
{
  "Topology": {
    "DataCenters": [
      {
        "Free": 3,
        "Id": "imgdatacenter1",
        "Max": 10,
        "Racks": [
          {
            "DataNodes": [
              {
                "Free": 3,
                "Max": 10,
                "PublicUrl": "localhost:9991",
                "Url": "localhost:9991",
                "Volumes": 7
              }
            ],
            "Free": 3,
            "Id": "imgrack1",
            "Max": 10
          }
        ]
      }
    ],
    "Free": 3,
    "Max": 10,
    "layouts": [
      {
        "collection": "",
        "replication": "000",
        "ttl": "",
        "writables": [
          1,
          2,
          3,
          4,
          5,
          6,
          7
        ]
      }
    ]
  },
  "Version": "1.10"
}

我们查看下文件上传后volumeserver的状态
我们发现id为4的volume的filecount为1,说明该文件上传到了这里。

curl "http://localhost:9991/status?pretty=y"
{
  "Version": "1.10",
  "Volumes": [
    {
      "Id": 1,
      "Size": 0,
      "ReplicaPlacement": {
        "SameRackCount": 0,
        "DiffRackCount": 0,
        "DiffDataCenterCount": 0
      },
      "Ttl": {},
      "Collection": "",
      "Version": 3,
      "FileCount": 0,
      "DeleteCount": 0,
      "DeletedByteCount": 0,
      "ReadOnly": false
    },
    {
      "Id": 2,
      "Size": 0,
      "ReplicaPlacement": {
        "SameRackCount": 0,
        "DiffRackCount": 0,
        "DiffDataCenterCount": 0
      },
      "Ttl": {},
      "Collection": "",
      "Version": 3,
      "FileCount": 0,
      "DeleteCount": 0,
      "DeletedByteCount": 0,
      "ReadOnly": false
    },
    {
      "Id": 3,
      "Size": 0,
      "ReplicaPlacement": {
        "SameRackCount": 0,
        "DiffRackCount": 0,
        "DiffDataCenterCount": 0
      },
      "Ttl": {},
      "Collection": "",
      "Version": 3,
      "FileCount": 0,
      "DeleteCount": 0,
      "DeletedByteCount": 0,
      "ReadOnly": false
    },
    {
      "Id": 4,
      "Size": 77285,
      "ReplicaPlacement": {
        "SameRackCount": 0,
        "DiffRackCount": 0,
        "DiffDataCenterCount": 0
      },
      "Ttl": {},
      "Collection": "",
      "Version": 3,
      "FileCount": 1,
      "DeleteCount": 0,
      "DeletedByteCount": 0,
      "ReadOnly": false
    },
    {
      "Id": 5,
      "Size": 0,
      "ReplicaPlacement": {
        "SameRackCount": 0,
        "DiffRackCount": 0,
        "DiffDataCenterCount": 0
      },
      "Ttl": {},
      "Collection": "",
      "Version": 3,
      "FileCount": 0,
      "DeleteCount": 0,
      "DeletedByteCount": 0,
      "ReadOnly": false
    },
    {
      "Id": 6,
      "Size": 0,
      "ReplicaPlacement": {
        "SameRackCount": 0,
        "DiffRackCount": 0,
        "DiffDataCenterCount": 0
      },
      "Ttl": {},
      "Collection": "",
      "Version": 3,
      "FileCount": 0,
      "DeleteCount": 0,
      "DeletedByteCount": 0,
      "ReadOnly": false
    },
    {
      "Id": 7,
      "Size": 0,
      "ReplicaPlacement": {
        "SameRackCount": 0,
        "DiffRackCount": 0,
        "DiffDataCenterCount": 0
      },
      "Ttl": {},
      "Collection": "",
      "Version": 3,
      "FileCount": 0,
      "DeleteCount": 0,
      "DeletedByteCount": 0,
      "ReadOnly": false
    }
  ]
}

我们你再看下filer的状态
多了个1.jpg文件

curl  -H "Accept: application/json" "http://localhost:8888/?pretty=y" 
{
  "Path": "",
  "Entries": [
    {
      "FullPath": "/1.jpg",
      "Mtime": "2018-12-18T10:38:18+08:00",
      "Crtime": "2018-12-18T10:38:18+08:00",
      "Mode": 436,
      "Uid": 1000,
      "Gid": 1000,
      "Mime": "image/jpeg",
      "Replication": "",
      "Collection": "",
      "TtlSec": 0,
      "chunks": [
        {
          "file_id": "4,0189b08312",
          "size": 77244,
          "mtime": 1545100698715493243,
          "e_tag": "32f4abc5"
        }
      ]
    }
  ],
  "Limit": 100,
  "LastFileName": "1.jpg",
  "ShouldDisplayLoadMore": false
}

我们再看下我们的挂载目录

ls /home1/seaweeddir/mountdir/
1.jpg

你可能感兴趣的:(使用seaweedfs搭建一个图片服务器 (下))