首先简单了解一下基础概念,FastDFS是一个开源的轻量级分布式文件系统,由跟踪服务器(tracker server)、存储服务器(storage server)和客户端(client)三个部分组成,主要解决了海量数据存储问题,特别适合以中小文件(建议范围:4KB < file_size <500MB)为载体的在线服务。
FastDFS的两个核心概念分别是:
Tracker(跟踪器)
Storage(存储节点)
Tracker主要做调度工作,相当于mvc中的controller的角色,在访问上起负载均衡的作用。跟踪器和存储节点都可以由一台或多台服务器构成,跟踪器和存储节点中的服务器均可以随时增加或下线而不会影响线上服务,其中跟踪器中的所有服务器都是对等的,可以根据服务器的压力情况随时增加或减少。Tracker负责管理所有的Storage和group,每个storage在启动后会连接Tracker,告知自己所属的group等信息,并保持周期性的心跳,tracker根据storage的心跳信息,建立group==>[storage server list]的映射表,Tracker需要管理的元信息很少,会全部存储在内存中;另外tracker上的元信息都是由storage汇报的信息生成的,本身不需要持久化任何数据,这样使得tracker非常容易扩展,直接增加tracker机器即可扩展为tracker cluster来服务,cluster里每个tracker之间是完全对等的,所有的tracker都接受stroage的心跳信息,生成元数据信息来提供读写服务。
Storage采用了分卷[Volume](或分组[group])的组织方式,存储系统由一个或多个组组成,组与组之间的文件是相互独立的,所有组的文件容量累加就是整个存储系统中的文件容量。一个卷[Volume](组[group])可以由一台或多台存储服务器组成,一个组中的存储服务器中的文件都是相同的,组中的多台存储服务器起到了冗余备份和负载均衡的作用,数据互为备份,存储空间以group内容量最小的storage为准,所以建议group内的多个storage尽量配置相同,以免造成存储空间的浪费。
新安装的 CentOS-7-x86_64-DVD-1511.iso基础服务器版
镜像下载地址:http://vault.centos.org/7.2.1511/isos/x86_64/CentOS-7-x86_64-DVD-1511.iso
具体CentOS7安装步骤请自行百度,本文重在安装和配置FastDSF
源码下载
fastdfs https://github.com/happyfish100/fastdfslibfastcommon
libfastcommon https://github.com/happyfish100/libfastcommon/releases/tag/V1.0.35
libfastcommon (fastdfs公共的函数封装)
上传 fastdfs 和 libfastcommon 到CentOS7,我的登录用户是kenny,因此上传到了/home/kenny目录下
执行如下命令:
cd /etc
sudo mv yum.repos.d yum.repos.d.bak
sudo mkdir yum.repos.d
sudo wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
sudo yum clean all
sudo yum makecache
执行命令:
sudo yum update
以上fastdfs源码都是纯C语言编写的,因此需要下载gcc-c++编译器对源码进行编译
sudo yum install gcc-c++
解压到libfastcommon当前目录
tar -zxvf libfastcommon-1.0.35.tar.gz
编译libfastcommon
cd libfastcommon-1.0.35/
./make.sh
编译成功后,进行安装
sudo ./make.sh install
libfastcommon.so默认被安装到/usr/lib64目录下,FastFDS的lib目录是/user/local/lib,因此需要设置软链接(类似于windows的快捷方式)
sudo ln -s /usr/lib64/libfastcommon.so /usr/local/lib/libfastcommon.so
sudo ln -s /usr/lib64/libfastcommon.so /usr/lib/libfastcommon.so
sudo ln -s /usr/lib64/libfdfsclient.so /usr/local/lib/libfdfsclient.so
sudo ln -s /usr/lib64/libfdfsclient.so /usr/lib/libfdfsclient.so
解压fastdfs-5.10.tar.gz到当前目录
tar -zxvf fastdfs-5.10.tar.gz
编译fastdfs
cd fastdfs-5.10/
./make.sh
安装 fastdfs
sudo ./make.sh install
fastdfs 安装路径 /etc/fdfs/
拷贝配置文件用于正式环境
sudo cp client.conf.sample client.conf
sudo cp storage.conf.sample storage.conf
sudo cp tracker.conf.sample tracker.conf
创建一个文件夹用于存储 Tracker 服务器的相关文件
mkdir -p /home/kenny/fastdfs/tracker
修改配置文件,修改项如下:
disabled=false #启用配置文件(默认启用)
port=22122 #设置tracker的端口号,通常采用22122这个默认端口
base_path=/home/kenny/fastdfs/tracker #设置tracker的数据文件和日志目录
http.server_port=8888 #设置http端口号,默认为8080
设置脚本软链接
sudo ln -s /usr/bin/fdfs_trackerd /usr/local/bin
sudo ln -s /usr/bin/stop.sh /usr/local/bin
sudo ln -s /usr/bin/restart.sh /usr/local/bin
启动 fdfs_tracker 服务
service fdfs_trackerd start
启动成功后,会自动在base_home 下生成 data 和logs 目录
查看端口监听
sudo netstat -unltp|grep fdfs
创建两个文件夹,一个用于存储服务器文件(storage),另一个用于存储接收文件(storage-data)
mkdir -p /home/kenny/fastdfs/storage
mkdir -p /home/kenny/fastdfs/storage-data
修改配置文件,修改项如下:
disabled=false #启用配置文件(默认启用)
group_name=group1 #组名,根据实际情况修改
port=23000 #设置storage的端口号,默认是23000,同一个组的storage端口号必须一致
base_path=/home/kenny/fastdfs/storage #设置storage数据文件和日志目录
store_path_count=1 #存储路径个数,需要和store_path个数匹配
store_path0=/home/kenny/fastdfs/storage-data #实际文件存储路径
tracker_server=192.168.154.148:22122 #tracker 服务器的 IP地址和端口号,如果是单机搭建,IP不要写127.0.0.1,否则启动不成功(此处的ip是我的CentOS虚拟机ip)
http.server_port=9999 #设置 http 端口号
设置启动脚本软链接
sudo ln -s /usr/bin/fdfs_storaged /usr/local/bin
启动 fastdfs storage 服务
service fdfs_storaged start
启动成功后,会自动在base_path目录下创建 logs 和 data 文件夹
检查tracker 是否与 storage 整合成功
/usr/bin/fdfs_monitor /etc/fdfs/storage.conf
修改 /etc/fdfs/client.conf,修改项如下:
base_path=/home/kenny/fastdfs/tracker_tracker #tracker服务器文件路径
tracker_server=192.168.154.148:22122 #tracker服务器IP地址和端口号
http.tracker_server_port=8888 # tracker 服务器的 http 端口号
sudo vi /etc/fdfs/client.conf
客户端命令测试上传文件
/usr/bin/fdfs_upload_file /etc/fdfs/client.conf /home/kenny/fastdfs-5.10.tar.gz
上传成功后,返回一个文件路径 group1/M00/00/00/wKialFlV-c2AYZNSAAUizRDgQt8.tar.gz
fastdfs 4.0.5版本开始移除了自带的HTTP支持(因为之前自带的HTTP服务较为简单,无法提供负载均衡等高性能服务),所以官方提供了基于nginx的FastDFS模块fastdfs-nginx-module来提供HTTP服务并且解决了group中storage服务器的同步延迟问题。
下载 nginx,http://nginx.org/download/nginx-1.8.1.tar.gz
下载 fastdfs-nginx-module,https://github.com/happyfish100/fastdfs-nginx-module
上传CentOS7服务器
安装 nginx 依赖
sudo yum -y install pcre pcre-devel zlib zlib-devel openssl openssl-devel
解压nginx 和 fastdfs-nginx-module到当前目录
tar -zxvf nginx-1.8.1.tar.gz
unzip fastdfs-nginx-module-master.zip
进入 nginx 目录,配置 fastdfs-nginx-module
cd nginx-1.8.1
sudo ./configure --prefix=/home/kenny/nginx-1.8.1 --add-module=/home/kenny/fastdfs-nginx-module-master/src
编译安装
sudo make
sudo make install
修改nginx配置文件,修改内容如下:
listen 8088
location ~/group1/M00 {
root /home/kenny/fastdfs/storage-data;
ngx_fastdfs_module;
}
拷贝配置文件
sudo cp /home/kenny/fastdfs-master/conf/http.conf /etc/fdfs
sudo cp /home/kenny/fastdfs-master/conf/mime.types /etc/fdfs
sudo cp /home/kenny/fastdfs-nginx-module-master/src/mod_fastdfs.conf /etc/fdfs
修改mod_fastdfs配置文件,修改内容如下:
base_path=/home/kenny/fastdfs/logs #保存日志目录
tracker_server=192.168.154.148:22122 #tracker服务器的IP地址以及端口号
storage_server_port=23000 #storage服务器的端口号
url_have_group_name = true #文件 url 中是否有 group 名
sotre_path_count=1
store_path0=/home/kenny/fastdfs/storage-data # 存储路径
group_count = 3
[group1]
group_name=group1
storage_server_port=23000
store_path_count=1
store_path0=/home/kenny/fastdfs/storage-data
[group2]
group_name=group2
storage_server_port=23000
store_path_count=1
store_path0=/home/kenny/fastdfs/storage-data
[group3]
group_name=group3
storage_server_port=23000
store_path_count=1
store_path0=/home/kenny/fastdfs/storage-data
创建M00目录软链接
sudo ln -s /home/kenny/fastdfs /home/kenny/fastdfs/storage-data/M00
启动nginx
/home/kenny/nginx-1.8.1/sbin/nginx
安装tracker-nginx
解压nginx,重命名为 nginx-tracker,编译安装,与之前命令相似
cd nginx-tracker
sudo ./configure --prefix=/home/kenny/nginx-tracker --add-module=/home/kenny/fastdfs-nginx-module-master/src
sudo make && make install
修改nginx-tracker的配置文件,内容如下:
upstream fdfs_group1 {
server 127.0.0.1:8088;
}
location /group1/M00 {
proxy_pass http://fdfs_group1;
}
vi nginx-tracker/conf/nginx.conf
启动 nginx-tracker
sudo nginx-tracker/sbin/nginx
开放80端口
sudo firewall-cmd --permanent --add-service=http --permanent --add-service=https
sudo firewall-cmd --reload
此时访问 http://192.168.154.148/group1/M00/00/00/wKialFlV-c2AYZNSAAUizRDgQt8.tar.gz 即可实现上传到FastDFS的文件下载
fastdfs_client_java._v1.25 源码下载
https://downloads.sourceforge.net/project/fastdfs/Java Client API Source Code/Java Client API Source Code V1.25/fastdfs_client_java._v1.25.tar.gz?r=https://sourceforge.net/projects/fastdfs/files/Java%20Client%20API%20Source%20Code/Java%20Client%20API%20Source%20Code%20V1.25/&ts=1498821814&use_mirror=nchc
解压后找到fdfs_client.conf配置文件,复制一份
使用 eclipse 创建一个 java 工程,复制源码和配置文件到 src 目录
package org.kenny.fdfs;
import java.io.File; import java.io.FileInputStream; import java.io.IOException; 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 static final String CONFIG_FILENAME = "src/fdfs_client.conf"; private static StorageClient1 storageClient; static { try { ClientGlobal.init(CONFIG_FILENAME); TrackerClient trackerClient = new TrackerClient(ClientGlobal.getG_tracker_group()); TrackerServer trackerServer = trackerClient.getConnection(); StorageServer storageServer = trackerClient.getStoreStorage(trackerServer); storageClient = new StorageClient1(trackerServer, storageServer); } catch (Exception e) { throw new RuntimeException(e); } } /** * 上传文件到FastDFS * * @param file * @param fileName * @return */ public static String uploadFile(File file, String fileName) { FileInputStream fis = null; try { fis = new FileInputStream(file); String fileId = null; NameValuePair[] metaList = null; byte[] fileBuffer = null; if (fis != null) { int fileLength = fis.available(); fileBuffer = new byte[fileLength]; fis.read(fileBuffer); fileId = storageClient.upload_file1(fileBuffer, getFileExt(fileName), metaList); } return fileId; } catch (Exception e) { throw new RuntimeException(e); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { throw new RuntimeException(e); } } } } /** * 删除FastDFS上的文件 * * @param groupName * @param fileName * @return 返回0表示删除成功 */ public static int deleteFile(String groupName, String fileName) { try { return storageClient.delete_file(groupName, fileName); } catch (Exception e) { throw new RuntimeException(e); } } /** * 删除FastDFS上的文件 * * @param groupName * @param fileName * @return 返回0表示删除成功 */ public static int deleteFile(String fileId) { try { return storageClient.delete_file1(fileId); } catch (Exception e) { throw new RuntimeException(e); } } private static String getFileExt(String fileName) { return fileName.substring(fileName.lastIndexOf(".") + 1); } /** * 修改FastDFS上的文件,先上传后删除 * * @param oldFileId * @param file * @param fileName * @return */ public static String modifyFile(String oldFileId, File file, String fileName) { String fileId = null; fileId = uploadFile(file, fileName); if (fileId != null) { deleteFile(oldFileId); } return fileId; } /** * 下载FastDFS上的文件 * * @param fileId * @return */ public static byte[] downloadFile(String fileId) { try { return storageClient.download_file1(fileId); } catch (Exception e) { throw new RuntimeException(e); } } } package org.kenny.fdfs.test; import java.io.File; import org.kenny.fdfs.FastDFSClient; public class FastDFSClientTest { public static void main(String[] args) { // uploadFile(); // deleteFile(); // modifyFile(); downloadFile(); } public static void uploadFile() { String filePath = "E:/JDK/jdk-7u80-linux-x64.tar.gz"; File file = new File(filePath); String fileName = "jdk-7u80-linux-x64.tar.gz"; String fileId = FastDFSClient.uploadFile(file, fileName); System.out.println(fileId); } public static void deleteFile() { String groupName = "group1"; String fileName = "M00/00/00/wKialFlWRt2AVbgkCSax2WbOrFE9134.gz"; int result = FastDFSClient.deleteFile(groupName, fileName); System.out.println(result); } public static void deleteFile1() { String fileName = "group1/M00/00/00/wKialFlWRt2AVbgkCSax2WbOrFE9134.gz"; int result = FastDFSClient.deleteFile(fileName); System.out.println(result); } public static void modifyFile() { String oldFileId = "group1/M00/00/00/wKialFlWSCKAckoMCSax2WbOrFE2307.gz"; String filePath = "E:/JDK/jdk-8u131-linux-x64.tar.gz"; File file = new File(filePath); String fileName = "jdk-8u131-linux-x64.tar.gz"; String fileId = FastDFSClient.modifyFile(oldFileId, file, fileName); System.out.println(fileId); } public static void downloadFile() { String fileId = "group1/M00/00/00/wKialFlWSS-AI_yxCw8fUQ2vcaQ4813.gz"; byte[] fileBuffer = FastDFSClient.downloadFile(fileId); System.out.println(fileBuffer.length); } }测试过程中一直出现 connect timeout 异常,确保fastdfs的tracker和storage服务都已经开启的情况下,只需要将tracker_server的端口开放即可,不要忘了 23000 端口!