Saeweedfs是一个由golang语言开发的分布式对象存储系统,很适合作图片服务器,性能很好,安装操做都很简单,而且可兼容挂载提供路径访问的方式,能够较为便捷的将nginx+nfs此类的文件服务器转换成nginx+seweedfs并提供api接口并不影响原有访问url的模式html
参考连接node
https://github.com/chrislusf/seaweedfs/wiki/Getting-Started 官网linux
http://www.importnew.com/3292.html 论文nginx
https://www.jianshu.com/p/2ff61b56f37b 安装git
https://blog.csdn.net/u012618915/article/details/83415955 参数github
https://www.jianshu.com/p/51d6d444303d 问题golang
首先咱们下载weedredis
在https://github.com/chrislusf/seaweedfs/releases/咱们能够看到已有版本及历史,写此文档时最新的长期支持版本为1.34,咱们下载解压后能够看见一个可执行文件weed,由于是golang编译好的,咱们能够直接使用它sql
1 [root@seaweedfs-bj-zw-vm1~]# wget https://github.com/chrislusf/seaweedfs/releases/download/1.34/linux_amd64.tar.gz 2 [root@seaweedfs-bj-zw-vm1~]# tar -zxf linux_amd64.tar.gz 3 [root@seaweedfs-bj-zw-vm1 ~]# ll 4 -rwxr-xr-x. 1 root root 48548500 5月 29 17:29 weed 5 [root@seaweedfs-bj-zw-vm1 ~]# ./weed -h # 查看帮助
master节点数据库
master的做用仅仅是管理文件卷与服务器磁盘的映射,连文件的元数据也无论理,所以不须要额外的磁盘存储,性能上也是极好的
1 [root@seaweedfs-bj-zw-vm1 ~]# tail -30 master.out 2 I0604 18:46:39 5872 node.go:224] topo:zw:openstack-bj-zw-bgp6 adds child 172.16.100.138:8082 3 I0604 18:46:39 5872 master_grpc_server.go:67] added volume server 172.16.100.138:8082 4 I0604 18:46:39 5872 master_grpc_server.go:95] master see new volume 23 from 172.16.100.136:8081 5 I0604 18:46:39 5872 master_grpc_server.go:107] master send to filer172.16.100.111:25608: url:"172.16.100.136:8081" public_url:"172.16.100.136:8081" new_vids:23 6 I0604 18:46:39 5872 master_grpc_server.go:107] master send to filer172.16.100.107:15594: url:"172.16.100.136:8081" public_url:"172.16.100.136:8081" new_vids:23 7 I0604 18:46:39 5872 master_grpc_server.go:107] master send to filer172.16.100.106:40120: url:"172.16.100.136:8081" public_url:"172.16.100.136:8081" new_vids:23 8 I0604 18:46:39 5872 node.go:224] topo:zw:openstack-bj-zw-bgp6 adds child 172.16.100.138:8081 9 I0604 18:46:39 5872 master_grpc_server.go:67] added volume server 172.16.100.138:8081 10 I0604 18:46:39 5872 master_grpc_server.go:95] master see new volume 24 from 172.16.100.138:8081 11 I0604 18:46:39 5872 master_grpc_server.go:107] master send to filer172.16.100.111:25608: url:"172.16.100.138:8081" public_url:"172.16.100.138:8081" new_vids:24 12 I0604 18:46:39 5872 master_grpc_server.go:95] master see new volume 22 from 172.16.100.138:8082 13 I0604 18:46:39 5872 master_grpc_server.go:95] master see new volume 25 from 172.16.100.138:8082 14 I0604 18:46:39 5872 master_grpc_server.go:95] master see new volume 28 from 172.16.100.138:8082 15 I0604 18:46:39 5872 master_grpc_server.go:107] master send to filer172.16.100.111:25608: url:"172.16.100.138:8082" public_url:"172.16.100.138:8082" new_vids:22 new_vids:25 new_vids:28 16 I0604 18:46:39 5872 master_grpc_server.go:107] master send to filer172.16.100.107:15594: url:"172.16.100.138:8081" public_url:"172.16.100.138:8081" new_vids:24 17 I0604 18:46:39 5872 master_grpc_server.go:107] master send to filer172.16.100.107:15594: url:"172.16.100.138:8082" public_url:"172.16.100.138:8082" new_vids:22 new_vids:25 new_vids:28 18 I0604 18:46:39 5872 master_grpc_server.go:107] master send to filer172.16.100.106:40120: url:"172.16.100.138:8082" public_url:"172.16.100.138:8082" new_vids:22 new_vids:25 new_vids:28 19 I0604 18:46:39 5872 master_grpc_server.go:107] master send to filer172.16.100.106:40120: url:"172.16.100.138:8081" public_url:"172.16.100.138:8081" new_vids:24 20 I0604 18:46:39 5872 node.go:224] topo:zw:openstack-bj-zw-bgp5 adds child 172.16.100.136:8082 21 这是我使用过产生的日志,在master的输出日志中咱们能够直观看出master see new volume 22 from 172.16.100.138:8082这类日志,这就是卷及其映射,表明22号卷在172.16.100.138的8082端口可访问 22 咱们启动一个master,并设置一些参数,参数有不少都是默认的,能够不设置 23 # mdir 存储元数据的数据目录 24 # port 监听端口 25 # peers 主节点ip:端口 26 # defaultReplication 备份策略 27 # ip 服务器ip 28 # garbageThreshold 清空和回收空间的阈值 29 # maxCpu 最大cpu数量,0是全部 30 # pulseSeconds 心跳检测的时间间隔单位为秒 31 # ip.bind 绑定ip 32 # volumeSizeLimitMB volumes超载量,最大30G,即一个卷能够存多少数据,固然一个卷不表明一个磁盘,这点在下面的volume节点上再写 33 [root@seaweedfs-bj-zw-vm1 ~]# /root/weed master -mdir=/data/seaweedfs -port=9333 -peers=172.16.100.107:9333,172.16.100.111:9333,172.16.100.106:9333 -defaultReplication="000" -ip="172.16.100.107" -garbageThreshold=0.3 -maxCpu=0 -pulseSeconds=5 -ip.bind=0.0.0.0 -volumeSizeLimitMB=30000 >>/root/master.out & 34 [root@seaweedfs-bj-zw-vm1 ~]# tree /data/ # 这个目录里其实没啥东西 35 /data/ 36 └── seaweedfs 37 ├── conf 38 ├── log 39 └── snapshot 40 41 2 directories, 2 files 42 [root@seaweedfs-bj-zw-vm1 ~]# netstat -tpln|grep 9333 43 tcp6 0 0 :::19333 :::* LISTEN 770/weed 44 tcp6 0 0 :::9333 :::* LISTEN 770/weed 45 这样咱们一个master节点就起来,固然若是你须要高可用的时候要将另外的master节点也起来,master节点是奇数,他们之间会选举leader,剩下的成为从节点以备不时之需,咱们的参数-peers就是指定全部的master节点ip及port,若是是测试只是用单机那就不用加这个参数了
volume节点
volume很明显就是存储数据的真实节点了,它保留了文件的元数据及文件,经过卷的模式将磁盘分割,每一个卷都有一个索引文件,每一个元数据只有40字节,读取时间O(1),效率极高,速度极快
1 首先咱们先将底层磁盘挂载上,我是2个1T的磁盘 2 [root@seaweedfs-bj-zw-vm5 ~]# mkdir -p /data/seaweedfs/volume{1..2} 3 [root@seaweedfs-bj-zw-vm5 ~]# mount /dev/vdb /data/seaweedfs/volume1 4 [root@seaweedfs-bj-zw-vm5 ~]# mount /dev/vdc /data/seaweedfs/volume2 5 [root@seaweedfs-bj-zw-vm5 ~]# df -h 6 文件系统 容量 已用 可用 已用% 挂载点 7 /dev/vda1 40G 2.3G 38G 6% / 8 devtmpfs 1.9G 0 1.9G 0% /dev 9 tmpfs 1.9G 12K 1.9G 1% /dev/shm 10 tmpfs 1.9G 17M 1.9G 1% /run 11 tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup 12 tmpfs 379M 0 379M 0% /run/user/0 13 /dev/vdb 1.0T 369G 656G 36% /data/seaweedfs/volume1 14 /dev/vdc 1.0T 185G 840G 18% /data/seaweedfs/volume2 15 # dir 存储数据文件的目录,刚才的挂载点 16 # mserver master服务器列表 17 # port 监听端口 18 # ip 服务器ip 19 # max 本机volumes的最大值,在master上咱们定义的每一个卷为30G,但是咱们的磁盘不可能就这么点,而max的做用就是表示这个磁盘上能够分多少个卷,默认是7,也就是30G * 7 = 210G,很明显磁盘被浪费了不少空间,所以咱们须要指定一个大max值,保证volumeSizeLimitMB * max >= 磁盘容量,固然你能够直接100,简单粗暴 20 # dataCenter 机房 21 # rack 机架 22 # idleTimeout 链接空闲时间秒数 23 # images.fix.orientation 上传时调整jpg方向 24 # ip.bind 监听ip 25 # maxCpu 最大cpu数量 26 # read.redirect 从新定向转移非本地volumes 27 28 /root/weed volume -dir=/data/seaweedfs/volume1 -mserver=172.16.100.107:9333,172.16.100.111:9333,172.16.100.106:9333 -ip="172.16.100.136" -max=100 -dataCenter=zw -rack=openstack-bj-zw-bgp5 -idleTimeout=30 -images.fix.orientation=true -ip.bind=0.0.0.0 -maxCpu=0 -port=8081 -read.redirect=true >>/root/volume1.out & 29 /root/weed volume -dir=/data/seaweedfs/volume2 -mserver=172.16.100.107:9333,172.16.100.111:9333,172.16.100.106:9333 -ip="172.16.100.136" -max=100 -dataCenter=zw -rack=openstack-bj-zw-bgp5 -idleTimeout=30 -images.fix.orientation=true -ip.bind=0.0.0.0 -maxCpu=0 -port=8082 -read.redirect=true >>/root/volume2.out & 30 [root@seaweedfs-bj-zw-vm5 ~]# tail -30 volume1.out 31 I0605 05:28:44 23656 store.go:99] In dir /data/seaweedfs/volume1 adds volume:35 collection: replicaPlacement:000 ttl: 32 I0605 05:28:44 23656 volume_loading.go:82] loading index /data/seaweedfs/volume1/35.idx to memory readonly false 33 I0605 05:28:44 23656 store.go:103] add volume 35 34 I0605 22:36:02 23656 store.go:99] In dir /data/seaweedfs/volume1 adds volume:36 collection: replicaPlacement:000 ttl: 35 I0605 22:36:02 23656 volume_loading.go:82] loading index /data/seaweedfs/volume1/36.idx to memory readonly false 36 I0605 22:36:02 23656 store.go:103] add volume 36 37 I0605 22:36:02 23656 store.go:99] In dir /data/seaweedfs/volume1 adds volume:41 collection: replicaPlacement:000 ttl: 38 I0605 22:36:02 23656 volume_loading.go:82] loading index /data/seaweedfs/volume1/41.idx to memory readonly false 39 I0605 22:36:02 23656 store.go:103] add volume 41 40 I0605 22:36:02 23656 store.go:99] In dir /data/seaweedfs/volume1 adds volume:42 collection: replicaPlacement:000 ttl: 41 I0605 22:36:02 23656 volume_loading.go:82] loading index /data/seaweedfs/volume1/42.idx to memory readonly false 42 I0605 22:36:02 23656 store.go:103] add volume 42 43 I0606 04:03:13 23656 store.go:99] In dir /data/seaweedfs/volume1 adds volume:43 collection: replicaPlacement:000 ttl: 44 I0606 04:03:13 23656 volume_loading.go:82] loading index /data/seaweedfs/volume1/43.idx to memory readonly false 45 I0606 04:03:13 23656 store.go:103] add volume 43 46 I0606 09:42:43 23656 store.go:99] In dir /data/seaweedfs/volume1 adds volume:50 collection: replicaPlacement:000 ttl: 47 I0606 09:42:43 23656 volume_loading.go:82] loading index /data/seaweedfs/volume1/50.idx to memory readonly false 48 I0606 09:42:43 23656 store.go:103] add volume 50 49 I0606 09:42:43 23656 store.go:99] In dir /data/seaweedfs/volume1 adds volume:51 collection: replicaPlacement:000 ttl: 50 I0606 09:42:43 23656 volume_loading.go:82] loading index /data/seaweedfs/volume1/51.idx to memory readonly false 51 I0606 09:42:43 23656 store.go:103] add volume 51 52 I0606 09:42:43 23656 store.go:99] In dir /data/seaweedfs/volume1 adds volume:53 collection: replicaPlacement:000 ttl: 53 I0606 09:42:43 23656 volume_loading.go:82] loading index /data/seaweedfs/volume1/53.idx to memory readonly false 54 I0606 09:42:43 23656 store.go:103] add volume 53 55 I0606 14:23:03 23656 store.go:99] In dir /data/seaweedfs/volume1 adds volume:58 collection: replicaPlacement:000 ttl: 56 I0606 14:23:03 23656 volume_loading.go:82] loading index /data/seaweedfs/volume1/58.idx to memory readonly false 57 I0606 14:23:03 23656 store.go:103] add volume 58 58 I0606 14:23:03 23656 store.go:99] In dir /data/seaweedfs/volume1 adds volume:62 collection: replicaPlacement:000 ttl: 59 I0606 14:23:03 23656 volume_loading.go:82] loading index /data/seaweedfs/volume1/62.idx to memory readonly false 60 I0606 14:23:03 23656 store.go:103] add volume 62 61 [root@seaweedfs-bj-zw-vm5 ~]# du -sh /data/seaweedfs/volume1/* 62 30G /data/seaweedfs/volume1/23.dat 63 4.9M /data/seaweedfs/volume1/23.idx 64 30G /data/seaweedfs/volume1/29.dat 65 5.5M /data/seaweedfs/volume1/29.idx 66 30G /data/seaweedfs/volume1/33.dat 67 5.5M /data/seaweedfs/volume1/33.idx 68 30G /data/seaweedfs/volume1/34.dat 69 5.5M /data/seaweedfs/volume1/34.idx 70 30G /data/seaweedfs/volume1/35.dat 71 5.5M /data/seaweedfs/volume1/35.idx 72 30G /data/seaweedfs/volume1/36.dat 73 4.8M /data/seaweedfs/volume1/36.idx 74 30G /data/seaweedfs/volume1/41.dat 75 4.9M /data/seaweedfs/volume1/41.idx 76 30G /data/seaweedfs/volume1/42.dat 77 4.9M /data/seaweedfs/volume1/42.idx 78 30G /data/seaweedfs/volume1/43.dat 79 3.0M /data/seaweedfs/volume1/43.idx 80 30G /data/seaweedfs/volume1/50.dat 81 3.5M /data/seaweedfs/volume1/50.idx 82 30G /data/seaweedfs/volume1/51.dat 83 3.5M /data/seaweedfs/volume1/51.idx 84 30G /data/seaweedfs/volume1/53.dat 85 3.5M /data/seaweedfs/volume1/53.idx 86 8.1G /data/seaweedfs/volume1/58.dat 87 2.0M /data/seaweedfs/volume1/58.idx 88 7.9G /data/seaweedfs/volume1/62.dat 89 2.0M /data/seaweedfs/volume1/62.idx 90 咱们能够看错,每一个索引文件最大5M,数据文件30G,磁盘被分割成了不少的卷(idx+dat)
简单测试
如今的模式是master+ volume这种标准模式
1 [root@seaweedfs-bj-zw-vm5 ~]# curl http://172.16.100.107:9333/dir/assign 2 {"fid":"3,57f4e1898d66","url":"172.16.100.136:8082","publicUrl":"172.16. 100.136:8082","count":1} 3 [root@seaweedfs-bj-zw-vm5 ~]# curl -F file=@/root/9ee6c1c5d88b0468af1a3280865a6b7a.png http://172.16.100.136:8082/3,57f4e1898d66 4 [root@seaweedfs-bj-zw-vm5 ~]# wget 172.16.100.136:8082/3,57f4e1898d66 5 [root@seaweedfs-bj-zw-vm5 ~]# ls # 新下载下来的资源会被命名为fid 6 3,57f4e1898d66 7 [root@seaweedfs-bj-zw-vm5 ~]# curl -X DELETE 172.16.100.136:8082/3,57f4e1898d66 8 咱们能够看出流程是,找master节点申请ip:port及fid,本身拼接ip:port/fid,而后post上传,此时该资源到服务器上了,咱们能够对ip:port/fid进行get等请求 9 这里面有2点比较麻烦 10 1. 要先申请,再拼接,再上传 11 2. 要记录返回的ip:port/fid才能对该资源进行之后的操做,也就是3个信息 12 相对应的解决方式也是有的 13 1. curl -F file=@/root/9ee6c1c5d88b0468af1a3280865a6b7a.png http://172.16.100.107:9333/submit这样会直接上传(申请fid+上传) 14 2. wget 172.16.100.107:9333/3,57f4e1898d66咱们就直接访问master节点ip:port/fid,这样也是能够操做资源的,由于内部默认是开启了内部代理功能,咱们只须要记录fid就能够了
现实问题
在大部分中小企业中,你们一开始使用的都是nginx+nfs提供静态资源访问的模式,也就是nginx管理root路径,而root路径是外部挂载的大磁盘,而后咱们访问的时候就是url/资源路径模式。
它的优势在于
它的缺点主要仍是来源于规模带来的一些问题
解决方式
咱们天然是使用本次的seaweedfs做为图片服务器了,这样就能够对应解决咱们上述的问题
引出的问题
解决方式
filer节点
filer节点是能够在任何地方执行的,它再次打开了一个http服务,而且也对外提供restful api,只是咱们可使用url/文件路径的模式进行访问了(以前的url/fid依然生效),filer节点提供的http服务能够如同一个文件系统同样被挂载,在挂载点,咱们能够直观的看见目录层级(也是对象),及操做各个文件
1 [root@seaweedfs-bj-zw-vm1 ~]# /root/weed filer -master=172.16.100.111:9333,172.16.100.107:9333,172.16.100.106:9333 -ip=172.16.100.107 -defaultReplicaPlacement='000' -disableDirListing >>/root/filer.out & 2 [root@seaweedfs-bj-zw-vm1 ~]# /root/weed mount -filer=172.16.100.107:8888 -dir=/mnt >>/dev/null & 3 [root@seaweedfs-bj-zw-vm1 ~]# netstat -tpln|grep 8888 4 tcp 0 0 172.16.100.107:8888 0.0.0.0:* LISTEN 771/weed 5 tcp6 0 0 :::18888 :::* LISTEN 771/weed 6 [root@seaweedfs-bj-zw-vm1 ~]# df -h|grep mnt 7 SeaweedFS 1.3T 1.2T 48G 97% /mnt
访问的流程其实仍是,以路径模式操做---根据路径获取fid---以fid模式操做----seaweedfs,也就是路径跟fid之间filer节点帮你作了一次转换
在默认状况下这种对应关系是存放在内存当中,实际状况下,咱们须要安装一个记录关系的服务,如下是官方推荐的服务及其功能,咱们果断使用了熟悉的redis,redis的记录也很简单,就是最简单的string的kv对应关系,key是路径,value是fid(转义过的),固然其余存储的关系大概也能想来,数据库类的天然就是有一个表(这个表的sql在配置文件里都有),而后就是两个记录的字段便可
1 [root@seaweedfs-bj-zw-vm1 ~]# mkdir -p /etc/seaweedfs 2 [root@seaweedfs-bj-zw-vm1 ~]# cd /etc/seaweedfs 3 [root@seaweedfs-bj-zw-vm1 seaweedfs]# /root/weed scaffold filer -output=" filer.toml " 4 [root@seaweedfs-bj-zw-vm1 ~]# vim /etc/seaweedfs/filer.toml # 把redis的信息填好,若是使用其余后端,将其enabled改为true并填写相关信息便可 5 [redis] 6 enabled = true 7 address = "xxx:6379" 8 password = "" 9 db = 0
咱们重启filer服务后再次挂载,此时对应关系就会存在redis里了,我的已经放入1.T数据,大概1.5亿个key,在性能上彻底没问题
后期咱们不管是使用restful api,仍是在mount的目录直接进行操做,仍是在redis的库里直接操做,这三者操做都是一致的。例如咱们在redis上删除了某个路径的key,那么这个文件就会直接消失,所以保存关系的后端也要维护好哦,固然,若是redis挂了,那么filer功能就会崩溃,只能直接使用url/fid的模式
所以,使用filer来兼容以前nfs,咱们须要额外保证后端存储的可用性!