美文网首页
[转][笔记]分布式文件系统 MofileFS

[转][笔记]分布式文件系统 MofileFS

作者: C86guli | 来源:发表于2016-08-17 13:08 被阅读460次

    参考:
    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 我们可以自行建立高可用。每个服务器可以承担多个角色。

    Snip20160815_116.png

    当 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

    Snip20160817_118.png

    最后附上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.

    相关文章

      网友评论

          本文标题:[转][笔记]分布式文件系统 MofileFS

          本文链接:https://www.haomeiwen.com/subject/rmuusttx.html