FastDFS-单机版搭建

    在这一章,我们实现单机版的FastDFS图片服务器。

一、前言

    一般而言,当用户量较少的时候,我们就把图片之类的静态资源文件存储到一台装有 Tomcat 的服务器上。但是,随着用户访问量的增大,一个Tomcat服务就不能满足业务需求了,下面提出几种解决方案:

    1. 部署Tomcat集群,使用 Nginx作为负载均衡服务器,分散存储到不同的 Tomcat 服务器上

    这种做法可以简单的扩大存储,但是需要处理一个问题:分散存储后,需要正确的处理逻辑来访问到正确的Tomcat 分支上。例如:存储的时候,由Nginx 分配到 Tomcat1 上;访问的时候,由Nginx 分配到 Tomcat2 上。

    2. 搭建一个唯一的图片服务器,即tomcat本身不保存图片,而将图片上传到图片服务器上

    这种方式采用http的方式来访问图片,需要使用http服务器。可以使用Tomcat ,但是Tomcat的强项在于处理动态请求,这里使用Nginx 服务器比较合适。

    注意:在上述方案一中,我们也使用了 Nginx,但是“负载均衡”只是 Nginx的功能之一。

    3. 搭建图片服务器集群,即分布式文件系统

    这种方式用于解决进一步的用户量增长问题,是方案二的升级版。分布式系统可以解决图片、音视频、文件共享的问题。目前,流行的分布式文件系统有FastDFS、GFS(谷歌)、HDFS(Hadoop)、TFS(淘宝),我们采用FastDFS 来进行介绍和部署。

二、FastDFS 介绍

2.1 简介

    FastDFS 是由淘宝的余庆先生开发,是一个轻量级、高性能的开源分布式文件系统,用纯C语言开发,包括文件存储、文件同步、文件访问(上传、下载)、存取负载均衡、在线扩容、相同内容只存储一份等功能,适合有大容量存储需求的应用或系统。

    FastDFS 按组区分存储资源,当存储空间不足时,可以通过增加水平分组来达到扩容的目的。

    FastDFS 允许少数Nginx发生故障,是一个满足高可用的分布式文件系统。

2.2角色介绍和操作流程

    角色介绍:

    FastDFS 两个主要的角色:TrackerServer 和 Storage Server;

    Tracker Server:跟踪服务器,主要负责调度storage节点与client通信,在访问上起负载均衡的作用,和记录storage节点的运行状态,是连接client和storage节点的枢纽;

    Storage Server:存储服务器,保存文件和文件的meta data(元数据);

    Group:文件组,也称为卷。做集群时一组会有多台服务器,同组服务器上的文件是完全相同的,当文件上传到组内的一台机器后,该文件会同步到同组内的其它所有机器上,起到备份的作用;

    meta data:文件相关属性,键值对(KeyValue Pair)方式,如:width=1024, height=768;  

    FastDFS文件上传流程:

        1、client询问tracker上传到的storage,不需要附加参数;

        2、tracker返回一台可用的storage;

        3、client直接和storage通讯完成文件上传。

    FastDFS文件下载流程:

        1、client询问tracker下载文件的storage,参数为文件标识(组名和文件名);

        2、tracker返回一台可用的storage;

        3、client直接和storage通讯完成文件下载。

2.3 安装准备

    跟踪服务器(TrackerServer)和存储服务器(Storage Server):192.168.232.100

    操作系统:CentOS7(最小化安装即可)

    安装包:

        fastdfs-master.zip:FastDFS源码

        libfastcommon-master.zip:(从 FastDFS 和 FastDHT 中提取出来的公共 C 函数库)

        fastdfs-nginx-module-master.zip:storage节点http服务nginx模块

        nginx-1.12.1.tar.gz:Nginx安装包

    FastDFS相关的安装包可到https://github.com/happyfish100去下载,Nginx需要到官网下载,下载完成后,将压缩包上传到 “/usr/local”目录下。

三、单机版安装

3.1 安装 FastDFS安装包

3.1.1安装所需的依赖包

shell> yum install make cmake gcc gcc-c++ perl zip unzip 

3.1.2 安装 libfastcommon

shell> cd /usr/local  
shell> unzip libfastcommon-master.zip  
shell> cd libfastcommon-master  
## 编译、安装  
shell> ./make.sh  
shell> ./make.sh install  

3.1.3 安装 FastDFS

shell> cd /usr/local  
shell> unzip fastdfs-master.zip  
shell> cd fastdfs-master  
## 编译、安装  
shell> ./make.sh  
shell> ./make.sh install  

3.1.4 启动服务

shell> /etc/init.d/fdfs_storaged  

shell> /etc/init.d/fdfs_trackerd 

3.1.5 配置文件和命令工具目录

#配置文件(/etc/fdfs/目录)  
[root@localhost bin]# ll /etc/fdfs/  
total 84  
-rw-r--r--. 1 root root  1459 Feb 21 18:12 client.conf  
-rw-r--r--. 1 root root  1461 Jan 13 14:50 client.conf.sample  
-rw-r--r--. 1 root root   955 Jan 13 15:17 http.conf  
-rw-r--r--. 1 root root 31172 Jan 13 15:17 mime.types  
-rw-r--r--. 1 root root  3729 Feb 21 18:12 mod_fastdfs.conf  
-rw-r--r--. 1 root root  7919 Feb 21 18:11 storage.conf  
-rw-r--r--. 1 root root  7927 Jan 13 14:50 storage.conf.sample  
-rw-r--r--. 1 root root   105 Jan 13 14:50 storage_ids.conf.sample  
-rw-r--r--. 1 root root  7385 Jan 13 14:53 tracker.conf  
-rw-r--r--. 1 root root  7389 Jan 13 14:50 tracker.conf.sample  

#命令行工具(/usr/bin目录)  
shell> ll /usr/bin/ | grep fdfs  
-rwxr-xr-x. 1 root root    317560 Jan 13 14:50 fdfs_appender_test  
-rwxr-xr-x. 1 root root    317336 Jan 13 14:50 fdfs_appender_test1  
-rwxr-xr-x. 1 root root    304184 Jan 13 14:50 fdfs_append_file  
-rwxr-xr-x. 1 root root    303920 Jan 13 14:50 fdfs_crc32  
-rwxr-xr-x. 1 root root    304248 Jan 13 14:50 fdfs_delete_file  
-rwxr-xr-x. 1 root root    304976 Jan 13 14:50 fdfs_download_file  
-rwxr-xr-x. 1 root root    304576 Jan 13 14:50 fdfs_file_info  
-rwxr-xr-x. 1 root root    322488 Jan 13 14:50 fdfs_monitor  
-rwxr-xr-x. 1 root root   1111888 Jan 13 14:50 fdfs_storaged  
-rwxr-xr-x. 1 root root    327504 Jan 13 14:50 fdfs_test  
-rwxr-xr-x. 1 root root    326712 Jan 13 14:50 fdfs_test1  
-rwxr-xr-x. 1 root root    454096 Jan 13 14:50 fdfs_trackerd  
-rwxr-xr-x. 1 root root    305168 Jan 13 14:50 fdfs_upload_appender  
-rwxr-xr-x. 1 root root    306200 Jan 13 14:50 fdfs_upload_file 

3.2 Tracker服务器配置

3.2.1 复制样例配置文件

shell> cp /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf  

3.2.2 修改配置文件参数

shell> vi /etc/fdfs/tracker.conf  
# 修改的内容如下:  
disabled=false              # 启用配置文件  
port=22122                  # tracker服务器端口(默认22122)  
base_path=/fastdfs/tracker  # 存储日志和数据的根目录  

    其它参数保留默认配置

3.2.3 创建 base_path 指定的目录

shell> mkdir -p /fastdfs/tracker 

3.2.4开启端口(默认为 22122)

使用iptables:  
shell> vi /etc/sysconfig/iptables   
#添加如下端口行: 
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22122 -j ACCEPT   
#重启防火墙:   
shell> service iptables restart  
使用firewall:  
shell> firewall-cmd --add-port=22122/tcp --permanent #添加端口  
shell> firewall-cmd --reload #重新加载  
shell> firewall-cmd --list-port  #查看端口 
#如果想关闭某个端口,可以使用下面的指令  
shell> firewall-cmd --remove-port=22122/tcp --permanent 

3.2.5 启动 tracker 服务器

shell> /etc/init.d/fdfs_trackerd start   #初次启动,会在/fastdfs/tracker目录下生成logs、data两个目录。   
shell> ps -ef|grep fdfs_trackerd         #检查FastDFS Tracker Server是否启动成功  

    如果想停止 tracker服务器,可以使用下面的指令

shell> /etc/init.d/fdfs_trackerd stop  

3.2.6 设置tracker服务开机启动

shell> chkconfig fdfs_trackerd on  

3.3 配置storage服务器

3.3.1 复制样例配置文件

shell> cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage.conf

3.3.2 编辑文件 

shell> vi /etc/fdfs/storage.conf  
# 修改的内容如下:  
disabled=false                          # 启用配置文件  
port=23000                               # storage服务端口  
base_path=/fastdfs/storage              # 数据和日志文件存储根目录  
store_path0=/fastdfs/storage            # 第一个存储目录  
tracker_server=192.168.232.100:22122    # tracker服务器IP和端口  
http.server_port=8888                   # http访问文件的端口 

    其它参数保留默认配置。

3.3.3 创建基础数据目录

shell> mkdir -p /fastdfs/storage  

3.3.4开启端口(默认为 23000) 

firewall:  
shell> firewall-cmd --add-port=23000/tcp --permanent   #添加端口  
shell> firewall-cmd --reload     #重新加载  
shell> firewall-cmd --list-port  #查看端口 

3.3.5 启动 storage 服务器

shell> /etc/init.d/fdfs_storaged start  

    初次启动,会在/fastdfs/storage目录下生成logs、data两个目录。

    检查FastDFSTracker Server是否启动成功:

shell> ps -ef | grep fdfs_storaged  

    停止 storage 服务器的命令

shell> /etc/init.d/fdfs_storaged stop  

3.3.6 设置 storage 服务开机启动

shell> chkconfig fdfs_storaged on  

3.4上传测试

3.4.1复制样例配置文件并编辑文件

shell> cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf    
shell> vi /etc/fdfs/client.conf   

# 修改以下配置,其它保持默认  
base_path=/fastdfs/tracker  
tracker_server=192.168.232.100:22122 

3.4.2 执行文件上传命令

shell> /usr/bin/fdfs_upload_file /etc/fdfs/client.conf /home/w/test.jpg 

    返回类似的文件ID号:group1/M00/00/00/wKjodVqNUXeAE452AAE9rfD8DeY539.jpg。

3.5 安装 fastdfs-nginx-module

3.5.1  fastdfs-nginx-module 介绍

    上传文件时,同组存储服务器之间需要复制文件,这就会有同步延迟。在文件还没有复制完成的情况下,客户端如果访问同组其他的服务器,就会出现访问错误。fastdfs-nginx-module 可以重定向文件连接到源服务器(上传的服务器)取文件,避免复制延迟导致的访问错误。

3.5.2 解压 fastdfs-nginx-module-master.zip

shell> cd /usr/local  
shell> unzip fastdfs-nginx-module-master.zip  

3.5.3 安装Nginx

## 安装 Nginx 所需的依赖包  
shell> yum install gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel  
## 编译安装 Nginx(添加 fastdfs-nginx-module 模块)  
shell> cd /usr/local  
shell> tar -zxvf nginx-1.12.1.tar.gz  
shell> unzip fastdfs-nginx-module-master.zip  
shell> cd nginx-1.12.1  
shell> ./configure --prefix=/opt/nginx --sbin-path=/usr/bin/nginx --add-module=/usr/local/fastdfs-nginx-module-master/src  
shell> make && make install  

3.5.4 复制并编辑fastdfs-nginx-module配置文件

shell> cp /usr/local/fastdfs-nginx-module-master/src/mod_fastdfs.conf /etc/fdfs/  
shell> vi /etc/fdfs/mod_fastdfs.conf  
#修改以下配置:  
connect_timeout=10                  # 客户端访问文件连接超时时长(单位:秒)  
base_path=/tmp                      # 临时目录  
tracker_server=192.168.232.100:22122  # tracker服务IP和端口  
storage_server_port=23000           # storage服务端口  
group_name=group1                   # 组名  
url_have_group_name=true            # 访问链接前缀加上组名  
store_path0=/fastdfs/storage        # 文件存储路径  

    其它配置保持默认。

3.5.5 复制 FastDFS 配置文件到/etc/fdfs 目录

shell> cd /usr/local/fastdfs-master/conf  
shell> cp http.conf mime.types /etc/fdfs/  

3.5.6创建软连接

shell> ln -s /fastdfs/storage/data/ /fastdfs/storage/data/M00 

3.5.7 配置nginx访问storage文件

#简洁版nginx配置:    
vi /opt/nginx/conf/nginx.conf    

user nobody;    
worker_processes 1;    
events {    
    worker_connections 1024;    
}    
http {    
    include mime.types;    
    default_type application/octet-stream;    
    sendfile on;    
    keepalive_timeout 65;    
    server {    
        listen 8888;    
        server_name localhost;    
        location ~/group([0-9])/M00 {    
            ngx_fastdfs_module;    
        }    
        error_page 500 502 503 504 /50x.html;    
        location = /50x.html {    
             root html;    
         }    
     }    
}  

    注意1:8888 端口值与/etc/fdfs/storage.conf中的http.server_port=8888 相对应。

    注意2:Storage 对应有多个 group 的情况下,访问路径带group 名,如/group1/M00/00/00/xxx,对应的 Nginx 配置为:

     location~/group([0-9])/M00 {

        ngx_fastdfs_module;

    }

    注意3:若发现频繁报 404,可将nginx.conf 第一行 user nobody; 修改为 user root; 后重新启动。

3.5.8 开启8888 端口

shell> firewall-cmd --add-port=8888/tcp --permanent  #添加端口  
shell> firewall-cmd --reload      #重新加载  
shell> firewall-cmd --list-port  #查看端口 

3.5.9 启动Nginx

#启动命令如下,会显示类似 "ngx_http_fastdfs_set pid=xxx"的提示信息  
shell> /usr/bin/nginx      
#nginx重启命令如下:  
shell> /usr/bin/nginx -s reload  

3.5.10访问上传的文件

    测试上传后返回的文件ID为:group1/M00/00/00/wKjodVqNUXeAE452AAE9rfD8DeY539.jpg

    浏览访问的地址为:http://192.168.232.111:8888/group1/M00/00/00/wKjodVqNUXeAE452AAE9rfD8DeY539.jpg

    注意:不要使用 kill命令,否则可能会导致数据丢失。

3.6 使用FastDFS-Client客户端测试上传和下载

3.6.1 打包fastdfs-client 到本地仓库

    访问Github官网下载fastdfs-client源码并转化为maven工程,然后打包到本地maven仓库。这里需要在maven项目中加入坐标,如下所示。

<dependency>    
     <groupId>org.csource</groupId>   
     <artifactId>fastdfs-client-java</artifactId>    
     <version>1.27-SNAPSHOT</version>    
</dependency>  

3.6.2 新建配置文件

    在工程的resources目录下新建一个resource文件夹,如下图所示。

    

    在文件夹得下面创建client.conf文件,client.conf文件中输入tracker所在的设备的IP及端口,只保留红框中的即可,如下图所示。

    

    注意1:注释加在上方,否则会报错。

    注意2:tracker 服务器可以有多个,上图的配置文件配置了集群的情况,使用的时候取消注释即可。

3.6.3 新建测试类

    下面新建一个测试类来进行测试,在src/test/java目录下新建一个包com.xxx.fastdfs,在该包下新建一个测试类TestFastDFS.java,如下所示。

package com.xxx.fastdfs;    

import org.csource.common.NameValuePair;    
import org.csource.fastdfs.ClientGlobal;    
import org.csource.fastdfs.StorageClient;    
import org.csource.fastdfs.StorageServer;    
import org.csource.fastdfs.TrackerClient;    
import org.csource.fastdfs.TrackerServer;    
import org.junit.Test;  
import com.xxx.utils.FastDFSClient;    

public class TestFastDFS {      

     @Test    
     public void testUploadFile() throws Exception{    
         //1.向工程添加jar包    
         //2.创建一个配置文件,配置tracker服务器地址    
         //3.加载配置文件    
         ClientGlobal.init("D:/Work/taotao2/taotao-manager-web/src/main/resources/resource/client.conf");    
         //4.创建一个TrackerClient对象    
         TrackerClient trackerClient = new TrackerClient();    
         //5.使用TrackerClient对象获得trackerserver对象。    
         TrackerServer trackerServer = trackerClient.getConnection();    
         //6.创建一个StorageServer的引用,我们用null就可以    
         StorageServer storageServer = null;    
         //7.创建一个StorageClient对象。trackerserver、StorageServer两个参数    
         StorageClient storageClient = new StorageClient(trackerServer, storageServer);    
         //8.使用StorageClient对象上传文件    
         NameValuePair[] metaList = new NameValuePair[3];    
         metaList[0] = new NameValuePair("fileName", "2");    
         metaList[1] = new NameValuePair("createTime", "2017-04-13 16:01:00");    
         metaList[2] = new NameValuePair("createUser", "zhangsan");    
         String[] upload_files = storageClient.upload_file("D:/test.jpg", "jpg", metaList);    
         for(String file : upload_files){    
             System.out.println(file);    
         }    
     }    
 }  

    注意1:在工程中添加junit的依赖(版本已在父工程中定义)

<dependency>    
    <groupId>junit</groupId>    
    <artifactId>junit</artifactId>    
</dependency>   

    注意2:NameValuePair是给图片添加附加信息的,包括图片原文件名、大小、作者等等,导包时会发现有多个选项,我们选择"import org.csource.common.NameValuePair"

    注意3:如果在复制粘贴系统的本地文件绝对路径(D:/test.jpg)时,Eclipse识别不了,则手动输入。

3.6.4 执行测试方法

    控制台会返回两行数据:第一行是组号;第二行是存放的具体位置。        

    

    带有附加信息的图片上传后,会生成一个以"-m"结尾的文件,如下图所示。

    

3.6.5 通过浏览器访问图片

    访问拼接后的地址192.168.232.100:8888/group1/M00/00/00/wKjoZFqNlgCAQ4enAAVOJlr_l7Q570.jpg,端口8888是在Nginx中配置的对外暴露的访问端口,如下图所示。

    

3.6.6 封装工具类及测试

    为了方便使用,下面对类进行封装,内容如下。封装类中使用的Storage客户端是StorageClient1而不是StorageClient,这个客户端能够自动把文件所在的组以及存放位置拼接到一块。

package com.xxx.utils;  

import org.csource.common.NameValuePair;  
import org.csource.fastdfs.ClientGlobal;  
import org.csource.fastdfs.StorageClient1;  
import org.csource.fastdfs.StorageServer;  
import org.csource.fastdfs.TrackerClient;  
import org.csource.fastdfs.TrackerServer;  

public class FastDFSClient {  
    private TrackerClient trackerClient = null;  
    private TrackerServer trackerServer = null;  
    private StorageServer storageServer = null;  
    private StorageClient1 storageClient = null;  

    public FastDFSClient(String conf) throws Exception {  
        // 将相对路径"classpath:applications.properties"转为绝对路径"E:/workspace/src/main/resources"  
        if (conf.contains("classpath:")) {  
            conf = conf.replace("classpath:", this.getClass().getResource("/").getPath());  
        }  
        ClientGlobal.init(conf);  
        trackerClient = new TrackerClient();  
        trackerServer = trackerClient.getConnection();  
        storageServer = null;  
        // StorageClient1能够自动把文件所在的组以及存放位置拼接到一块  
        storageClient = new StorageClient1(trackerServer, storageServer);  
    }  

    /** 
     * 上传文件方法 
     * <p> 
     * Title: uploadFile 
     * </p> 
     * <p> 
     * Description: 
     * </p> 
     *  
     * @param fileName 
     *            文件全路径 
     * @param extName 
     *            文件扩展名,不包含(.) 
     * @param metas 
     *            文件扩展信息 
     * @return 
     * @throws Exception 
     */  
    public String uploadFile(String fileName, String extName, NameValuePair[] metas) throws Exception {  
        String result = storageClient.upload_file1(fileName, extName, metas);  
        return result;  
    }  

    public String uploadFile(String fileName) throws Exception {  
        return uploadFile(fileName, null, null);  
    }  

    public String uploadFile(String fileName, String extName) throws Exception {  
        return uploadFile(fileName, extName, null);  
    }  

    /** 
     * 上传文件方法 
     * <p> 
     * Title: uploadFile 
     * </p> 
     * <p> 
     * Description: 
     * </p> 
     *  
     * @param fileContent 
     *            文件的内容,字节数组 
     * @param extName 
     *            文件扩展名 
     * @param metas 
     *            文件扩展信息 
     * @return 
     * @throws Exception 
     */  
    public String uploadFile(byte[] fileContent, String extName, NameValuePair[] metas) throws Exception {  
        String result = storageClient.upload_file1(fileContent, extName, metas);  
        return result;  
    }  

    public String uploadFile(byte[] fileContent) throws Exception {  
        return uploadFile(fileContent, null, null);  
    }  

    public String uploadFile(byte[] fileContent, String extName) throws Exception {  
        return uploadFile(fileContent, extName, null);  
    }  

}  

    新建一个工具包com.xxx.utils,然后把封装类FastDFSClient.java放到下面。

    

    下面进行测试,在TestFastDFS类中新建测试方法testFastDFSClient,代码如下:

@Test  
public void testFastDFSClient() throws Exception {  
    FastDFSClient fastDFSClient = new FastDFSClient(  
        "D:/Work/taotao2/taotao-manager-web/src/main/resources/resource/client.conf");  
    String imgPath = fastDFSClient.uploadFile("D:/test.jpg");  
    System.out.println(imgPath);  
}  

    运行testFastDFSClient方法,返回的结果如下图所示。

    

    类似的也可以通过浏览器访问这个图片。



“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

luqi0000

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值