为什么选择Nginx
Nginx 是一个很牛的高性能Web和反向代理服务器, 它具有有很多非常优越的特性:
- 在高连接并发的情况下,Nginx是Apache服务器不错的替代品:
Nginx在美国是做虚拟主机生意的老板们经常选择的软件平台之一. 能够支持高达 50,000 个并发连接数的响应, 感谢Nginx为我们选择了 epoll and kqueue 作为开发模型. - Nginx作为负载均衡服务器:
Nginx 既可以在内部直接支持 Rails 和 PHP 程序对外进行服务, 也可以支持作为 HTTP代理 服务器对外进行服务. Nginx采用C进行编写, 不论是系统资源开销还是CPU使用效率都比 Perlbal 要好很多. - 作为邮件代理服务器:
Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器), Last.fm 描述了成功并且美妙的使用经验. - Nginx 是一个 [#installation 安装] 非常的简单 , 配置文件 非常简洁(还能够支持perl语法), Bugs 非常少的服务器:
Nginx 启动特别容易, 并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动. 你还能够 不间断服务的情况下进行软件版本的升级
- 在高连接并发的情况下,Nginx是Apache服务器不错的替代品:
FastDFS为什么要结合Nginx?
我们在使用FastDFS部署一个分布式文件系统的时候,通过FastDFS的客户端API来进行文件的上传、下载、删除等操作。同时通过FastDFS的HTTP服务器来提供HTTP服务。但是FastDFS的HTTP服务较为简单,无法提供负载均衡等高性能的服务,所以FastDFS的开发者——淘宝的架构师余庆同学,为我们提供了Nginx上使用的FastDFS模块(也可以叫FastDFS的Nginx模块)。其使用非常简单。
FastDFS通过Tracker服务器,将文件放在Storage服务器存储,但是同组之间的服务器需要复制文件,有延迟的问题.假设Tracker服务器将文件上传到了192.168.1.80,文件ID已经返回客户端,这时,后台会将这个文件复制到192.168.1.30,如果复制没有完成,客户端就用这个ID在192.168.1.30取文件,肯定会出现错误。这个fastdfs-nginx-module可以重定向连接到源服务器取文件,避免客户端由于复制延迟的问题,出现错误。
FastDFS tracker storage 的工作原理及流程
FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。
FastDFS服务端有两个角色:跟踪器(tracker)和存储节点(storage)。跟踪器主要做调度工作,在访问上起负载均衡的作用。
存储节 点存储文件,完成文件管理的所有功能:存储、同步和提供存取接口,FastDFS同时对文件的metadata进行管理。所谓文件的meta data就是文件的相关属性,以键值对(key value pair)方式表示,如:width=1024,其中的key为width,value为1024。文件metadata是文件属性列表,可以包含多个键值对。
跟踪器和存储节点都可以由一台或多台服务器构成。跟踪器和存储节点中的服务器均可以随时增加或下线而不会影响线上服务。其中跟踪器中的所有服务器都是对等的,可以根据服务器的压力情况随时增加或减少。
为了支持大容量,存储节点(服务器)采用了分卷(或分组)的组织方式。存储系统由一个或多个卷组成,卷与卷之间的文件是相互独立的,所有卷的文件容量累加就是整个存储系统中的文件容量。一个卷可以由一台或多台存储服务器组成,一个卷下的存储服务器中的文件都是相同的,卷中的多台存储服务器起到了冗余备份和负载均衡的作用。
在卷中增加服务器时,同步已有的文件由系统自动完成,同步完成后,系统自动将新增服务器切换到线上提供服务。
当存储空间不足或即将耗尽时,可以动态添加卷。只需要增加一台或多台服务器,并将它们配置为一个新的卷,这样就扩大了存储系统的容量。
FastDFS中的文件标识分为两个部分:卷名和文件名,二者缺一不可。
存储节点采用了分组(group)的方式。存储系统由一个或多个group组成,group与group之间的文件是相互独立的,所有group的文件容量累加就是整个存储系统中的文件容量。一个group可以由一台或多台存储服务器组成,一个group下的存储服务器中的文件都是相同的,group中的多台存储服务器起到了冗余备份和负载均衡的作用(一个组的存储容量为该组内存储服务器容量最小的那个,不同组的Storage server之间不会相互通信,同组内的Storage server之间会相互连接进行文件同步)。
在group中增加服务器时,同步已有的文件由系统自动完成,同步完成后,系统自动将新增服务器切换到线上提供服务。
当存储空间不足或即将耗尽时,可以动态添加group。只需要增加一台或多台服务器,并将它们配置为一个新的group,这样就扩大了存储系统的容量。
FastDFS只有两个角色:Tracker server和Storage server。Tracker server作为中心结点,其主要作用是负载均衡和调度。Tracker server在内存中记录分组和Storage server的状态等信息,不记录文件索引信息,占用的内存量很少。另外,客户端(应用)和Storage server访问Tracker server时,Tracker server扫描内存中的分组和Storage server信息,然后给出应答。由此可以看出Tracker server非常轻量化,不会成为系统瓶颈。
FastDFS中的Storage server在其他文件系统中通常称作Trunk server或Data server。Storage server直接利用OS的文件系统存储文件。FastDFS不会对文件进行分块存储,客户端上传的文件和Storage server上的文件一一对应(FastDFS中的文件标识分为两个部分:组名和文件名,二者缺一不可)
Tracker Server 192.168.55.222 /home/tracker 端口:22122
Tracker Server 192.168.55.226 /home/tracker 端口:22122
Storage1 Server 192.168.55.223 group1 /home/storage 端口:23000
Storage4 Server 192.168.55.227 group1 /home/storage 端口:23000
Storage2 Server 192.168.55.224 group2 /home/storage 端口:23000
Storage3 Server 192.168.55.225 group2 /home/storage 端口:23000
#Storage2为group2的源服务器
注意:
1.group2同组的Storage2和Storage3 FastDFS服务端口必须一致: port=23000。
2.一台服务器可以装多个组(group)但不能装同组的多个Storage,日志会报错误,日志报错原因是"注意1"
3.Version 4.05之前fastdfs内部绑定了libevent作为http服务器.Version 4.05之后的版本删除了内置的web http服务,内置的web http服务是个累赘,不用也罢!
4.启动storage server时,一直处于僵死状态.启动storage server,storage将连接tracker server,如果连不上,将一直重试。直到连接成功,启动才算真正完成!如果集群中有2台tracker server,而其中一台tracker没有启动,可能会导致storage server一直处于僵死状态
FastDFS 同步机制说明:
tracker server会在内存中保存storage分组及各个组下的storage server,并将连接过自己的storage server及其分组保存到文件中,以便下次重启服务时能直接从本地磁盘中获得storage相关信息。storage server会在内存中记录本组的所有服务器,并将服务器信息记录到文件中。tracker server和storage server之间相互同步storage server列表:
1. 如果一个组内增加了新的storage
server或者storage server的状态发生了改变,tracker server都会将storage server列表同步给该组内的所有storage server。以新增storage server为例,因为新加入的storage
server主动连接tracker server,tracker server发现有新的storage server加入,就会将该组内所有的storage server返回给新加入的storage server,并重新将该组的storage server列表返回给该组内的其他storage server;
2. 如果新增加一台tracker server,storage server连接该tracker server,发现该tracker server返回的本组storage server列表比本机记录的要少,就会将该tracker server上没有的storage server同步给该tracker server。同一组内的storage server之间是对等的,文件上传、删除等操作可以在任意一台storage server上进行。文件同步只在同组内的storage server之间进行,采用push方式,即源服务器同步给目标服务器。以文件上传为例,假设一个组内有3台storage server A、B和C,文件F上传到服务器B,由B将文件F同步到其余的两台服务器A和C。我们不妨把文件F上传到服务器B的操作为源头操作,在服务器B上的F文件为源头数据;文件F被同步到服务器A和C的操作为备份操作,在A和C上的F文件为备份数据。同步规则总结如下:
1. 只在本组内的storage server之间进行同步;
2. 源头数据才需要同步,备份数据不需要再次同步,否则就构成环路了;
3. 上述第二条规则有个例外,就是新增加一台storage server时,由已有的一台storage server将已有的所有数据(包括源头数据和备份数据)同步给该新增服务器。storage server有7个状态,如下:
# FDFS_STORAGE_STATUS_INIT :初始化,尚未得到同步已有数据的源服务器
# FDFS_STORAGE_STATUS_WAIT_SYNC :等待同步,已得到同步已有数据的源服务器
# FDFS_STORAGE_STATUS_SYNCING :同步中
# FDFS_STORAGE_STATUS_DELETED :已删除,该服务器从本组中摘除(注:本状态的功能尚未实现)
# FDFS_STORAGE_STATUS_OFFLINE :离线
# FDFS_STORAGE_STATUS_ONLINE :在线,尚不能提供服务
# FDFS_STORAGE_STATUS_ACTIVE :在线,可以提供服务
当storage
server的状态为FDFS_STORAGE_STATUS_ONLINE时,当该storage server向tracker server发起一次heart beat时,tracker server将其状态更改为FDFS_STORAGE_STATUS_ACTIVE。
组内新增加一台storage server A时,由系统自动完成已有数据同步,处理逻辑如下:
1. storage server A连接tracker server,tracker server将storage server A的状态设置为FDFS_STORAGE_STATUS_INIT。storage server A询问追加同步的源服务器和追加同步截至时间点,如果该组内只有storage server A或该组内已成功上传的文件数为0,则没有数据需要同步,storage server A就可以提供在线服务,此时tracker将其状态设置为FDFS_STORAGE_STATUS_ONLINE,否则tracker
server将其状态设置为FDFS_STORAGE_STATUS_WAIT_SYNC,进入第二步的处理;
2. 假设tracker
server分配向storage server A同步已有数据的源storage server为B。同组的storage server和tracker server通讯得知新增了storage server A,将启动同步线程,并向tracker server询问向storage server A追加同步的源服务器和截至时间点。storage server B将把截至时间点之前的所有数据同步给storage server A;而其余的storage server从截至时间点之后进行正常同步,只把源头数据同步给storage server A。到了截至时间点之后,storage server B对storage server A的同步将由追加同步切换为正常同步,只同步源头数据;
3. storage server
B向storage server A同步完所有数据,暂时没有数据要同步时,storage server B请求tracker server将storage server A的状态设置为FDFS_STORAGE_STATUS_ONLINE;
4 当storage server A向tracker server发起heart beat时,tracker server将其状态更改为FDFS_STORAGE_STATUS_ACTIVE。
注:以上内容整理于互联网博客
实践安装过程
1、下载源码包
需要下载的源码包:
fastDFS源代码:FastDFS_v5.01.tar.gz 下载地址:FastDFS_v5.01.tar.gz
fastDFS的nginx模块源代码:fastdfs-nginx-module_v1.15.tar.gz 下载地址:fastdfs-nginx-module_v1.15.tar.gz
nginx服务器源代码:nginx-1.4.7.tar.gz 下载地址:nginx-1.4.7.tar.gz
nginx依赖的pcre库源代码:pcre-8.34.tar.gz 下载地址:pcre-8.34.tar.gz
nginx依赖的zlib库源代码:zlib-1.2.8.tar.gz 下载地址:zlib-1.2.8.tar.gz
2、安装,配置,运行tracker
1.安装
[root@H30 opt]# mkdir fastdfs
[root@H30 opt]# mkdir nginx
[root@H30 opt]# cd fastDFS/
[root@nginx opt]# cp FastDFS_v5.01.tar.gz /opt/fastDFS/
[root@nginx opt]# cd /opt/fastDFS/
[root@tracker src]# tar -zxf FastDFS_v5.01.tar.gz
[root@tracker src]# cd FastDFS
[root@nginx FastDFS]# ./make.sh #如出现错误请安装对应的依赖包
make出现异常情况:
错误:linux下安装安装pcre-8.34
./configure --prefix=/usr/local/pcre 出现以下错误
configure: error: You need a C++ compiler for C++ support
解决方案:C++依赖包
yum install -y gcc gcc-c++
[root@nginx FastDFS]# ./make.sh install #进行安装nginx编译后的二进制文件,如果是先安装了nginx再来安装fastDFS的话可以不用在进行安装nginx了,直接找/opt/nginx/nginx-1.4.7/objs(以自己的源代码目录为准)目录下的nginx文件替换到nginx的编译后的安装目录下的sbin下即可。
为确保替换nginx文件新模块成功了,可以使用 nginx -V 查看nginx已安装的模块(注意是大写的V,小写的v是查看版本信息)
[root@iZj6cgy98yqy7fow7dq2lnZ mnt]# nginx -V
nginx version: nginx/1.4.7
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC)
configure arguments: --prefix=/opt/demo/nginx --add-module=/opt/demo/ngin-module/fastdfs-nginx-module/src --with-pcre=/opt/demo/ngin-module/pcre-8.34 --with-zlib=/opt/demo/ngin-module/zlib-1.2.8
安装完成后,所有可执行文件在/usr/local/bin下,以fdfs开头,配置文件在/etc/fdfs下;
2.配置
[root@iZj6cgy98yqy7fow7dq2lnZ mnt]# mkdir /home/fdfs/tracker/ #创建好对应的tracker的数据文件和日志目录
[root@nginx FastDFS]# vim /etc/fdfs/tracker.conf
一般只需改动以下几个参数即可:
disabled=false #启用配置文件
port=22122 #设置tracker的端口号
base_path=/home/fdfs/tracker/ #设置tracker的数据文件和日志目录(需预先创建)
http.server_port=9300 #设置http访问的端口号
3.运行
运行tracker之前,如果配置了防火墙则要先开放tracker的默认端口22122,
[root@iZj6cgy98yqy7fow7dq2lnZ mnt]# service iptables status #检测防火墙开启状态
iptables: Firewall is not running. #并未启动防火墙
如果防火墙开启的通过添加端口开放: -A INPUT -m state --state NEW -m tcp -p tcp --dport 22122 -j ACCEPT
[root@nginx FastDFS]# /usr/local/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart #启动tracker
如需设置开机自启,可在/etc/rc.d/rc.local中添加上面的命令
3、安装、配置、运行storage
1、安装
由于现在将tracker和storeage安装在同一台服务器上,所以第二步已经安装过fastDFS了,跳过此步;
2、配置
[root@nginx FastDFS]# vim /etc/fdfs/storage.conf
一般只需改动以下几个参数即可:
disabled=false #启用配置文件
group_name=group1 #组名,根据实际情况修改
port=23000 #设置storage的端口号
base_path=/home/fdfs/storage #设置storage的日志目录(需预先创建)
store_path_count=1 #存储路径个数,需要和store_path个数匹配,目前只配置store_path0
store_path0=/home/fdfs/storage1 #存储路径
tracker_server=172.16.1.202:22122 #tracker服务器的IP地址和端口号,注意:如果是阿里云这样的服务器,多个服务器部署的话需要给服务器开启对应的22122端口,否则会连接失败.。如果tracker和storeage部署在同一台服务器的话可以直接使用本机的内网IP。
http.server_port=9300 #设置http端口号
3、运行
[root@nginx FastDFS]# /usr/local/bin/fdfs_storaged /etc/fdfs/storage.conf
如需设置开机自启,可在/etc/rc.d/rc.local中添加上面的命令
4、安装,配置,运行nginx
nginx安装篇:http://www.cnblogs.com/david97/p/7799121.html
1、安装
[root@H30 fastDFS]# cp nginx-1.4.7.tar.gz /opt/nginx/
[root@H30 fastDFS]# cp fastdfs-nginx-module_v1.15.tar.gz /opt/nginx/
[root@H30 fastDFS]# cp pcre-8.34.tar.gz /opt/nginx/
[root@H30 fastDFS]# cp zlib-1.2.11.tar.gz /opt/nginx/
[root@nginx opt]# cd /opt/nginx/
[root@nginx src]# tar zxf nginx-1.4.7.tar.gz
[root@nginx src]# tar zxf fastdfs-nginx-module_v1.15.tar.gz
[root@nginx src]# tar zxf pcre-8.34.tar.gz
[root@nginx src]# tar zxf zlib-1.2.8.tar.gz
[root@nginx src]# cd nginx-1.4.7
[root@nginx nginx-1.4.7]# ./configure --prefix=/opt/nginx --add-module=/opt/nginx/fastdfs-nginx-module/src --with-pcre=/opt/nginx/pcre-8.34/ --with-zlib=/opt/nginx/zlib-1.2.11
[root@nginx nginx-1.4.7] # make
[root@nginx nginx-1.4.7] # make install
[root@H30 nginx-1.4.7]# cp /opt/nginx/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs/
2、配置
[root@nginx nginx-1.4.7]# vim /opt/demo/nginx/conf/nginx.conf
修改nginx配置文件,添加fastDFS server模块
server {
listen 9300;
server_name localhost;
#注释掉部分为在有第二个storage的时候使用的
#location /group1/M01 {
# root /home/fdfs/storage2/data;
# ngx_fastdfs_module;
#}
location /group1/M00 {
root /home/fdfs/storage1/data;
ngx_fastdfs_module;
client_max_body_size 200m;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
[root@storage1 nginx-1.4.7]# vim /etc/fdfs/mod_fastdfs.conf
修改mod_fastdfs配置,一般需要修改如下几个配置
一般只需改动以下几个参数即可:
base_path=/home/fdfs/storage #保存日志目录
tracker_server=172.16.1.202:22122 #tracker服务器的IP地址以及端口号
storage_server_port=23000 #storage服务器的端口号
group_name=group1 #当前服务器的group名
url_have_group_name = true #文件url中是否有group名
store_path_count=1 #存储路径个数,需要和store_path个数匹配
store_path0=/home/fdfs/storage1 #存储路径
http.need_find_content_type=true #从文件扩展名查找文件类型(nginx时为true)
group_count = 1 #设置组的个数(具体要看有几个group)
在末尾增加组的具体信息(有几个group则增加几个)
[group1]
group_name=group1
storage_server_port=23000
store_path_count=1
store_path0=/home/fdfs/storage1
[root@nginx nginx-1.4.7]# ln -s /home/fdfs/storage1/data /home/fdfs/storage1/data/M00 #为storage存储添加软连接
3、运行
运行nginx之前,先要把防火墙中fastDFS的http端口打开(本例中为9300)
[root@iZj6cgy98yqy7fow7dq2lnZ mnt]# nginx -c /opt/demo/nginx/conf/nginx.conf #启动后可以查看下nginx日志
[root@iZj6cgy98yqy7fow7dq2lnZ mnt]# vim /opt/demo/nginx/logs/error.log
启动异常:
异常1:在Storage服务器上启动Nginx时出现
ERROR - file: /home/hadoop/dev/fastdfs/fastdfs-nginx-module/src/common.c, line: 103, section: group1, you must set parameter: group_name!
解决方案:在配置mod_fastdfs.conf文件时要保证group_count=2的个数与下面配置的[group*]个数相一致。如果发现将group_count=0可以启动成功并访问到nginx首页,检查是否给对应的group添加了描述信息。
[group1]
group_name=group1
storage_server_port=23000
store_path_count=1
store_path0=/home/fdfs/storage1
异常2:进程性的 nginx -s stop后再次启动nginx -s reload 会报错,异常原因多数是因为logs/nginx.pid文件不存在或者是被占用了,使用绝对路径配置下即可。
nginx: [error] open() "/alidata/server/nginx/logs/nginx.pid" failed (2: No such file or directory)
解决方案:
nginx -c /opt/demo/nginx/conf/nginx.conf #nginx的编译后的安装路径,使用绝对路径
或
pkill nginx && service nginx restart #杀死nginx并同时启动nginx的服务
异常3:nginx: [error] invalid PID number "" in "/run/nginx.pid"
解决方案:
nginx -c /opt/demo/nginx/conf/nginx.conf
nginx.conf文件的路径可以从nginx -t的返回中找到。
nginx -s reload
异常4:
nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
nginx: [emerg] still could not bind()
解决方案:使用netstat -ntpl命令查看80端口是否已经占用,多数情况是因为nginx已经在启动中导致端口占用没有停止掉,无法启动ipv6的80端口,在论坛找了其中一个解决方案是有些人建议在nginx.conf文件中添加
listen 80;
listen [::]:80 ipv6only=on;,然后我发现并没有效果,我出现这个问题是因为nginx的80端口没有被停用掉。我使用了kill -9 杀死了端口后就可以正常启动了。
启动无误后:通过netstat -ntlp 查看9300、22122、23000这几个端口是不是都存在
5、测试
尝试上传一个文件到FastDFS,然后访问试试。先配置client.conf文件
[root@nginx nginx-1.4.7]# vim /etc/fdfs/client.conf
一般修改如下参数:
base_path=/home/fdfs/tracker #日志存放路径
tracker_server=172.16.1.202:22122 #tracker服务器IP地址和端口号
http.tracker_server_port=9300
[root@nginx nginx-1.4.7]# /usr/local/bin/fdfs_upload_file /etc/fdfs/client.conf /mnt/monk.jpg
程序会返回一个url如:group1/M00/00/00/rBABz1MzKG6Ad_hBAACKLsUDM60560.jpg
然后使用浏览器访问:
http://172.16.1.202:9300/group1/M00/00/00/rBABz1MzKG6Ad_hBAACKLsUDM60560.jpg
此处的172.16.1.202为内网地址,要换成nginx所在的公网地址,如果能访问到图片则安装成功