上一篇文章詳細(xì)講解了怎么使用,這里完整的搭建一個圖片服務(wù)器,并且列出使用的命令,詳細(xì)的文檔請看上一篇文章(http://www.itdecent.cn/p/5e8dfb98fd86)和官方wiki(https://github.com/chrislusf/seaweedfs/wiki)。
1.架構(gòu)
我們先了解一個概念:見附錄
一個master:
作為cluster管理一個DataCenter名叫imgdatacenter1(抽象的概念);
imgdatacenter1包含一個機(jī)柜 rack名叫imgrack1(抽象的概念);
imgrack1機(jī)柜里面有一個DataNode名叫datanode1(可以認(rèn)為DataNode是一個volume server );
cd /home1/seaweeddir //這是我的測試目錄,你這里選擇你自己的目錄
mkdir {mtmp,vtmp1,vtmp2,ftmp,mountdir} //大括號內(nèi)千萬別多空格,否則會出現(xiàn)問題
weed master -ip=localhost -port=9333 -mdir=./mtmp (mtmp是你自定義的保存生成的序列文件id的文件夾)
一個DataNode:(datanode1只是抽象的名字沒有實質(zhì)的代碼賦值,下面通過地址來區(qū)分DataNode)
就是上面的datanode1,定義里面有10個volume,collection不先設(shè)置,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服務(wù)器
weed scaffold -config=filer -output=. //先生成filer.toml文件
默認(rèn)使用leveldb保存映射關(guān)系,打開filer.toml文件修改保存映射文件的文件夾為ftmp(自定義)

然后啟動filer服務(wù)
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
關(guān)閉掛在需要關(guān)閉mount并且手動umont ~/mdir目錄,如果一般用戶失敗請使用root用戶
2.驗證
我們驗證下我們的服務(wù)啟動狀態(tài),
此時有一個DataCenters名為imgdatacenter1,一個Racks名為imgrack1,一個DataNodes地址是localhost:9991,且該DataNode的Volumes個數(shù)為0,等我們新增文件的時候就會發(fā)現(xiàn)volumes個數(shù)才會增加
//這種返回表示master啟動成功且作為了leader
curl "http://localhost:9333/cluster/status?pretty=y"
{
"IsLeader": true,
"Leader": "localhost:9333"
}
//此時有一個DataCenters名為imgdatacenter1,一個Racks名為imgrack1,一個DataNodes地址是localhost:9991,且該DataNode的Volumes個數(shù)為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"
}
本地操作的方式往服務(wù)器新增一個文件
cd /home1/image/mountdir
cp /home1/image/1.jpg ./
我們查看下系統(tǒng)狀態(tài),(詳細(xì)數(shù)據(jù)參見附錄:上傳文件后的系統(tǒng)狀態(tài))
此時我們發(fā)現(xiàn)地址為localhost:9991的datanode的Volumes數(shù)量變成了7個,說明當(dāng)前新增了7個volume,因為我們之前設(shè)置的volume最大個數(shù)時10,所有最多還能再新增3個volume。
我們再看layouts,發(fā)現(xiàn)已經(jīng)不是之前的null了,而是出現(xiàn)了一個名為""的collection,有七個可以寫的volume。
這是因為如果我們沒有指定collection的時候,默認(rèn)所有數(shù)據(jù)都保存在名為""的collection中
我們查看下文件上傳后volumeserver的狀態(tài)
我們發(fā)現(xiàn)id為4的volume的filecount為1,說明該文件上傳到了這里。
我們你再看下filer的狀態(tài)
多了個1.jpg文件
我們再看下我們的掛載目錄
ls /home1/seaweeddir/mountdir/
1.jpg
此時說明我們上傳文件就成功了
此時我們可以操作本地文件系統(tǒng)中的目錄/home1/seaweeddir/mountdir,來操作我們的圖片服務(wù)器。
然而批量操作本地文件系統(tǒng)的mount文件夾時不是并發(fā)的,需要經(jīng)過fuse層,要想并發(fā)操作就需要直接操作filer服務(wù)。
通過filer服務(wù)器做一些文件操作
使用命令上傳
curl -F file=@report.js "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服務(wù)器的mystaff下,我們查看/home1/seaweeddir/mountdir/下,會發(fā)現(xiàn)多了個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.關(guān)閉volume mount時需要手動sudo mount -l /home1/seaweeddir/mountdir目錄,否則該目錄會導(dǎo)致終端卡死。
2.刪除操作不會馬上清空磁盤,要想實時清空未使用的空間,請執(zhí)行
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服務(wù)沒有保存映射關(guān)系,所有想使用filer,就得使用filer上傳文件,否則只能通過fid獲取信息。
curl -F file=@/home1/image/1.jpg "http://localhost:8888/javascript/2.jpg"http://在filer的javascript目錄下多了個2.jpg
weed download -server="localhost:9333" -dir="D:\data3" 4,012d48fa67 //可以通過fid下載文件
結(jié)尾
到這里一個圖片服務(wù)器就搭建起來了,
真正要熟悉使用seaweedfs需要仔細(xì)閱讀官方wiki,并且查看源碼和實現(xiàn)依賴的論文來了解實現(xiàn)原理。
剩余的像數(shù)據(jù)備份,服務(wù)器云備份等請看官網(wǎng)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
總結(jié)
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
//關(guān)閉服務(wù)后執(zhí)行 sudo umount -l /home1/seaweeddir/mountdir 取消掛載
//此時就可以使用filer通過web操作文件了,而且也可以通過/home1/seaweeddir/mountdir本地操作文件了。
//或者這么理解,sudo weed mount只能用sudo umount -l 取消掛載,而不是直接kill進(jìn)程。
附錄:
其他上傳下載的命令
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 ...]
//導(dǎo)出id為7的volume到/dir/name.tar,/tmp是volume保存的地址,只導(dǎo)出比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 是樹狀結(jié)構(gòu),DataNode 是樹的葉子節(jié)點, DataCenter 和 Rack 是樹的非葉子節(jié)點, DataCenter 是 Rack 的父母節(jié)點。
2.在 MasterServer 維護(hù)的拓?fù)浣Y(jié)構(gòu)里, 是把 VolumeServer 的相關(guān)信息存儲在 DataNode 里,每次查找對應(yīng)的DataNode,都需要從 DataCenter -> Rack -> DataNode 依次找下去。
3."fid":"1,01f96b93eb" 就是 Fid,F(xiàn)id 由三個部分組成 【VolumeId, NeedleId, Cookie】 組成
VolumeId: 1 32bit 存儲的物理卷的Id
NeedleId: 01 64bit 全局唯一NeedleId,每個存儲的文件都不一樣(除了互為備份的)。
Cookie: f96b93eb 32bit Cookie值,為了安全起見,防止惡意攻擊
4.VolumeId 是由 MasterServer 分配給 VolumeServer, 每個 VolumeServer 都維護(hù)個 n 個 Volume , 每個Volume 都有一個專屬 VolumeId,之后會細(xì)說。 Needle 屬于 Volume 里面的一個單元
5.dir 就是該 Volume 所在的目錄,
6.Collection 很有用,每個 Volume 只能對應(yīng)同一個 Collection,不同 Collection 的圖片存儲在不同 Volume,所以同一個 Volume 只能針對某一個 Collection ,而 同一個 Collection 的圖片可能分布在不同的 Volume
7.Replication 和 Topology 嚴(yán)重相關(guān),比如在 001 模式,即在同一個 rack 中的不同 DataNode 中備份一份。假設(shè)在 rack1 中含有 DataNode1, DataNode2, DataNode3 三個數(shù)據(jù)節(jié)點中【隨機(jī)】選出兩個數(shù)據(jù)節(jié)點, 比如選出 DataNode1, DataNode2 然后同時寫入這兩個數(shù)據(jù)節(jié)點。 假設(shè) rack1 只有一個數(shù)據(jù)節(jié)點的時候,而備份模式是 001 模式, 則無法正常備份,服務(wù)會報錯。
8.VolumeServer 啟動時, 未申請任何 Volume,當(dāng)?shù)谝淮?/dir/assign 的時候, 會分配 Volume
9.每個 VolumeServer 默認(rèn)的 Volume 大小是 7 。默認(rèn)情況下,當(dāng)一個 VolumeServer 使用的磁盤超過 7 *30G = 210G 之后, 該 VolumeServer 屬于只讀狀態(tài), MasterServer 不會再分配新的 Fid 給它。
10.每個 MasterServer 通過 Topology 維護(hù)多個 VolumeServer 。
11.每個 VolumeServer 維護(hù)多個 Volume 。
12.每個 Volume 包含多個 Needle ,Needle 即文件。
13.多臺 VolumeServer 之間的多機(jī)備份實現(xiàn)是強(qiáng)一致性。
14.多臺 MasterServer 之間的主從關(guān)系是是通過 goraft 實現(xiàn)。
collection的說明
如果我們沒有指定collection的時候,默認(rèn)所有數(shù)據(jù)都保存在名為""的collection中,
0.按照collection刪除
Delete Collection
curl "http://localhost:9333/col/delete?collection=xxx&pretty=y"
1.預(yù)申請volume的時候指定collection
//預(yù)申請4個屬于名為turbo的collection 的volume
curl "http://localhost:9333/vol/grow?collection=turbo&count=4"
2.添加filer時指定collection
//此時所有通過filer新增的數(shù)據(jù)都在名為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
上傳文件后的系統(tǒng)狀態(tài)
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的狀態(tài)
我們發(fā)現(xiàn)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的狀態(tài)
多了個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