FastDFS(分布式文件系统)图片上传

一、什么是FastDFS

FastDFS是由淘宝的余庆先生所开发的一个开源的分布式文件系统。用纯C语言开发,功能丰富:

  • 文件存储

  • 文件同步

  • 文件访问(上传、下载)

  • 存取负载均衡

  • 在线扩容

适合有大容量存储需求的应用或系统。同类的分布式文件系统有谷歌的GFS、HDFS(Hadoop)、TFS(淘宝)等。

二、 FastDFS架构

FastDFS两个主要的角色:Tracker Server 和 Storage Server 。

  • Tracker:跟踪服务器,管理集群,tracker也可以实现集群。每个tracker节点地位平等。收集Storage集群的状态。

  • Storage:存储服务器,实际保存文件,分为多个组,每个组之间保存的文件是不同的。每个组内部可以有多个成员,组成员内部保存的内容是一样的,组成员的地位是一致的,没有主从的概念。

三、上传和下载流程 

上传 

 

  1. Client通过Tracker server查找可用的Storage server。

  2. Tracker server向Client返回一台可用的Storage server的IP地址和端口号。

  3. Client直接通过Tracker server返回的IP地址和端口与其中一台Storage server建立连接并进行文件上传。

  4. 上传完成,Storage server返回Client一个文件ID(卷、目录),文件上传结束。

下载 

  1. Client通过Tracker server查找要下载文件所在的的Storage server。

  2. Tracker server向Client返回包含指定文件的某个Storage server的IP地址和端口号。

  3. Client直接通过Tracker server返回的IP地址和端口与其中一台Storage server建立连接并指定要下载文件。

  4. 下载文件成功。

四、安装准备工作(些许复杂)

安装的所有操作均在CentOS 环境下进行。

 将所需文件,上传到/usr/upload目录下:

1.1、单节点FastDFS

整个安装过程非常复杂,很容易出错,建议进行多次备份。

我们这里不打算安装多台虚拟机,因此会把tracker和storage都安装在一起。

 

1.1.1.安装gcc

GCC用来对C语言代码进行编译运行,使用yum命令安装:

yum -y install gcc

1.1.3.安装libfastcommon-master

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

#解压刚刚上传的libfastcommon-master.zip
unzip libfastcommon-master.zip

#进入解压完成的目录
cd libfastcommon-master

#编译并且安装:
./make.sh 
./make.sh install

1.1.4.安装fastdfs

tar -zxvf FastDFS_v5.08.tar.gz

cd FastDFS

./make.sh 

./make.sh install

 如果安装成功,会看到/etc/init.d/下看到提供的脚本文件:

ll /etc/init.d/ | grep fdfs 

  • fdfs_trackerd 是tracker启动脚本

  • fdfs_storaged 是storage启动脚本

能够在 /etc/fdfs/ 目录下看到默认的配置文件模板:

ll /etc/fdfs/ 

 

  • tarcker.conf.sample 是tracker的配置文件模板

  • storage.conf.sample 是storage的配置文件模板

  • client.conf.sample 是客户端的配置文件模板

1.1.5.配置并启动tracker服务

FastDFS的tracker和storage在刚刚的安装过程中,都已经被安装了,因此我们安装这两种角色的方式是一样的。不同的是,两种需要不同的配置文件。

我们要启动tracker,就修改刚刚看到的tarcker.conf,并且启动fdfs_trackerd脚本即可。

1)首先将模板文件复制

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

2)修改复制后的配置文件:

vim /etc/fdfs/tracker.conf  

# 修改的内容如下:  

base_path=/powershop/tracker                 # 存储日志和数据的根目录 

3)新建目录:

mkdir -p /powershop/tracker 

注意:关闭防火墙:  

chkconfig iptables off 

4)启动和停止

启动tracker服务器: /etc/init.d/fdfs_trackerd start

停止tracker服务器: /etc/init.d/fdfs_trackerd stop

不过安装过程中,fdfs已经被设置为系统服务,我们可以采用熟悉的服务启动方式:

service fdfs_trackerd start # 启动fdfs_trackerd服务,停止用stop 

检查FastDFS Tracker Server是否启动成功:  

 ps -ef | grep fdfs_trackerd

 设置tracker服务开机启动:

chkconfig fdfs_trackerd on 

1.1.6.配置并启动storage服务

1)首先将模板文件复制

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

2)修改复制后的配置文件:  

vim /etc/fdfs/storage.conf 

# 修改的内容如下:  

base_path=/powershop/storage                 # 日志文件存储根目录 

store_path0=/powershop/storage           # 文件存储目录 

tracker_server=192.168.204.130:22122       #  tracker服务器IP和端口

 

 3)新建目录:

mkdir -p /powershop/storage 

注意关闭防火墙: chkconfig iptables off

4)启动和停止

启动storage服务器:/etc/init.d/fdfs_storaged start

停止storage服务器:/etc/init.d/fdfs_storaged stop

推荐使用:

service fdfs_storaged start  # 启动fdfs_storaged服务,停止用stop 

检查FastDFS Tracker Server是否启动成功:  

 ps -ef | grep fdfs

设置storage服务开机启动:  

 chkconfig fdfs_storaged on

 

2.使用nginx访问FastDFS

2.1.为什么需要用Nginx访问?

FastDFS通过Tracker服务器,将文件放在Storage服务器存储,但是同组存储服务器之间需要进入文件复制,有同步延迟的问题。

假设Tracker服务器将文件上传到了192.168.4.125,上传成功后文件ID已经返回给客户端。此时FastDFS存储集群机制会将这个文件同步到同组存储192.168.4.126,在文件还没有复制完成的情况下,客户端如果用这个文件ID在192.168.4.126上取文件,就会出现文件无法访问的错误。

而fastdfs-nginx-module可以重定向文件连接到文件上传时的源服务器取文件,避免客户端由于复制延迟导致的文件无法访问错误

2.2.安装fastdfs-nginx-module插件

2.2.1.解压

 tar -zxvf fastdfs-nginx-module_v1.16.tar.gz

2.2.2.修改config

1)进入src目录

 cd fastdfs-nginx-module/src/

2)编辑config

vim config 

使用以下底行命令:

 :%s+/usr/local/+/usr/+g

将所有的/usr/local替换为 /usr,这个才是正确的目录:  

 

2.2.3.配置fastdfs-nginx-module与FastDFS关联配置文件

复制 fastdfs-nginx-module 源码中的配置文件到/etc/fdfs 目录, 并修改

cp /usr/upload/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs/

vim /etc/fdfs/mod_fastdfs.conf

 修改以下配置:

connect_timeout=10                       # 客户端访问文件连接超时时长(单位:秒)

tracker_server=192.168.204.158:22122    # tracker服务IP和端口

url_have_group_name=true                # 访问链接前缀加上组名

store_path0=/powershop/storage            # 文件存储路径

复制 FastDFS 的部分配置文件到/etc/fdfs 目录,否则不支持nginx

cd /usr/upload/FastDFS/conf/
cp http.conf mime.types /etc/fdfs/ 

2.3.1 安装nginx看nginx的安装文章 

2.3.2.如果已经安装过nginx

1) 进入nginx目录:

cd /usr/java/nginx-1.10.0/

2) 配置FastDFS 模块

./configure --prefix=/usr/local/nginx --add-module=/usr/upload/fastdfs-nginx-module/src 

注意:这次配置时,要添加fastdfs-nginx-moudle模块

3) 编译,注意,这次不要安装(install)

make 

4) 替换nginx二进制文件:

备份:

mv /usr/bin/nginx /usr/bin/nginx-bak 

用新编译的nginx启动文件替代原来的:

 cp objs/nginx /usr/bin/

2.3.3.启动nginx

配置nginx整合fastdfs-module模块

我们需要修改nginx配置文件:

vim  /usr/java/nginx/conf/nginx.conf

将文件中,原来的server 80{ ...} 部分代码替换为如下代码:

  server {
        listen       80;
        server_name  image.powershop.com;

    	# 监听域名中带有group的,交给FastDFS模块处理
        location ~/group([0-9])/ {
            ngx_fastdfs_module;#获得fastdfs中图片的存在路径  /usr/storage/group/0/atm.jpg
        }

        location / {
            root   html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

启动nginx:

./nginx    # 启动nginx

./nginx -s stop    # 停止nginx

./nginx -s reload    # 重新载入配置文件

 

2.4.Nginx开机启动

2.4.1.编写开机启动文件

  • 添加nginx.service文件

vim /lib/systemd/system/nginx.service 

文件内容如下:

[Unit]
Description=nginx
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target  

2.4.2.设置开机启动

 systemctl daemon-reload        #重新加载服务配置
systemctl enable nginx.service #设置为开机启动
systemctl start nginx.service  #启动服务
systemctl status nginx.service #查看服务状态
systemctl stop nginx.service   #停止服务

五、 java客户端使用

在父工程中,添加管理依赖,版本为:

<fastDFS-client-version>1.26.2</fastDFS-client-version>

<!--fastdfs-->
<dependency>
    <groupId>com.github.tobato</groupId>
    <artifactId>fastdfs-client</artifactId>
    <version>${fastDFS-client-version}</version>
</dependency>

因此,这里我们直接在power_shop_item子工程的pom.xml中引入坐标即可:  

 <dependency>
    <groupId>com.github.tobato</groupId>
    <artifactId>fastdfs-client</artifactId>
</dependency>

4.4.2.引入配置类

纯java配置:

@Configuration
//只需要一行注解 @Import(FdfsClientConfig.class)就可以拥有带有连接池的FastDFS Java客户端了
@Import(FdfsClientConfig.class)
public class FastClientImporter {
    
}

4.4.3.编写FastDFS属性

在application.yml配置文件中追加如下内容:

 fdfs:
  so-timeout: 1501 # 超时时间
  connect-timeout: 601 # 连接超时时间
  thumb-image: # 缩略图
    width: 60
    height: 60
  tracker-list: # tracker地址:你的虚拟机服务器地址+端口(默认是22122)
    - 192.168.204.130:22122

4.4.4.配置hosts

将来通过域名:image.powershop.com这个域名访问fastDFS服务器上的图片资源。所以,需要代理到虚拟机地址:http://image.powershop.com/group1/M00/00/00/wKjMhV7Du3WATIbZAABIvlHWjnY123.png

  • 配置hosts文件,使image.powershop.com可以访问fastDFS服务器

#测试环境
192.168.204.158 image.powershop.com 

4.4.5.测试

创建测试类:

import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.domain.ThumbImageConfig;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes={PowerShopItemApp.class})
public class FastDFSTest {

    @Autowired
    private FastFileStorageClient storageClient;

    @Autowired
    private ThumbImageConfig thumbImageConfig;

    @Test
    public void testUpload() throws FileNotFoundException {
        // 要上传的文件
        File file = new File("D:/images/1.jpg");
        // 上传并保存图片,参数:1-上传的文件流 2-文件的大小 3-文件的后缀 4-可以不管他
        StorePath storePath = this.storageClient.uploadFile(
                new FileInputStream(file), file.length(), "jpg", null);
        // 带分组的路径
        System.out.println(storePath.getFullPath());
        // 不带分组的路径
        System.out.println(storePath.getPath());
    }

    @Test
    public void testUploadAndCreateThumb() throws FileNotFoundException {
        File file = new File("D:/images/1.jpg");
        // 上传并且生成缩略图
        StorePath storePath = this.storageClient.uploadImageAndCrtThumbImage(
                new FileInputStream(file), file.length(), "png", null);
        // 带分组的路径
        System.out.println(storePath.getFullPath());
        // 不带分组的路径
        System.out.println(storePath.getPath());
        // 获取缩略图路径
        String path = thumbImageConfig.getThumbImagePath(storePath.getFullPath());
        System.out.println(path);
    }
}

 测试后会发现图片在服务器中的位置,在浏览器中带上ip地址通过nginx转发就可以访问到图片!

结果:

group1:卷名

/M00:store_path0 目录

00/00:两层256个文件夹

group1/M00/00/00/wKg4ZVsWl5eAdLNZAABAhya2V0c424.jpg
M00/00/00/wKg4ZVsWl5eAdLNZAABAhya2V0c424.jpg

group1/M00/00/00/wKjpgV6XBT2Abi8rAACaMWefTPs531.png
M00/00/00/wKjpgV6XBT2Abi8rAACaMWefTPs531.png
group1/M00/00/00/wKjpgV6XBT2Abi8rAACaMWefTPs531_60x60.png

 

相关文章

学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习...
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面...
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生...
Can’t connect to local MySQL server through socket \'/v...
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 ...
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服...