上一篇文章详细讲解了怎么使用,这里完整的搭建一个图片服务器,并且列出使用的命令,详细的文档请看上一篇文章(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(自定义)
然后启动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
- 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