MogileFS 安装总结

MogileFS 开源文件分布式存储

[ Mogilefs的组成部分 ]

1. 数据库(MySQL)部分
你可以用mogdbsetup程序来初始化数据库。数据库保存了Mogilefs的所有元数据,你可以单独拿数据库服务器来做,也可以跟其他程序跑在一起,数据库 部分非常重要,类似邮件系统的认证中心那么重要,如果这儿挂了,那么整个Mogilefs将处于不可用状态。因此最好是HA结构。

2. storageServer(存储节点)
mogstored 程序的启动将使本机成为一个存储节点。启动时默认去读/etc/mogilefs/mogstored.conf ,具体配置可以参考配置部分。mogstored启动后,便可以通过mogadm增加这台机器到cluster中。一台机器可以只运行一个mogstored作为存储节点即可,也可以同时运行其他程序。

3. trackersServer(跟踪器)
mogilefsd即 trackers程序,类似mogilefs的wiki上介绍的,trackers做了很多工作,Replication ,Deletion,Query,Reaper,Monitor等等。mogadm,mogtool的所有操作都要跟trackers打交 道,Client的一些操作也需要定义好trackers,因此最好同时运行多个trackers来做负载均衡。trackers也可以只运行在一台机器 上,也可以跟其他程序运行在一起,只要你配置好他的配置文件即可,默认在/etc/mogilefs/mogilefsd.conf。

4. 工具
主要就是mogadm,mogtool这两个工具了,用来在命令行下控制整个mogilefs系统以及查看状态等等。
如果使用其他语言调用接口,需要二次开发。

5. Client
Client实际上是一个Perl的pm,可以写程序调用该pm来使用mogilefs系统,对整个系统进行读写操作。

[ 逻辑原理 ]

每次文件的上传和读取,都经过前端TrackerServer服务器,trackerServer服务器受到client端的请求,查询数据库,返回一个上传或者是读取的可用的后端StorageServer的地址,然后由client端直接操作后端StorageServer服务器。upload操作返回就是成功或者失败的结果,read操作就是返回对应的查询数据。

=======================================================

自动安装数据库

#mogdbsetup -dbhost=127.0.0.1 -dbname=mogile -dbuser=mogile -dbpassword=mogile

Storage Server Conf 存储节点配置  (mogstored.conf)

#These are set inside the Gentoo conf.d/mogilefsd
#pidfile = /var/run/mogile/mogstored.pid
#daemonize = 1


httplisten=0.0.0.0:7500
mgmtlisten=0.0.0.0:7501
docroot=/var/mogdata



my %config_opts = (
'iostat' => \$opt_iostat,
'daemonize|d' => \$opt_daemonize,
'config=s' => \$opt_config,
'httplisten=s' => \$http_listen,
'mgmtlisten=s' => \$mgmt_listen,
'docroot=s' => \$docroot,
'maxconns=i' => \$max_conns,
'server=s' => \$server,
'serverbin=s' => \$serverbin, );


The mogstored daemon listens on port 7501 for management commands by default, so show this in the config file.


Tracker Conf 监视主机配置 (mogilefsd.conf)

daemonize = 1 不明

db_dsn:数据库主机
db_user:数据库用户名
db_pass:数据库密码

conf_port:监听器端口号
mog_root:不明

(query_jobs:)
listener_jobs
query_jobs

delete_jobs
replicate_jobs
reaper_jobs
monitor_jobs
min_free_space
max_disk_age
debug
pidfile
default_mindevcount 最少的储存份数?
node_timeout
old_repl_compat
listener_jobs







添加用户mogile

adduser mogile



Tracker start 启动监听器

mogilefsd -c /etc/mogilefs/mogilefsd.conf
参数:
--daemon 后台启动

#ps aux | grep mogilefsd


Add Host 添加一个存储节点服务器

用 ‘mogadm’工具将 storage server 加到数据库中. 往数据库中插入了一行语句
将trackers 127.0.0.1:3333 添加到侦听主机表
mogadm -lib=/usr/lib/perl5/5.8.8 -trackers=127.0.0.1:3333 host add mogilestorage -ip=192.168.0.25 -port=7500 -status=alive


Add device to Host 加入一个设备到你的存储节点服务器

mogadm -lib=/usr/lib/perl5/5.8.8 -trackers=127.0.0.1:3333 device add vlinkostorage 1
mkdir -p /var/mogdata/dev1


Storage server start 启动存储节点服务器

mogstored -d
访问存储节点服务器
http://192.168.0.25:7500/dev1/usage

Trackers check 检查跟踪器

mogadm -lib=/usr/local/share/perl/5.8.4 --trackers=127.0.0.1:3333 check
mogadm -lib=/usr/lib/perl5/5.8.8 -trackers=127.0.0.1:3333 host list
mogadm -lib=/usr/lib/perl5/5.8.8 -trackers=127.0.0.1:3333 device list


Add Domain 添加加一个域

mogadm -lib=/usr/lib/perl5/5.8.8 -trackers=127.0.0.1:3333 domain add testdomain

Add Class 添加一个类到一个域

mogadm -lib=/usr/lib/perl5/5.8.8 -trackers=127.0.0.1:3333 class add testdomain testclass
意思是某一个类文件,比如图片类的文件。一个域下面有N多文件类,一个文件类下面的文件KEY是不可以重名的




相关文献
从文档 http://www.danga.com/words/2007_06_usenix/usenix.pdf , 47页, 我们可以看到客户端浏览器最终是通过perlbal这个proxy server直接访问mogilefs storage server上的文件的(想法非常的妙!)。

我不熟悉perlbal, 想使用nginx等高性能的服务器该怎么办?当然,perlbal的性能也是很好的。

perlbal使用了internal redirect的方式来reproxy, 这种方式在apache, lighttpd, nginx中都有实现。由于nginx的proxy性能很突出,所以这里只研究了一下nginx的运作方式。

nginx相关文档: http://wiki.codemongers.com/NginxXSendfile

实验:

1. 192.168.0.1 部署tomcat, 监听8080端口 在webapps/ROOT/目录下创建文件test.jsp, 内容为

<%

String filename = request.getParameter("filename");

response.addHeader("X-Accel-Redirect","/download/" + filename);

%>

2. 192.168.0.2 部署nginx, 监听80端口, 配置文件中加入

                location / {

                        proxy_pass      http://192.168.0.1:8080;

                }

                location /download {

                        internal;

                        rewrite ^/download/(.*) /$1 break;

                        proxy_pass      http://192.168.0.3;

                }

3. 192.168.0.3 部署任意一种web server

现在, 我访问: http://192.168.0.2/test.jsp?filename=test.rar ,系统会产生如下效果:

1. 192.168.0.2 把 这个request proxy到192.168.0.1

2. 192.168.0.1 做了个简单的处理 在response header中加入名字为: X-Accel-Redirect, 内容为: /download/test.rar的header

3. 192.168.0.2收到192.168.0.1的response后,再把request reproxy到 192.168.0.3, 并且url rewrite 为 http://192.168.0.3/test.rar

4. 192.168.0.3 把 test.rar response 给 192.168.0.2

5. 192.168.0.2 把 得到的response返回给客户端浏览器。

因此,对于47页这个图,我们可以把图中的mod_perl改为tomcat, 使用 mogilefs java client得到文件在storage server上的url.

比如: 有两个storage server, 192.168.0.11(dev1) 192.168.0.12(dev2), 注意不同的storage server有不同的存储目录。通过java client我们可以得到url为: http://192.168.0.11/dev1/00/00/00000000, 但只把uri部分/dev1/00/00/00000000放入header中。

nginx proxy中可以配置:

                location /dev1 {

                        internal;

                        proxy_pass      http://192.168.0.11;

                }

                location /dev2 {

                        internal;

                        proxy_pass      http://192.168.0.12;

                }

在storage server上,也可以部署lighttpd等高性能web server, 只要把端口错开。

这样配置有个缺点, 如果有100个storage server, 只能在nginx中配置100个location. 除了自己写一个模块外(不好写啊),我想不出有什么办法可以添加storage server而不修改nginx配置文件。

利用Nginx的X-Accel-Redirect头实现下载控制(附带php和rails实例)

有时你可能需要实现控制下载:即将下载文件的请求转发到某脚本, 然后由这脚本决定怎么做:发送这个文件给用户,出现决绝访问页,或着其他的事。在lighttpd服务器里可以通过从脚本传回X-Sendfile头实现;而Nginx是通过使用X-Accel-Redirect头实现的。在这篇文章里我会尽量简捷地描述在php和rails里如何使用这一特性。

假设你使用Apache运行PHP或Rails产生动态内容,而用Nginx作为前台反向代理(bianbian注:反向代理又称为服务器加速(Server accelerate),原理是将用户的请求转发到目标服务器,然后将结果转发给用户。好处有很多:保护目标服务器安全、负载均衡容易实现、有点类似防火墙;坏处我认为就是要传递用户的IP的时候多了些步骤)。你就达到了两个目标:

因为Nginx服务器会改善所有对动态内容的缓慢请求,能节省服务器的资源(细节正在

这里). (bianbian注:凭我对Nginx的理解,这个就是Nginx会缓存客户端的请求,等全部发送完毕了才一起转发给后台脚本,比如在上载文件的时候。好处是减少后台脚本等待的时间,确实对性能有一定改善;坏处就是在脚本里时时显示上载进度的功能是不可能实现了[当然,以后Nginx如果自己开放这个进度API也是可能的,不过也不是脚本级的,好在显示进度的功能不常用])

你能对静态文件的下载做出控制.(bianbian注:后面的一大段都是说这个啦!)

在这里,假设网站位于 /var/www 目录,而一些静态文件(类似电影、歌曲、或其他)位于 /var/www/files 目录。Apache监听8080端口。

首先,让我们看一看nginx配置:

http {

    ....

    server {

        listen       80;

        server_name  your-domain.com;

        location / {

            rewrite ^/download/(.*) /down.php?path=$1 last;

            proxy_pass         http://127.0.0.1:8080/;

            proxy_redirect     off;

            proxy_set_header   Host             $host;

            proxy_set_header   X-Real-IP        $remote_addr;

            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

            client_max_body_size       10m;

            client_body_buffer_size    128k;

            proxy_connect_timeout      90;

            proxy_send_timeout         90;

            proxy_read_timeout         90;

            proxy_buffer_size          4k;

            proxy_buffers              4 32k;

            proxy_busy_buffers_size    64k;

            proxy_temp_file_write_size 64k;

        }

        location /files {

            root /var/www;

            internal;

        }

    }

}

关键字“internal”指明了哪些目录需要通过X-Accel-Redirect头与后台脚本进行内部转向。我们的脚本只需要完成下载控制的部分,至于分段下载等其他特性跟一般的静态文件一样,都由Nginx服务器实现。

这里是 down.php 的内容:

<?php

// 得到要下载的文件名

$path = $_GET["path"];

//...

// 这里完成权限校验、下载统计等等

//...

// 重定向完成下载

header("X-Accel-Redirect: /files/" . $path);

?>

在 Rails 里可以在控制(controller)里写如下代码(bianbian注:Rails是约定好的MVC架构):

# 得到要下载的文件名

path = @params["path"]

# ...

# 这里完成权限校验、下载统计等等

# ...

# 重定向完成下载

@response.headers['X-Accel-Redirect'] = "/files/" + path

这样就完成了!用上述方法我们就能创建非常灵活又极度高效的文件分发系统。

原文链接:Using X-Accel-Redirect Header With Nginx to Implement Controlled Downloads (with rails and php examples)

http://blog.kovyrin.net/2006/11/01/nginx-x-accel-redirect-php-rails/

测试成功!!!请大家注意:

internal 关键字必须要有!internal指明了必须通过内部才能下载(避免直接输链接)。

如果忘记了internal,即使后台fastcgi输出X-Accel-Redirect也没有用!

那么,如果有些文件又允许直接下载,又允许fastcgi来转向下载怎么办呢?

还好linux有link文件,用“ln -s”建立一个软指向目录就可以了!

两个小时的血泪经验阿,晕倒~

使用注意,有时候需要加上:

proxy_hide_header Content-Type;

谢谢,我一直找X-SENDFILE做什么用的,在这里终于找到了答案。

虽然这里说的是Nginx的X-Accel-Redirect但是Apache的X-SENDFILE同样可以支持!

方法也是类似的!


Perlbal

Perlbal 是一个用 Perl 写的单线程的事件驱动服务器,可充当 web 服务器,HTTP 负载均衡。

快,小,可管理的http web 服务器/代理

可以在内部进行转发

使用Perl开发

单线程,异步,基于事件,使用epoll , kqueue

支持Console管理与http远程管理,支持动态配置加载

多种模式:web服务器,反向代理,插件

支持插件:GIF/PNG互换

如何直接访问mogilefs保存的文件

问题的提出

我在Catalyst上应用Mogilefs来存储用户上传的文件。但当用户下载时,需要多一个手续,就是Catalyst从mogilefs那里取得文件,然后放在$c->res->body里面,返回给客户。这里的缺点有2:

需要多一遍传输

Catalyst需要将文件内容全部读进内存,放在一个scalar变量里面,然后再放到$c->res->body里面.这样如果文件太大的话(比如1000M),会极大的降低性能。

解决方法:

幸亏,我们有perlbal. 具体方法为: 用perlbal作为反向代理,catalyst不直接返回数据,而是返回给perlbal一个特殊的header,来指示perlbal应该去哪里取这个文件: 具体代码为:

my $file = $c->model('DB::Files')->find( { store_name => $store_name } );

my @paths =

$c->model('MogilefsFile')

->get_paths( $store_name, { noverify => 1 } );

my $paths = join( ' ', @paths );

$c->res->content_type( $file->type );

$c->res->headers->header( 'X-REPROXY-URL' => $paths );

"X-Reproxy-Url:http://10.0.0.31/dev3/0/023/683/0023683057.fid"

# 返回一个字串,这样就避免了调用view了

return $c->res->body('ok');

这里,我们设置header一个属性为'X-REPROXY-URL' => $paths,这样perlbal收到这个response后,就会到@paths中的某一个地址来取相应的文件。

但是,怎么设置文件的类型呢?答案是,直接在catalyst里设置好content_type即可:

$c->res->content_type( $file->type );

另外,注意catalyst一般当$c->res->body里没有内容时,会调用view来处理template,由于我们没有设置template,从而catalyst返回一个错误,这样perlbal就得不到正确 的header, 因而也会返回一个错误。所以我们要在$c->res->body里面写上一个ok,这样perlbal就会得到头部,而抛弃内容ok.

或者我们直接改view,让它在有头部X-REPROXY-URL时,不处理template.

发表者 chylli 位置在: 10:31 下午

标签: Catalyst, mogilefs, perlbal

Debugging Common Problems With Using MogileFS

Unable to store files

Does the user mogstored is running as have permission to write to files on var/mogdata/devN* ?
Does that user own the /var/mogdata/devN directory?
Is there at least min_free_space free on the device? (Default: 100MB)
Are all machines using accurate time? In particular,
trackers and databases should have time that's in sync,
otherwise devices will not be considered writable because the device report from the monitor in the database (which uses the database's time),
will be older than tracker's localtime - max_disk_age.

MogileServer - VMWare Virtual Applience Download


Usernames & Passwords
root/root
mogile/mogile -- use this account to use "mogadm"
What you need to do

as user root, setup a static IP for it. (it boots by default with DHCP)
edit /etc/network/interfaces and follow directions therein
use mogadm (as user mogile), to add a host,
then use mogadm to add a device
then download some client code (MogileFS::Client from CPAN if perl), and try it out

http://code.sixapart.com/appliances/
http://code.sixapart.com/appliances/MogileServer.tar.gz
http://code.sixapart.com/appliances/MogileServer.zip



neon


neon is an HTTP and WebDAV client library, with a C interface. Features:

High-level wrappers for common HTTP and WebDAV operations (GET, MOVE, DELETE, etc)Low-level interface to the HTTP request/response engine, allowing the use of arbitrary HTTP methods, headers, etc.
Authentication support including Basic and Digest support, along with GSSAPI-based Negotiate on Unix, and SSPI-based Negotiate/NTLM on Win32
SSL/TLS support using OpenSSL or GnuTLS; exposing an abstraction layer for verifying server certificates, handling client certificates, and examining certificate properties.
Abstract interface to parsing XML using libxml2 or expat, and wrappers for simplifying handling XML HTTP response bodies
WebDAV metadata support; wrappers for PROPFIND and PROPPATCH to simplify property manipulation.
neon is free software, distributed under the GNU Library GPL.

http://www.webdav.org/neon/

Definitions

domain
A domain is the top level separation of files. File keys are unique within domains. A domain consists of a set of classes that define the files within the domain. Examples of domains: fotobilder, livejournal.

class
Every file is part of exactly one class. A class is part of exactly one domain. A class, in effect, only specifies the minimum replica count of a file. Examples of classes: userpicture, userbackup, phonepost.

key
A key is a unique textual string that identifies a file. Keys are unique within domains. Examplse of keys: userpicture:34:39, phonepost:93:3834, userbackup:15.


minimum replica count
This is a property of a class. This defines how many times the files in that class need to be replicated onto different devices in order to ensure redundancy among the data and prevent loss.


file
A file is a defined collection of bits uploaded to MogileFS to store. Files are replicated according to their minimum replica count. Each file has a key, is a part of one class, and is located in one domain. Files are the things that MogileFS stores for you.


MogileFS数据库表结构

#创建一个数据库
CREATE DATABASE `mogile` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
#添加一个Mysql的Mogile用户
CREATE USER 'mogile'@'localhost' IDENTIFIED BY '123456';
GRANT USAGE ON * . * TO'mogile'@'localhost' IDENTIFIED BY'123456' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;
GRANT ALL PRIVILEGES ON `mogile` . * TO'mogile'@'localhost' WITH GRANT OPTION ;

CREATE TABLE `class` (
  `dmid` smallint(5) unsigned NOT NULL default '0',
  `classid` tinyint(3) unsigned NOT NULL default '0',
  `classname` varchar(50) default NULL,
  `mindevcount` tinyint(3) unsigned NOT NULL default '0',
  PRIMARY KEY  (`dmid`,`classid`),
  UNIQUE KEY `dmid` (`dmid`,`classname`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `device` (
  `devid` mediumint(8) unsigned NOT NULL default '0',
  `hostid` mediumint(8) unsigned NOT NULL default '0',
  `status` enum('alive','dead','down','readonly') default NULL,
  `weight` mediumint(9) default '100',
  `mb_total` mediumint(8) unsigned default NULL,
  `mb_used` mediumint(8) unsigned default NULL,
  `mb_asof` int(10) unsigned default NULL,
  PRIMARY KEY  (`devid`),
  KEY `status` (`status`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `domain` (
  `dmid` smallint(5) unsigned NOT NULL default '0',
  `namespace` varchar(255) default NULL,
  PRIMARY KEY  (`dmid`),
  UNIQUE KEY `namespace` (`namespace`)
) TYPE=MyISAM;


CREATE TABLE `file` (
  `fid` int(10) unsigned NOT NULL default '0',
  `dmid` smallint(5) unsigned NOT NULL default '0',
  `dkey` varchar(255) default NULL,
  `length` int(10) unsigned default NULL,
  `classid` tinyint(3) unsigned NOT NULL default '0',
  `devcount` tinyint(3) unsigned NOT NULL default '0',
  PRIMARY KEY  (`fid`),
  UNIQUE KEY `dkey` (`dmid`,`dkey`),
  KEY `devcount` (`dmid`,`classid`,`devcount`)
) TYPE=MyISAM;


CREATE TABLE `file_on` (
  `fid` int(10) unsigned NOT NULL default '0',
  `devid` mediumint(8) unsigned NOT NULL default '0',
  PRIMARY KEY  (`fid`,`devid`),
  KEY `devid` (`devid`)
) TYPE=MyISAM;

CREATE TABLE `file_on_corrupt` (
  `fid` int(10) unsigned NOT NULL default '0',
  `devid` mediumint(8) unsigned NOT NULL default '0',
  PRIMARY KEY  (`fid`,`devid`)
) TYPE=MyISAM;

CREATE TABLE `file_to_delete` (
  `fid` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (`fid`)
) TYPE=MyISAM;

CREATE TABLE `host` (
  `hostid` mediumint(8) unsigned NOT NULL default '0',
  `status` enum('alive','dead','down') default NULL,
  `http_port` mediumint(8) unsigned default '7500',
  `http_get_port` mediumint(8) unsigned default NULL,
  `hostname` varchar(40) default NULL,
  `hostip` varchar(15) default NULL,
  `altip` varchar(15) default NULL,
  `altmask` varchar(18) default NULL,
  `remoteroot` varchar(60) default NULL,
  PRIMARY KEY  (`hostid`),
  UNIQUE KEY `hostname` (`hostname`),
  UNIQUE KEY `hostip` (`hostip`),
  UNIQUE KEY `altip` (`altip`)
) TYPE=MyISAM;

CREATE TABLE `server_settings` (
  `field` varchar(50) NOT NULL default '',
  `value` varchar(255) default NULL,
  PRIMARY KEY  (`field`)
) TYPE=MyISAM;

INSERT INTO `server_settings` VALUES ('schema_version','5');

CREATE TABLE `tempfile` (
  `fid` int(10) unsigned NOT NULL auto_increment,
  `createtime` int(10) unsigned NOT NULL default '0',
  `classid` tinyint(3) unsigned NOT NULL default '0',
  `dmid` smallint(5) unsigned NOT NULL default '0',
  `dkey` varchar(255) default NULL,
  `devids` varchar(60) default NULL,
  PRIMARY KEY  (`fid`)
) TYPE=MyISAM;



CREATE TABLE `unreachable_fids` (
  `fid` int(10) unsigned NOT NULL default '0',
  `lastupdate` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (`fid`),
  KEY `lastupdate` (`lastupdate`)
) TYPE=MyISAM;

猜你喜欢

转载自tenleaves.iteye.com/blog/2174440