参考:
http://www.cnblogs.com/xiaocen/p/3721390.html
http://blog.csdn.net/21aspnet/article/details/6620723
注,本文有许多直接用了其中的图片,文字,但有很多更新修改 ,结合课程笔记,以及自己的实验做出此文
MogileFS 项目官方 wiki:
https://code.google.com/p/mogilefs/wiki
用作反向代理的 nginx 模块:
http://www.grid.net.ru/nginx/mogilefs.en.html
大纲
一、分布式文件系统
二、MogileFS 的实现
三、安装配置 mogilefsd和mogstored
四、安装及初始化 mysql
五、配置存储及上传文件测试
六、使用 nginx 反向代理 MogileFS
附录: nginx mogilefs 模块详解(翻译)
一、分布式文件系统
分布式文件系统(Distributed File System)是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点相连,也就是集群文件系统,可以支持大数量的节点以及PB级的数量存储。相对地,在一个分享的磁盘文件系统中,所有节点对数据存储区块都有相同的访问权,在这样的系统中,访问权限就必须由客户端程序来控制。
分布式文件系统可能包含的功能有:透通的数据复制与容错。也就是说,即使系统中有一小部份的节点脱机,整体来说系统仍然可以持续运作而不会有数据损失
1.1分布式文件系统的类别:
MogileFS | 适用于处理海量小文件,比如网站图片,使用 MySQL 存储元数据 |
---|---|
FastDFS | 适用于处理海量小文件,类似 MogileFS,但不使用 MySQL 存储元数据,在内存中存储。 |
Ceph | 是一个 Linux PB 级别的分布式文件系统 |
MooseFS | 通用简便,适用于研发能力不强的公司 |
Taobao Filesystem | 适用于处理海量小文件 |
GlusterFS | 适用于处理少量单个大文件,比如视频文件,比如云环境的虚拟机映像文件(用友科技的案例) |
Google Filesystem | GFS+MapReduce 擅长处理单个大文件 |
HDFS | HDFS(GFS的山寨版)+MapReduce |
GFS 构建的基础理论:
- MapReduce
- Bigtable: GFS 只支持文件增加和删除,不支持编辑,为解决这个问题,出现了 Bigtable
HDFS,即 Hadoop Distributed Filesystem,是GFS的山寨版,HDFS+MapReduce = Hadoop(平台,需要java编程调用其接口,运行于 Hadoop 平台之上),擅长处理单个大文件。
HBase 是基于 Bigtable 理论实现的列式 NoSQL 数据库。
分布式文件系统,一般日访问量PV千万级别时候使用。
一个分布式文件系统,是否适合处理海量文件,主要看 NameNode(存放文件元数据的节点)。MogileFS 不是直接在内存存放元数据,而是通过 MySQL 存储元数据,所以支持海量文件,但这对性能有影响。
二、MogileFS 的实现
MogileFS 是一个开源的分布式文件系统,用于组建分布式文件集群,由 LiveJournal 旗下 Danga Interactive 公司开发,Danga 团队开发了包括 Memcached、MogileFS、Perlbal 等不错的开源项目:(注:Perlbal 是一个强大的 Perl 写的反向代理服务器)。目前国内使用 MogileFS 的有图片托管网站 yupoo云 ,大众点评,安居客,豆瓣。
MogileFS 的优点:MogileFS是一个开源的分布式文件系统。主要特性包括:应用层的组件、无单点故障、自动文件复制、具有比RAID更好的可靠性、无需RAID支持等……核心角色如下:
tracker节点:借助数据库保存各节点文件的元数据信息,保存每个域中所有键的存储位置分布,方便检索定位数据位置,并且可监控各节点,告诉客户端存储区位置并指挥storage节点复制数据副本,进程名为mogilefsd(7001)。
mysql节点:为tracker节点提供数据存取服务。用于为tracker存储元数据信息;mogilefs的名称空间及文件名;
- storage节点:将指定域中的键转换为其特有的文件名存储在指定的设备文件中,转换后的文件名为值,storage节点自动维护键值的对应关系,storage节点由于使用http进行数据传输,因此依赖于perlbal。storage节点前端可以使用nginx进行反向代理,但需要安装nginx-mogilefs-module-master模块进行名称转换,进程名mogstored(7501),perbal(7500)。能完成文件的创建、删除、重命名。
Domain:一个域中的键值是惟一的,一个MogileFS可以有多个域,域是用来存储不同应用类型的数据的容器。
Host:每一个存储节点称为一个主机,一个主机上可以有多个存储设备(单独的硬盘),每个设备都有ID号,Domain+Fid用来定位文件。
Class:复制最小单位,文件属性管理,定义文件存储在不同设备上份数。
为什么 MogileFS 号称无单点?以为每个 tracker节点可以有多个,storage节点也可以有多个,mysql 我们可以自行建立高可用。每个服务器可以承担多个角色。
当 tracker 节点有多个的时候,我们需要对其做负载均衡,这里使用 nginx 做负载均衡。
MogileFS的特性:
- 1、用户空间文件系统(FUSE):无须特殊的核心组件;
- 2、无单点失败:
- 3、自动文件复制
- 4、比“RAID”好多了
- 5、传输中立,无特殊协议(HTTP,NFS)
- 6、命名空间较简单:每个文件对应于一个key;用于domain定义名称空间;
- 7、不依赖于任何共享存储设备;
MogileFS由3个部分组成:
第1个部分: 是server端,包括mogilefsd和mogstored两个程序。前者即是mogilefsd的tracker,它将一些全局信息保存在数据库里,例如站点domain,class,host等。后者即是存储节点(store node),它其实是个HTTP Daemon,默认侦听在7500端口,接受客户端的文件备份请求。在安装完后,要运行mogadm工具将所有的store node注册到mogilefsd的数据库里,mogilefsd会对这些节点进行管理和监控。
第2个部分:是utils(工具集),主要是MogileFS的一些管理工具,例如mogadm等。
第3个部分:是客户端API,目前只有Perl API(MogileFS.pm)、PHP,用这个模块可以编写客户端程序,实现文件的备份管理功能,提供MogileFS.pm。
实现MogileFS的分布式过程,按照下图构建MogileFS分布式文件系统的结构,这里限于机器的原因,一些服务都整合在一起;
逻辑结构如上:两个 mogilefsd 节点 + 两个 mogstored 节点,一个 mysql 节点,一个 nginx 节点
实验环境:
一共三台服务器,将 mysql 和 nginx 安装到同一台服务器上(192.168.0.171);另两台服务器都分别安装了 mogilefsd和mogstored两个程序。
操作系统:CentOS 6.8
nginx: 192.168.0.171
node1(Trackers+Stored): 192.168.0.181
node2(Trackers+Stored): 192.168.0.182
mysql: 192.168.0.171
三、安装配置 mogilefsd和mogstored
node1
在 node1上,使用打包好的 rpm 包安装:
[root@tomcat1 packages]# ls
MogileFS-Server-2.46-2.el6.noarch.rpm
MogileFS-Server-mogilefsd-2.46-2.el6.noarch.rpm
MogileFS-Server-mogstored-2.46-2.el6.noarch.rpm
MogileFS-Utils-2.19-1.el6.noarch.rpm
Perlbal-1.78-1.el6.noarch.rpm
Perlbal-doc-1.78-1.el6.noarch.rpm
perl-MogileFS-Client-1.14-1.el6.noarch.rpm
perl-Net-Netmask-1.9015-8.el6.noarch.rpm
perl-Perlbal-1.78-1.el6.noarch.rpm
注,这些包不是官方提供的,官方的安装方法是使用 cpan,本文顶部给出的官方链接,其中有文档,我试过安装,安装过程较耗时间。
安装 MogileFS,这里直接 yum 安装所有 rpm 包:
# cd packages
# yum install *
mogstored 的运行需要 perl-IO-AIO
yum install perl-IO-AIO
编辑 mogilefsd和mogstored 的配置文件
配置 mogilefsd:
安装好之后修改配置文件,只需要修改以下几项就可以了
mysql指使用的数据库是什么,MariaDB也是写mysql;mogdb指数据库名;host=192.168.0.171指定安装数据的地址
[root@tomcat1 ~]# vi /etc/mogilefs/mogilefsd.conf
# Database connection information
db_dsn = DBI:mysql:mogdb:host=192.168.0.171
db_user = moguser # 指登录mogdb数据所使用的用户名
db_pass = guli123 # 登录mogdb数据所使用密码
listen = 0.0.0.0:7001 # 0.0.0.0表示监听所有地址
配置 mogilestored:
准备存储设备挂载至 /dfs/mogdata 目录下,确认此路径下存在目录devN,N 为 device id。
此路径的属主和属组为mogilefs.mogilefs
再编辑 mogstored.conf 这个配置文件
[root@tomcat1 ~]# vi /etc/mogilefs/mogstored.conf
maxconns = 10000
httplisten = 0.0.0.0:7500
mgmtlisten = 0.0.0.0:7501
docroot = /dfs/mogdata # 把这项改一个特定的目录,以便存储数据,最好是一个独立分区
创建数据目录:
[root@node1 ~]# mkdir -pv /dfs/mogdata/dev1 # 创建修改的docroot目录
[root@node1 ~]# chown -R mogilefs.mogilefs /dfs/mogdata/dev1 # 修改属主属组
[root@node1 ~]# chown -R mogilefs.mogilefs /var/run/mogilefsd/
[root@node1 ~]# cd /etc/mogilefs
[root@node1 ~]# scp mogilefsd.conf mogstored.conf root@192.168.0.181:/etc/mogilefs/
node2
node2 也使用 yum install * 安装。
# cd /root/packages
# ls
MogileFS-Server-2.46-2.el6.noarch.rpm
MogileFS-Server-mogilefsd-2.46-2.el6.noarch.rpm
MogileFS-Server-mogstored-2.46-2.el6.noarch.rpm
MogileFS-Utils-2.19-1.el6.noarch.rpm
Perlbal-1.78-1.el6.noarch.rpm
Perlbal-doc-1.78-1.el6.noarch.rpm
perl-MogileFS-Client-1.14-1.el6.noarch.rpm
perl-Net-Netmask-1.9015-8.el6.noarch.rpm
perl-Perlbal-1.78-1.el6.noarch.rpm
# yum install *
mogstored 的运行需要 perl-IO-AIO
yum install perl-IO-AIO
创建 docroot 目录及权限配置:
[root@node2 ~]# mkdir -pv /dfs/mogdata/dev2 # 创建修改的docroot目录
[root@node1 ~]# chown -R mogilefs.mogilefs /var/run/mogilefsd/
[root@node2 ~]# chown -R mogilefs.mogilefs /dfs/mogdata/dev3 # 修改属主属组
复制修改好的两个配置文件到node2的mogilefs目录下,覆盖即可,两个节点都安装配置好之后先不要启动服务,数据库还没有安装。
注,node1 上的数据目录是 /dfs/mogdata/dev1;node2 上的目录是 /dfs/mogdata/dev3;这里的 1 和 3 是设备id,一会添加设备时会使用,设备id对于这里的一个 dev# 目录,# 是设备id号。
四、安装及初始化 mysql
在 192.168.0.171 节点上安装 mysql,我们这里直接 yum 安装
yum install mysql-server mysql
启动 mysql:
service mysqld start
修改 root 密码为 guli123
[root@vm1 src]# mysqladmin -u root password 'guli123'
登陆并创建用户:
# mysql -uroot -p
mysql> GRANT ALL ON *.* TO 'root'@'192.168.%.%' IDENTIFIED BY 'guli123';
mysql> GRANT ALL ON mogdb.* TO 'moguser'@'192.168.%.%' IDENTIFIED BY 'guli123';
mysql> FLUSH PRIVILEGES;
2、在两个节点上,在其中一个上设置即可,授权数据库用户,并初始化 mysql 数据库(会自动创建 mogdb 库)
# mogdbsetup --dbhost=192.168.0.171 \
--dbport=3306 \
--dbname=mogdb \
--dbrootuser=root \
--dbrootpass=guli123 \
--dbuser=moguser \
--dbpass=guli123 \
--yes
去数据库查看:
mysql> use mogdb
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+----------------------+
| Tables_in_mogdb |
+----------------------+
| checksum |
| class |
| device |
| domain |
| file |
| file_on |
| file_on_corrupt |
| file_to_delete |
| file_to_delete2 |
| file_to_delete_later |
| file_to_queue |
| file_to_replicate |
| fsck_log |
| host |
| server_settings |
| tempfile |
| unreachable_fids |
+----------------------+
17 rows in set (0.00 sec)
五、配置存储
使用 modadm 工具设置存储,为此需要先运行 mogilefsd。
启动 mogilefsd
启动 mogstored:
以 root 执行命令:
# mogstored --daemon
启动 mogilefsd
# su mogile
$ mogilefsd -c /etc/mogilefs/mogilefsd.conf --daemon
$ exit
或者。。
rpm 包里面自带了脚本,可以直接使用:
service mogilefsd start
脚本为:
[root@vm2 packages]# cat /etc/init.d/mogilefsd
#!/bin/bash
# Author: MageEdu <linuxedu@foxmail.com>
# mogilefsd - Startup script for the MogileFS tracker
#
# chkconfig: - 85 15
# description: MogileFS tracker
# processname: mogilefsd
# config: /etc/mogilefs/mogilefsd.conf
# pidfile: /var/run/mogilefsd/mogilefsd.pid
# Source function library.
. /etc/rc.d/init.d/functions
# Path to the apachectl script, server binary, and short-form for messages.
lockfile=${LOCKFILE-/var/lock/subsys/mogilefsd}
RETVAL=0
prog=$(which mogilefsd)
start() {
ulimit -n 65535
echo -n $"Starting mogilefsd"
su - mogilefs -c "$prog -c /etc/mogilefs/mogilefsd.conf --daemon" &> /dev/null
RETVAL=$?
[ $RETVAL = 0 ] && success && touch ${lockfile} || failure
echo
return $RETVAL
}
stop() {
echo -n $"Stopping mogilefsd"
netstat -nlp|grep "mogilefsd"|grep -v grep|awk '{print $7}'|awk -F"/" '{print $1}'|xargs kill -9
RETVAL=$?
[ $RETVAL = 0 ] && success && rm -f ${lockfile} || failure
echo
}
reload() {
echo -n $"Reloading mogilefsd: "
killall mogilefsd -HUP
RETVAL=$?
[ $RETVAL = 0 ] && success || failure
echo
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status mogilefsd
RETVAL=$?
;;
restart)
stop
sleep 1
start
;;
reload)
reload
;;
*)
echo $"Usage: mogilefsd {start|stop|restart|reload|status}"
exit 1
esac
exit $RETVAL
查看启动的情况:
[root@vm2 packages]# ps -ef | grep mogilefs
mogilefs 1297 1 0 16:00 ? 00:00:00 mogilefsd
mogilefs 1299 1297 0 16:00 ? 00:00:00 mogilefsd [monitor]
mogilefs 1300 1297 0 16:00 ? 00:00:00 mogilefsd [replicate]
mogilefs 1301 1297 0 16:00 ? 00:00:00 mogilefsd [replicate]
mogilefs 1302 1297 0 16:00 ? 00:00:00 mogilefsd [replicate]
mogilefs 1303 1297 0 16:00 ? 00:00:00 mogilefsd [replicate]
mogilefs 1304 1297 0 16:00 ? 00:00:00 mogilefsd [replicate]
mogilefs 1305 1297 0 16:00 ? 00:00:00 mogilefsd [delete]
mogilefs 1306 1297 0 16:00 ? 00:00:00 mogilefsd [queryworker]
mogilefs 1307 1297 0 16:00 ? 00:00:00 mogilefsd [queryworker]
mogilefs 1308 1297 0 16:00 ? 00:00:00 mogilefsd [queryworker]
mogilefs 1309 1297 0 16:00 ? 00:00:00 mogilefsd [queryworker]
mogilefs 1310 1297 0 16:00 ? 00:00:00 mogilefsd [queryworker]
mogilefs 1311 1297 0 16:00 ? 00:00:00 mogilefsd [queryworker]
mogilefs 1312 1297 0 16:00 ? 00:00:00 mogilefsd [queryworker]
mogilefs 1313 1297 0 16:00 ? 00:00:00 mogilefsd [queryworker]
mogilefs 1314 1297 0 16:00 ? 00:00:00 mogilefsd [queryworker]
mogilefs 1315 1297 0 16:00 ? 00:00:00 mogilefsd [queryworker]
mogilefs 1316 1297 0 16:00 ? 00:00:00 mogilefsd [reaper]
mogilefs 1317 1297 0 16:00 ? 00:00:00 mogilefsd [fsck]
mogilefs 1318 1297 0 16:00 ? 00:00:00 mogilefsd [job_master]
root 1342 1209 0 16:02 pts/0 00:00:00 grep mogilefs
启动 mogstored
可以直接启动:
[root@vm2 mogilefs]# mogstored --daemon
也可以使用脚本启动,脚本为:
[root@vm2 mogilefs]# cat /etc/init.d/mogstored
#!/bin/bash
# Author: MageEdu <linuxedu@foxmail.com>
# mogstored - Startup script for the MogileFS storage
#
# chkconfig: - 86 14
# description: MogileFS storage
# processname: mogstored
# config: /etc/mogilefs/mogstored.conf
# pidfile: /var/run/mogilefsd/mogstored.pid
# Source function library.
. /etc/rc.d/init.d/functions
# Path to the apachectl script, server binary, and short-form for messages.
lockfile=${LOCKFILE-/var/lock/subsys/mogstored}
RETVAL=0
configfile='/etc/mogilefs/mogstored.conf'
prog=$(which mogstored)
start() {
ulimit -n 65535
echo -n $"Starting mogstored"
su - mogilefs -c "$prog -c $configfile --daemon" &> /dev/null
RETVAL=$?
[ $RETVAL = 0 ] && success && touch ${lockfile} || failure
echo
return $RETVAL
}
stop() {
echo -n $"Stopping mogstored"
netstat -nlp|grep "mogstored"|grep -v grep|awk '{print $7}'|awk -F"/" '{print $1}'|xargs kill -9
RETVAL=$?
[ $RETVAL = 0 ] && success && rm -f ${lockfile} || failure
echo
}
reload() {
echo -n $"Reloading mogstored: "
killall mogstored -HUP
RETVAL=$?
[ $RETVAL = 0 ] && success || failure
echo
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status mogstored
RETVAL=$?
;;
restart)
stop
sleep 1
start
;;
reload)
reload
;;
*)
echo $"Usage: mogstored {start|stop|restart|reload|status}"
exit 1
esac
exit $RETVAL
启动后查看:
[root@vm2 mogilefs]# ss -nlt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:7500 *:*
LISTEN 0 128 *:7501 *:*
设置 host
查看 host 相关命令:
[root@vm2 ~]# mogadm host
Help for 'host' command:
(enter any command prefix, leaving off options, for further help)
mogadm host add <hostname> [opts] Add a host to MogileFS.
mogadm host delete <hostname> Delete a host.
mogadm host list List all hosts.
mogadm host mark <hostname> <status> Change the status of a host. (equivalent to 'modify --status')
mogadm host modify <hostname> [opts] Modify a host's properties.
添加两个存储主机:mogstorage1,mogstorage1
mogadm --trackers=192.168.0.181:7001 host add mogstorage1 --ip=192.168.0.181 --status=alive
mogadm --trackers=192.168.0.181:7001 host add mogstorage2 --ip=192.168.0.182 --status=alive
另外一些操作:
mogadm --trackers=192.168.0.181:7001 host del mogstorage1 # 有设备时不能删除
mogadm --trackers=192.168.0.181:7001 host modify <hostname> --status={alive|down} # 修改 host 状态
检查是否添加上了存储主机:
# mogadm --trackers=192.168.0.181:7001 host list
mogstorage1 [1]: alive
IP: 192.168.0.181:7500
mogstorage2 [2]: alive
IP: 192.168.0.182:7500
给存储主机添加设备
设备相关命令:
[root@vm2 ~]# mogadm device
Help for 'device' command:
(enter any command prefix, leaving off options, for further help)
mogadm device add <hostname> <devid> [opts] Add a device to a host.
mogadm device list [opts] List all devices, for each host.
mogadm device mark <hostname> <devid> <status> Mark a device as {alive,dead,down,drain,readonly}
mogadm device modify <hostname> <devid> [opts] Modify a device's properties.
mogadm device summary [opts] List the summary of devices, for each host.
注,这里很奇怪,没有 device delete 命令,在 man mogamd 手册中是有的。后来实验发现确实不能删除设备。
我们需要给每个存储主机添加设备,这里需要自己指定一个设备id,我们简单设置为 1,3:
mogadm --trackers=192.168.0.181:7001 device add mogstorage1 1
mogadm --trackers=192.168.0.181:7001 device add mogstorage2 3
查看 device 列表:mogadm --trackers=192.168.0.181:7001 device list
[root@vm2 ~]# mogadm --trackers=192.168.0.181:7001 device list
mogstorage1 [1]: alive
used(G) free(G) total(G) weight(%)
dev1: alive 2.554 3.591 6.145 100
mogstorage2 [2]: alive
used(G) free(G) total(G) weight(%)
dev3: alive 1.296 4.849 6.145 100
另外一些操作:
mogadm device modify <hostname> <devid> --status={alive,dead,down,drain,readonly} # 设定设备的状态,为 dead 时,会从设备列表中删除
mogadm device modify <hostname> <devid> --weight=i # 设定设备的权重
设置 domain
domain 相关命令:
[root@vm2 ~]# mogadm domain
Help for 'domain' command:
(enter any command prefix, leaving off options, for further help)
mogadm domain add <domain> Add a domain (namespace)
mogadm domain delete <domain> Delete a domain.
mogadm domain list List all hosts.
我们添加三个 domain,分别为 images, files, html:
mogadm --trackers=192.168.0.181:7001 domain add images
mogadm --trackers=192.168.0.181:7001 domain add files
mogadm --trackers=192.168.0.181:7001 domain add html
查看设置情况:
[root@vm2 ~]# mogadm domain list
domain class mindevcount replpolicy hashtype
-------------------- -------------------- ------------- ------------ -------
files default 2 MultipleHosts() NONE
html default 2 MultipleHosts() NONE
images default 2 MultipleHosts() NONE
设置 class
class 相关命令:
[root@vm2 ~]# mogadm class
Help for 'class' command:
(enter any command prefix, leaving off options, for further help)
mogadm class add <domain> <class> [opts] Add a file class to a domain.
mogadm class delete <domain> <class> Delete a file class from a domain.
mogadm class list List all classes, for each domain.
mogadm class modify <domain> <class> [opts] Modify properties of a file class.
看看 mogadm class add 的设置命令
[root@vm2 ~]# mogadm class add
ERROR: Missing argument 'domain'
Help for 'class-add' command:
mogadm class add <domain> <class> [opts] Add a file class to a domain.
<class> Name of class to add.
<domain> Domain to add class to.
--hashtype=s Hash algorithm string ('MD5', 'NONE').
--mindevcount=i Minimum number of replicas.
--replpolicy=s Replication policy string.
这里看到可设置的选项,其中 --mindevcoun 是一份存储要复制的份数(>=1),一般设置为 3,这里因为我们只有两个存储节点,所以设置为 2。
在 images 域中新建一个 class:
mogadm --trackers=192.168.0.181:7001 class add images class0 --mindevcoun=2
查看设置情况:
[root@vm2 ~]# mogadm class list
domain class mindevcount replpolicy hashtype
-------------------- -------------------- ------------- ------------ -------
files default 2 MultipleHosts() NONE
html default 2 MultipleHosts() NONE
images class0 2 MultipleHosts() NONE
images default 2 MultipleHosts() NONE
这里除了我们设置的 class0,每个域中都有一个叫做 default 的 class,各自的 mindevcount 都为 2。
上传文件:
使用 mogupload 上传文件,相关命令使用方法是:
[root@vm2 ~]# mogupload
Usage: /usr/bin/mogupload --trackers=host --domain=foo --key='/hello.jpg' --file='./hello.jpg'
这里指定了 domain,存储的键,以及要存储的文件的路径,但没指定 --class,这就会使用默认的 default class。
我们上传几张图片和html文件上去:
/usr/share/nginx/html/50x.html
/usr/share/nginx/html/index.html
mogupload --trackers=192.168.0.181:7001 --domain=images --key="1.jpg" --file=/root/p936066463.jpg
mogupload --trackers=192.168.0.181:7001 --domain=images --key="2.jpg" --file=/root/p936066738.jpg
mogupload --trackers=192.168.0.181:7001 --domain=html --key="1.html" --file=/usr/share/nginx/html/index.html
mogupload --trackers=192.168.0.181:7001 --domain=html --key="2.html" --file=/usr/share/nginx/html/50x.html
mogupload --trackers=192.168.0.181:7001 --domain=files --key="1.file" --file=/root/epel-release-6-8.noarch.rpm
查看上传情况:
[root@tomcat1 ~]# moglistkeys --trackers=192.168.0.181:7001 --domain=images
1.jpg
2.jpg
[root@tomcat1 ~]# moglistkeys --trackers=192.168.0.181:7001 --domain=files
1.file
[root@tomcat1 ~]# moglistkeys --trackers=192.168.0.181:7001 --domain=html
1.html
2.html
查看一个 key=1.jpg 的详细信息:
# mogfileinfo --trackers=192.168.0.181:7001 --domain=images --key='1.jpg'
- file: 1.jpg
class: default
devcount: 2
domain: images
fid: 9
key: 1.jpg
length: 68326
- http://192.168.0.181:7500/dev1/0/000/000/0000000009.fid
- http://192.168.0.182:7500/dev3/0/000/000/0000000009.fid
可在浏览器访问一下 http://192.168.0.181:7500/dev1/0/000/000/0000000009.fid
:
查看一个 key=1.html 的详细信息:
[root@tomcat1 ~]# mogfileinfo --trackers=192.168.0.181:7001 --domain=html --key='1.html'
- file: 1.html
class: default
devcount: 2
domain: html
fid: 6
key: 1.html
length: 612
- http://192.168.0.182:7500/dev3/0/000/000/0000000006.fid
html 类的文件通过浏览器访问,会返回文件的源代码:
<!DOCTYPE html>
<html>
<head>
<title>Error</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>An error occurred.</h1>
<p>Sorry, the page you are looking for is currently unavailable.<br/>
Please try again later.</p>
<p>If you are the system administrator of this resource then you should check
the <a href="http://nginx.org/r/error_log">error log</a> for details.</p>
<p><em>Faithfully yours, nginx.</em></p>
</body>
</html>
查看 rpm 包:
[root@tomcat1 ~]# mogfileinfo --trackers=192.168.0.181:7001 --domain=files --key='1.file'
- file: 1.file
class: default
devcount: 2
domain: files
fid: 8
key: 1.file
length: 14540
- http://192.168.0.181:7500/dev1/0/000/000/0000000008.fid
- http://192.168.0.182:7500/dev3/0/000/000/0000000008.fid
我们上传了一个 rpm 包,使用浏览器访问会直接下载文件。
检查总体状态:
[root@tomcat1 ~]# mogadm --trackers=192.168.0.181:7001,192.168.0.182:7001 check
Checking trackers...
192.168.0.181:7001 ... OK
192.168.0.182:7001 ... OK
Checking hosts...
[ 1] mogstorage1 ... OK
[ 2] mogstorage2 ... OK
Checking devices...
host device size(G) used(G) free(G) use% ob state I/O%
---- ------------ ---------- ---------- ---------- ------ ---------- -----
[ 1] dev1 6.145 2.555 3.590 41.57% writeable N/A
[ 2] dev3 6.145 1.297 4.848 21.10% writeable N/A
---- ------------ ---------- ---------- ---------- ------
total: 12.290 3.851 8.438 31.34%
六、使用 nginx 反向代理 MogileFS
环境准备:
yum -y groupinstall "Development Tools" "Server Platform Development"
yum -y install openssl-devel pcre-devel
groupadd -r nginx
useradd -r -g nginx nginx
nginx 下载:
wget http://nginx.org/download/nginx-1.10.1.tar.gz
模块下载:
wget http://www.grid.net.ru/nginx/download/nginx_mogilefs_module-1.0.4.tar.gz
解压安装:
[root@vm1 src]# tar -xf nginx_mogilefs_module-1.0.4.tar.gz
[root@vm1 src]# tar -xf nginx-1.10.1.tar.gz
[root@vm1 src]# cd nginx-1.10.1
[root@vm1 nginx-1.10.1]# ./configure --prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--http-client-body-temp-path=/var/cache/nginx/client_temp \
--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_stub_status_module \
--with-http_slice_module \
--with-file-aio \
--with-http_v2_module \
--with-ipv6 \
--with-stream \
--with-stream_ssl_module \
--with-http_auth_request_module \
--add-module=/src/nginx_mogilefs_module-1.0.4 #模块的父目录
[root@vm1 nginx-1.10.1]# make && make install
注,测试发现一旦携带 --with-threads 参数,在 nginx_mogilefs_module 这里就出现编译错误
注,对于如下编译选项,make install 不会为其自动创建目录,需要我们自行创建,如果不创建启动 nginx 会报错:
--http-client-body-temp-path=/var/cache/nginx/client_temp \
--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
[root@vm1 nginx-1.10.1]# nginx
Starting nginx: nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed (2: No such file or directory)
方法一:
mkdir -p /var/cache/nginx/{client_temp,proxy_temp,fastcgi_temp,uwsgi_temp,scgi_temp}
chown -R nginx:nginx /var/cache/nginx/
方法二:在启动脚本中加入如下函数,它会自动检测 nginx 的编译选项,提取含有 -temp-path 的选项,创建对应的目录,并且修改权限。可让 start() 函数调用 make_dirs() 函数,让其在每次启动 nginx 之前检测是否有对应的目录。
make_dirs() {
# make required directories
user=`nginx -V 2>&1 | grep "configure arguments:" | sed 's/[^*]*--user=\([^ ]*\).*/\1/g' -`
options=`$nginx -V 2>&1 | grep 'configure arguments:'`
for opt in $options; do
if [ `echo $opt | grep '.*-temp-path'` ]; then
value=`echo $opt | cut -d "=" -f 2`
if [ ! -d "$value" ]; then
# echo "creating" $value
mkdir -p $value && chown -R $user $value
fi
fi
done
}
这里为简单起见,选择方法一,进行手动创建,然后测试启动一下:
[root@vm1 nginx-1.10.1]# nginx
[root@vm1 nginx-1.10.1]# ss -nlt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:80 *:*
LISTEN 0 128 :::22 :::*
LISTEN 0 128 *:22 *:*
LISTEN 0 100 ::1:25 :::*
LISTEN 0 100 127.0.0.1:25 *:*
测试访问:
[root@vm1 nginx-1.10.1]# curl -I 127.0.0.1
HTTP/1.1 200 OK
Server: nginx/1.10.1
Date: Wed, 17 Aug 2016 03:23:16 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Wed, 17 Aug 2016 02:53:16 GMT
Connection: keep-alive
ETag: "57b3d19c-264"
Accept-Ranges: bytes
然后我们准备一个 /etc/init.d/nginx 脚本,方便调用:
[root@vm1 nginx]# cat /etc/init.d/nginx
#!/bin/sh
#
# nginx Startup script for nginx
#
# chkconfig: - 85 15
# processname: nginx
# config: /etc/nginx/nginx.conf
# config: /etc/sysconfig/nginx
# pidfile: /var/run/nginx.pid
# description: nginx is an HTTP and reverse proxy server
#
### BEGIN INIT INFO
# Provides: nginx
# Required-Start: $local_fs $remote_fs $network
# Required-Stop: $local_fs $remote_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start and stop nginx
### END INIT INFO
# Source function library.
. /etc/rc.d/init.d/functions
if [ -L $0 ]; then
initscript=`/bin/readlink -f $0`
else
initscript=$0
fi
sysconfig=`/bin/basename $initscript`
if [ -f /etc/sysconfig/$sysconfig ]; then
. /etc/sysconfig/$sysconfig
fi
nginx=${NGINX-/usr/sbin/nginx}
prog=`/bin/basename $nginx`
conffile=${CONFFILE-/etc/nginx/nginx.conf}
lockfile=${LOCKFILE-/var/lock/subsys/nginx}
pidfile=${PIDFILE-/var/run/nginx.pid}
SLEEPMSEC=${SLEEPMSEC-200000}
UPGRADEWAITLOOPS=${UPGRADEWAITLOOPS-5}
RETVAL=0
start() {
echo -n $"Starting $prog: "
daemon --pidfile=${pidfile} ${nginx} -c ${conffile}
RETVAL=$?
echo
[ $RETVAL = 0 ] && touch ${lockfile}
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
killproc -p ${pidfile} ${prog}
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile}
}
reload() {
echo -n $"Reloading $prog: "
killproc -p ${pidfile} ${prog} -HUP
RETVAL=$?
echo
}
upgrade() {
oldbinpidfile=${pidfile}.oldbin
configtest -q || return
echo -n $"Starting new master $prog: "
killproc -p ${pidfile} ${prog} -USR2
echo
for i in `/usr/bin/seq $UPGRADEWAITLOOPS`; do
/bin/usleep $SLEEPMSEC
if [ -f ${oldbinpidfile} -a -f ${pidfile} ]; then
echo -n $"Graceful shutdown of old $prog: "
killproc -p ${oldbinpidfile} ${prog} -QUIT
RETVAL=$?
echo
return
fi
done
echo $"Upgrade failed!"
RETVAL=1
}
configtest() {
if [ "$#" -ne 0 ] ; then
case "$1" in
-q)
FLAG=$1
;;
*)
;;
esac
shift
fi
${nginx} -t -c ${conffile} $FLAG
RETVAL=$?
return $RETVAL
}
rh_status() {
status -p ${pidfile} -b ${nginx} ${nginx}
}
# See how we were called.
case "$1" in
start)
rh_status >/dev/null 2>&1 && exit 0
start
;;
stop)
stop
;;
status)
rh_status
RETVAL=$?
;;
restart)
configtest -q || exit $RETVAL
stop
start
;;
upgrade)
rh_status >/dev/null 2>&1 || exit 0
upgrade
;;
condrestart|try-restart)
if rh_status >/dev/null 2>&1; then
stop
start
fi
;;
force-reload|reload)
reload
;;
configtest)
configtest
;;
*)
echo $"Usage: $prog {start|stop|restart|condrestart|try-restart|force-reload|upgrade|reload|status|help|configtest}"
RETVAL=2
esac
exit $RETVAL
而后为此脚本赋予执行权限:
# chmod +x /etc/rc.d/init.d/nginx
配置 nginx.conf
下面我们要编辑 nginx.conf 文件,关于 mogilefs 模块的使用方法,参考最后关于 nginx_mogilefs 模块的小节。
这里给出一份简单的 nginx 配置:
[root@vm1 nginx]# cat /etc/nginx/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream mogcluster {
server 192.168.0.182:7001;
server 192.168.0.181:7001;
}
server {
listen 80;
server_name localhost;
location /images/ {
mogilefs_tracker mogcluster;
mogilefs_domain images; # 指定 domain
mogilefs_pass {
proxy_pass $mogilefs_path;
proxy_hide_header Content-Type;
proxy_buffering off;
}
}
}
}
根据这个配置,如果访问:http://192.168.0.171/images/2.jpg,mogilefs 模块会用 2.jpg 为 key 向 MogileFS 请求文件。这个 key 的得出是用 URI - /images/ 得到的,也就是用请求 URI 减去与 location 名称匹配的部分得到的。
这是 mogilefs_pass 没有明确指定 key 时,默认的一种计算得出 key 的规则。实际上 mogilefs_pass 也可以明确指定 key,像下面这样:
location ~* ^/images/(.*)$ {
mogilefs_tracker mogcluster;
mogilefs_domain images;
mogilefs_pass $1 {
proxy_pass $mogilefs_path;
proxy_hide_header Content-Type;
proxy_buffering off;
}
}
这里使用了正则表达式匹配,匹配的结果保存在 $1 变量中,用这一部分作为 key 向 MogileFS 发起请求。
我们之前上传了一些文件,我们查看一下上传情况:
[root@tomcat1 ~]# moglistkeys --trackers=192.168.0.181:7001 --domain=images
1.jpg
2.jpg
[root@tomcat1 ~]# moglistkeys --trackers=192.168.0.181:7001 --domain=files
1.file
[root@tomcat1 ~]# moglistkeys --trackers=192.168.0.181:7001 --domain=html
1.html
2.html
对 MogileFS 的请求是要看不同的 domain 的,在 domain 里,key 是唯一的。在上面的配置中我们用 mogilefs_domain 指令指定了 images domain。
用浏览器访问测试一下:http://192.168.0.171/images/2.jpg
最后附上nginx mogilefs 模块的详解。
附录: nginx mogilefs 模块详解(翻译)
http://www.grid.net.ru/nginx/mogilefs.en.html
nginx mogilefs 模块是专为 nginx web server 打造的 MogileFS 客户端。
nginx 使用这个模块,可对 MogileFS 的 trackers 发起查询,trackers 返回文件的路径,nginx 使用第一个路径去获取文件。
mogilefs_tracker 指定 MogileFS 的 trackers
mogilefs_pass 指定文件的 key
如果 trackers 没有找到文件,nginx 返回 "404 Not found"
如果 trackers 找到了文件,但是 trackers 没有返回文件访问路径,nginx 返回 "503 Service unavailable"
如果 trackers 返回成功响应,nginx 使用这个模块尝试根据优先级最高的文件路径获取文件。
配置指令
syntax: mogilefs_pass [<key>] {<fetch block>}
default: none
severity: mandatory
context: server, location, limit_except
mogilefs_pass 指定请求文件的 key。key 可以包含任意变量。如果没有给出 key,默认使用 URI 一部分作为 key。URI 减去 与 location 匹配的部分,剩下的部分为 key。
location /download/ {
mogilefs_pass {
[...]
}
}
对于这个例子,如果请求 URI 为 /download/example.jpg,key 为 example.jpg。
mogilefs_pass 区块被称为 fetch 区块,在其中包含关于一些配置,当 nginx 从 MogileFS 的存储节点获取文件时,会使用这些配置。
$mogilefs_path 变量包含了文件的绝对 URL 路径。
fetch 区块会创建一个隐藏的内部 location,location 名为 /mogilefs_fetch_XXXXXXXX
,当 trackers 返回成功响应时,会进行重定向。
$mogilefs_path1 ~ $mogilefs_path9 包含备份文件的 URL。
syntax: mogilefs_methods <[[method 1] method 2 ... ]>
default: GET
severity: optional
context: main, server, location
mogilefs_methods 指定允许的访问 MogileFS 的方法,可以指定多个。
GET 是默认方法,表示从 MogileFS 获取资源
PUT 表示创建或替换
DELETE 表示删除
syntax: mogilefs_domain <domain>
default: default
severity: optional
context: main, server, location
mogilefs_domain 指定查询哪个 MogileFS 域。可以包含变量。
默认查询 default 域。
syntax: mogilefs_class <class0> [ <class1> [ ... ] ]
default: N/A
severity: optional
context: main, server, location
This directive specifies what to use as "class" parameter when making a request to tracker. The arguments of this directives will be evaluated and first non-empty value will be used as class. Arguments can contain variables.
mogilefs_class 指定查询时的 class 参数。
syntax: mogilefs_tracker <IP|IP:port|upstream>
default: none
severity: mandatory
context: main, server, location
Specifies address of MogileFS tracker to query.
mogilefs_tracker 指定 MogileFS tracker 的访问地址。
syntax: mogilefs_noverify <on/off>
default: off
severity: optional
context: main, server, location
Enables sending of noverify argument to MogileFS.
syntax: mogilefs_connect_timeout <time>
default: 60s
severity: optional
context: main, server, location
Specifies a timeout to be used to connect to mogilefs tracker. Could not be longer than 75 seconds.
指定连接 tracker 的超时时间,最大不超过 75s。
syntax: mogilefs_send_timeout <time>
default: 60s
severity: optional
context: main, server, location
Specifies a timeout to be used to send data to mogilefs tracker. If no data will be received by mogilefs tracker during this time interval, nginx will close the connection.
发送数据到 tracker 的超时时间。
syntax: mogilefs_read_timeout <time>
default: 60s
severity: optional
context: main, server, location
Specifies a timeout to be used to receive data from mogilefs tracker. If no data will be sent by mogilefs tracker during this time interval, nginx will close the connection.
从 tracker 读取数据的超时时间。
nginx 配置示例
error_log logs/error.log notice;
working_directory /usr/local/nginx;
http {
include mime.types;
default_type application/octet-stream;
server {
listen 80;
#
# This location could be used to retrieve files from MogileFS.
# It is publicly available.
#
location /download/ { # 获取文件
#
# Query tracker at 192.168.2.2 for a file with the key
# equal to remaining part of request URI
#
mogilefs_tracker 192.168.2.2;
mogilefs_domain example_domain;
mogilefs_pass {
proxy_pass $mogilefs_path;
proxy_hide_header Content-Type;
proxy_buffering off;
}
}
#
# This location could be used to store or delete files in MogileFS.
# It may be configured to be accessable only from local network.
#
location /upload/ { # 上传或删除文件
allow 192.168.2.0/24;
deny all;
mogilefs_tracker 192.168.2.2;
mogilefs_domain example_domain;
mogilefs_methods PUT DELETE;
mogilefs_pass {
proxy_pass $mogilefs_path;
proxy_hide_header Content-Type;
proxy_buffering off;
}
}
}
}
使用要求
nginx 0.7.1 或以上版本
下载地址:
Latest version 1.0.4:
http://www.grid.net.ru/nginx/download/nginx_mogilefs_module-1.0.4.tar.gz
MD5:2466aa02b225ad2aa1af22e6e50a9d2f
SHA1:4f6b774096a77aa8c550d8fd6a3f5d39a661d8ed
http://www.grid.net.ru/nginx/download/nginx_mogilefs_module-1.0.4.zip
MD5:4667d8b805aa4ecc94c7353d79a1020a
SHA1:8d86fa4f0fcb60cdd73195f77fbadf45ac51a875
或者这里:http://www.grid.net.ru/nginx/download
使用方法
下载文件之后,解压:
tar xvzf nginx_mogilefs_module-1.0.4.tar.gz
nginx 需要在编译安装时加入这个模块:
cd <path to nginx sources>
./configure --add-module=<path to mogilefs module sources> # 模块文件的父目录
make
make install
Licence
The above-described module is an addition to nginx web-server, nevertheless they are independent products. The licence of above-described module is BSD You should have received a copy of license along with the source code. By using the materials from this site you automatically agree to the terms and conditions of this license. If you don't agree to the terms and conditions of this license, you must immediately remove from your computer all materials downloaded from this site.