柴少鹏的官方网站 技术在分享中进步,水平在学习中升华

Fastdfs与nginx结合提供web服务

注意:4.0.6版本之后,fastdfs已经删除了http web的服务,因此需要与nginx整合,tracker与storage都需要配置nginx,其中storage需要结合nginx_fastdfs模块,tracker不需要,tracker上的nginx主要起代理调度作用。所以前面配置文件里面涉及到的HTTP的部分都不用关注,都没用。生产上面也是后端storage上面都部署nginx,然后前端nginx调用它们开放的端口。

一、nginx和fastdfs整合的单机操作步骤

1.1 fast安装

#wget https://github.com/happyfish100/libfastcommon/archive/master.zip

#wget https://github.com/happyfish100/fastdfs/archive/master.zip

#wget https://github.com/happyfish100/fastdfs-nginx-module/archive/master.zip

#三个软件全下载最新版,避免软件版本冲突什么的,然后按照前面将的安装步骤将libfastcommon和fastdfs。

#将fastdfs-nginx-module的安装包解压以备后面nginx加载。

1.2 nginx加载fastdfs模块

#cd /nginx-1.10.3

# ./configure  --prefix=/usr/local/nginx/ --with-http_stub_status_module --with-http_ssl_module --add-module=../fastdfs-nginx-module-master/src/
# make && make install

1.3 mod_fastdfs.conf文件的配置

# cp /root/fastdfs-nginx-module-master/src/mod_fastdfs.conf  /etc/fdfs/
# vim /etc/fdfs/mod_fastdfs.conf  #模块到时候会使用这个文件,这里我只粘贴修改部分

base_path=/opt/fastdfs/mod_fastdfs
tracker_server=192.168.1.103:22122   #默认的tracker_server=tracker:22122替换掉
tracker_server=192.168.1.104:22122
group_name=group2            #这里是要修改的部分,一定跟本机storege里面设置的组名相一致
url_have_group_name = true   #使用${group_name}在前面的那种url方式
store_path_count=2           #挂载了几块盘这里就写几。
store_path0=/data01
store_path1=/data02
log_level=warn
flv_support = false        #看需求吧,我们这里是关闭的不支持flv格式

# mkdir /opt/fastdfs/mod_fastdfs

1.4 nginx的配置

如下面的简单配置:

   server {
         listen 9090;  #因为我们并不是提供公网的80的网站服务只是作为后端通过web将图片提供给前端的服务器,端口方面最好有些区分
         server_name 192.168.1.106;   #这里可加可不加了一般前端代理是通过IP加端口来调用的
         location ~ /group2/ {
             access_log logs/fast.access.log main;
             ngx_fastdfs_module;   #使用此模块
         }
     }

# /usr/local/nginx/sbin/nginx -s stop
# /usr/local/nginx/sbin/nginx

ngx_http_fastdfs_set pid=6601

# netstat -lntup|grep 9090  #经过nginx的启动和端口查看,可见nginx的配置没问题

tcp        0      0 0.0.0.0:9090            0.0.0.0:*               LISTEN      6602/nginx: master

博文来自:www.51niux.com

1.5 上传文件并访问url进行测试

# fdfs_upload_file  /etc/fdfs/client.conf 6.jpg

group2/M00/00/00/wKgBallfWkWAPInTAAHi22xyv2s173.jpg

浏览器访问url:http://192.168.1.106:9090/group2/M00/00/00/wKgBallfWkWAPInTAAHi22xyv2s173.jpg

图片.png

#我靠你会发现浏览器一直再绕圈圈。

#注意(还需要复制两个文件):

# cp /usr/local/nginx/conf/mime.types /etc/fdfs/
# cp /root/fastdfs-master/conf/http.conf  /etc/fdfs/

# /usr/local/nginx/sbin/nginx -s stop
# /usr/local/nginx/sbin/nginx

再次来查看一下:

图片.png

#从测试结果看是可以了。

1.6 lua来提供status服务

小例子而已,前面已经说过了,我们要针对storage做监控,根据fdfs_monitor的输出信息来监控storage节点是否处于active状态。

 server {
         listen 9090;
         ...
         location /nginx_status {
              set $stat "OK";
              content_by_lua '
                     ngx.header.content_type = "text/plain";
                     ngx.say(ngx.var.stat);
                     ';
              access_log off;
          }
    ...
    }

图片.png

#返回OK说明9090端口,也就是我们的storage的web服务是正常提供的,你除了对端口做监控以外也可以根据URL做监控,显然URL做监控更好一点,端口就算在进程就算在,但是可能网页访问不了。

博文来自:www.51niux.com

二、fastdfs做后端服务器

2.1、捋顺nginx+storage的调用关系

首先我们的nginx配置文件要改一改:

 server {
         listen 9090;
         server_name 192.168.1.104;
         location ~ ^/group[1-99]/M(0|1)[0-9A-F]/[0-9A-F][0-9A-F]/[0-9A-F][0-9A-F]/{
         #主要是这里,因为前面过来的nginx不仅可能找/group1/还可能找/group2/等等,那么如果你只定义了/group1/那么其他过来的请求也就走别的地方就要返回404错误了。
             access_log logs/fast.access.log main;
             ngx_fastdfs_module;
         }
     }

测试很简单:

我们的环境现在是:

192.168.1.103、192.168.1.104、192.168.1.107现在都属于group1组。

192.168.1.105、192.168.1.106现在都属于group2组。

现在我们这五台机器都已经本机安装了nginx,然后也做了nginx的9090端口对外开放,把上面的那句话每个节点上面都配置一下,当然server_name 嫌麻烦可以改成localhost;就都统一了。

现在我们来测试两个URL来查看一下nginx的日志(通过访问同一个IP机器,但是访问不通的group组,来判断这个url是怎么跳转的):

http://192.168.1.105:9090/group1/M00/00/00/wKgBa1lfTiuAVu6MAAFD-qKJBjg667.jpg

http://192.168.1.105:9090/group2/M00/00/00/wKgBaVleCaKAJc0nAAVIZEHwqlg605.jpg

测试开始:

首先先访问:http://192.168.1.105:9090/group1/M00/00/00/wKgBa1lfTiuAVu6MAAFD-qKJBjg667.jpg

查看192.168.1.105的log日志:

192.168.1.112 - - [10/Jul/2017:15:13:15 +0800] "GET /group1/M00/00/00/wKgBa1lfTiuAVu6MAAFD-qKJBjg667.jpg HTTP/1.1" 200 82938 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)" "-" "192.168.1.107:9090"

#从日志可以看出,此图片访问成功了,但是呢192.168.1.105是group2组的,本身呢并没有fid为group1/M00/00/00/wKgBa1lfTiuAVu6MAAFD-qKJBjg667.jpg的文件,所以它把这个请求代理给了192.168.1.107:9090(日志格式里面加了这个"$upstream_addr"字段就能显示出来)

查看192.168.1.107的log日志:

192.168.1.105 - - [10/Jul/2017:15:13:20 +0800] "GET /group1/M00/00/00/wKgBa1lfTiuAVu6MAAFD-qKJBjg667.jpg?redirect=1  HTTP/1.0" 200 82938 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)" "-" "-"

然后再访问:http://192.168.1.105:9090/group2/M00/00/00/wKgBaVleCaKAJc0nAAVIZEHwqlg605.jpg

查看192.168.1.105的log日志:

192.168.1.112 - - [10/Jul/2017:15:14:48 +0800] "GET /group2/M00/00/00/wKgBaVleCaKAJc0nAAVIZEHwqlg605.jpg HTTP/1.1" 200 346212 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)" "-" "-"

#所以通过这个小测试可以看出,本地的storage跟nginx结合向外提供web服务,如果是请求的fid里面的开头组是本机,就直接返回请求,如果fid里面的开头组不是本机所在的组,回通过自己配置文件里面设置的tracker服务器的IP地址去询问,然后向返回的IP地址去请求一下,就相当于nginx的反向代理的角色了。

nginx前端应该如何配置呢?前端反向代理Nginx的配置:

http {
   ...
      upstream backend_fdfs {
              server 192.168.1.103:9090;
              server 192.168.1.104:9090;
              server 192.168.1.105:9090;
              server 192.168.1.106:9090;
              server 192.168.1.107:9090;
    }
  ...
  server {
        listen       80;
        server_name  192.168.1.108;
        proxy_pass http://backend_fdfs;
        }
}

访问url测试并查看日志:

http://192.168.1.108/group1/M00/00/00/wKgBa1lfTiuAVu6MAAFD-qKJBjg667.jpg

查看192.168.1.108的日志:

192.168.1.112 - - [10/Jul/2017:15:49:14 +0800] "GET /group1/M00/00/00/wKgBa1lfTiuAVu6MAAFD-qKJBjg667.jpg HTTP/1.1" 200 82938 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0" "-" "192.168.1.103:9090"

查看192.168.1.103的日志:

192.168.1.108 - - [10/Jul/2017:15:49:20 +0800] "GET /group1/M00/00/00/wKgBa1lfTiuAVu6MAAFD-qKJBjg667.jpg HTTP/1.0"200 82938 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0" - "-"

#因为我们上面upstream是轮询的,第一个正好是192.168.1.103,而192.168.1.103正好是group1组,所以就直接返回了。

http://192.168.1.108/group2/M00/00/00/wKgBalljLpGAecpfAAHi22xyv2s539.jpg
查看192.168.1.108的日志:

192.168.1.112 - - [10/Jul/2017:15:49:39 +0800] "GET /group2/M00/00/00/wKgBalljLpGAecpfAAHi22xyv2s539.jpg HTTP/1.1" 200 123611 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0" "-" "192.168.1.104:9090"

查看192.168.1.104的日志:

192.168.1.108 - - [10/Jul/2017:15:51:01 +0800] "GET /group2/M00/00/00/wKgBalljLpGAecpfAAHi22xyv2s539.jpg HTTP/1.0" 200 123611 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0" "-" "192.168.1.106:9090"

查看192.168.1.106的日志:

192.168.1.104 - - [10/Jul/2017:15:51:05 +0800] "GET /group2/M00/00/00/wKgBalljLpGAecpfAAHi22xyv2s539.jpg?redirect=1  HTTP/1.0" 200 123611 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0" "-" "-"

#因为按照轮询第二个正好是192.168.1.104来处理请求,结果是group2组,192.168.1.104是属于group1组的,所以又发生了跳转,又把请求交给了192.168.1.106.可以看到url的显示都不一样。192.168.1.106是?redirect=1结尾。

注:

nginx前端就是这样调用后端的fastdfs集群的,但是一般nginx前端一般会开启nginx缓存功能,将图片什么的在本地缓存一份,这样不会频繁的回后端调用,nginx缓存在nginx系列中已经提到过了。

生产过程中可以考虑在采用在fastdfs的storage节点上,使用lua脚本的形式,前端用nginx做cache,然后url肯定不能是group2什么的,是一个我们定义的url连接,如一个正常的文件url连接什么的,然后发送到了后端fastdfs,然后fastdfs通过lua脚本将这个url转换成fastdfs可以识别的url。

如下面的配置:

server {
        listen       9090;
        server_name  192.168.1.103;
        location ~ ^/group[1-99]/M(0|1)[0-9A]/[0-9A-F][0-9A-F]/[0-9A-F][0-9A-F]/ {
                ngx_fastdfs_module;
        }
        location / {
                 rewrite_by_lua_file '/usr/local/nginx/conf/Rewrite.lua';  #过来的请求不是group开头的什么url,然后先通过lua调用下url重写脚本将url转换成fastdfs可以识别的fid那种形式。
        }
        #因为Rewrite.lua里面设置了连接mysql和redis,mysql记录了fid跟文件正常url的对应关系,如果连接请求过来了,先拿着url去redis里面去查询跟fid的对应关系,因为redis是内存级别并且是键值对的存储方式,所以查询起来会很快。
        #如果redis里面能查到,那就将url重写一下就交给上面的location了,如果redis里面没有,就会去mysql里面查询,如果查询到了就redis里面缓存一份,然后将url交给上面的location,如果mysql里面也查询不到那就是查不到了。

#当然很多时候是没必要像上面那样搞的复杂一点的,一般情况下图片都是加载到网页里面的,除了我们搞技术的没多少人去关心你这个图片的url是什么的,你可以看拉勾上面的图片或者百度或者什么其他网站的图片都是如此。最后图片的url做成什么样子还是要看需求的。

博文来自:www.51niux.com

三、如何让用户下载的时候是原始的文件名

一般我们的图片都是为了显示的,所以一般也不会涉及到下载,如果大的软件如:apk,压缩包啊什么的都要存储到别的地方了就不用fastdfs来存放了。

这里记录一下,如果你就是把apk,gz压缩包什么的放到了fastdfs里面,然后希望希望下载的时候不是fid文件名,而是文件的原名。

# fdfs_upload_file  /etc/fdfs/client.conf nginx-1.10.3.tar.gz  #比如我们现在将nginx压缩包上传到fastdfs

group2/M00/00/00/wKgBalljPJCAB2zAAA3oleMTgGo.tar.gz

图片.png

#从上图可以看到你去下载的时候的时候,不是我们想要的nginx-1.10.3.tar.gz文件名

稍微的修改下nginx的配置:

  location  / {
            proxy_pass http://backend_fdfs;
            if ($arg_attname ~ "^(.*).tar.gz") {   #加上这句话,判断如果是tar.gz结尾的
                add_header Content-Disposition "attachment;filename=$arg_attname"; #截获url中的参数attname,在Http响应头里面加上字段 Content-Disposition “attachment;filename=$arg_attname”。
            }
        }

访问Url:http://192.168.1.108/group2/M00/00/00/wKgBalljPJCAB2zAAA3oleMTgGo.tar.gz?attname=nginx-1.10.3.tar.gz

图片.png

#浏览器发现响应头里面有Content-Disposition “attachment;filename=$arg_attname”时,就会把文件名显示成filename指定的名称。

#因为上传也是通过程序上传嘛,所以上传的时候就将原始文件的名称以及产生的fid都存储到数据库中,然后再下载的时候,就可以让程序去读数据库然后通过fid搜出原始的文件名然后写到响应头里面。


作者:忙碌的柴少 分类:分布式文件系统 浏览:4041 评论:0
留言列表
发表评论
来宾的头像