(一) 下载FastDFS安装包
FastDFS官方论坛:http://www.csource.org
下载1:http://sourceforge.net/projects/fastdfs/files/
下载2:https://code.google.com/p/fastdfs/downloads/list
使用CentOS 6.5 x86_64版操作系统,按照以下网络拓扑进行部署:
所需要下载的压缩包有:
FastDFS源代码:FastDFS_v5.01.tar.gz
nginx模块源代码:fastdfs-nginx-module_v1.15.tar.gz
nginx服务器源代码:nginx-1.4.7.tar.gz
nginx cache purge插件源代码:ngx_cache_purge-2.1.tar.gz
nginx依赖的pcre库源代码:pcre-8.34.tar.gz
nginx依赖的zlib库源代码:zlib-1.2.8.tar.gz
(二) 安装tracker
1. 安装
首先在192.168.244.131-132上安装FastDFS tracker,使用FastDFS_v5.01.tar.gz源代码包。
可以直接从Linux系统下载源代码包并解压安装。如果是在Windows系统下载,可以在Linux系统中挂载Windows的共享目录并且将源代码包复制进Linux系统内。挂载命令如下
首先将代码包复制到系统的/usr/local/src内(这一步可选),然后使用tar命令解压
运行make.sh,确认make成功。期间如果有错误,可能会是缺少依赖的软件包,需安装后再次make。
运行make.sh install,确认install成功。
安装完成后,所有可执行文件在/usr/local/bin下,以fdfs开头:
所有配置文件在/etc/fdfs下:
至此tracker安装完成。
2. 配置
编辑配置文件目录下的tracker.conf,设置相关信息并保存。
一般只需改动以下几个参数即可:
disabled=false #启用配置文件
port=22122 #设置tracker的端口号
base_path=/fdfs/tracker #设置tracker的数据文件和日志目录(需预先创建)
http.server_port=8080 #设置http端口号
如需要进行性能调优,可以参照附录的配置文件的详细说明。
3. 运行
运行tracker之前,先要把防火墙中对应的端口打开(本例中为22122)。
启动tracker,确认启动是否成功。(查看是否对应端口22122是否开始监听)
也可查看tracker的日志是否启动成功或是否有错误。
设置开机自动启动。
将运行命令行添加进文件:/usr/local/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart
(三) 安装storage
1. 安装
首先在192.168.244.133-138上安装FastDFS storage,使用FastDFS_v5.01.tar.gz源代码包。
首先将代码包复制到系统的/usr/local/src内(这一步可选),然后使用tar命令解压
运行make.sh,确认make成功。期间如果有错误,可能会是缺少依赖的软件包,需安装后再次make。
运行make.sh install,确认install成功。
安装完成后,所有可执行文件在/usr/local/bin下,以fdfs开头:
所有配置文件在/etc/fdfs下:
至此storage安装完成。
2. 配置
编辑配置文件目录下的storage.conf,设置相关信息并保存。
一般只需改动以下几个参数即可:
disabled=false #启用配置文件
group_name=group1 #组名,根据实际情况修改
port=23000 #设置storage的端口号
base_path=/fdfs/storage #设置storage的日志目录(需预先创建)
store_path_count=1 #存储路径个数,需要和store_path个数匹配
store_path0=/fdfs/storage #存储路径
#如果有多个挂载磁盘则定义多个store_path
#store_path1=.....
#store_path2=......
配置tracker可以制定多个
tracker_server=192.168.244.132:22122
tracker_server=192.168.244.131:22122 #tracker服务器的IP地址和端口号
http.server_port=8080 #设置http端口号
如需要进行性能调优,可以参照附录的配置文件的详细说明。
3. 运行
运行storage之前,先要把防火墙中对应的端口打开(本例中为23000)。
启动storage,会根据配置文件的设置自动创建多级存储目录,确认启动是否成功。(查看是否对应端口23000是否开始监听)
也可查看storage的日志是否启动成功或是否有错误。
确认启动成功后,可以运行fdfs_monitor查看storage服务器是否已经登记到tracker服务器。
看到“192.168.244.133 ACTIVE”即可确认storage运行正常。
设置开机自动启动。
将运行命令行添加进文件:/usr/local/bin/fdfs_storaged /etc/fdfs/storage.conf restart
之后依次在192.168.244.133~138上全部安装上storage并确认运行正常。注意配置文件中group名参数需要根据实际情况调整,本例中group是这样分配的:
group1:192.168.244.133,192.168.244.134
group2:192.168.244.135,192.168.244.136
group3:192.168.244.137,192.168.244.138
另外每个group中所有storage的端口号必须一致。
(四) 在storage上安装nginx
在storage上安装的nginx主要为了提供http的访问服务,同时解决group中storage服务器的同步延迟问题。
1. 安装
首先在172.16.1.203上安装nginx,使用nginx-1.4.7.tar.gz源代码包以及FastDFS的nginx插件fastdfs-nginx-module_v1.15.tar.gz。
首先将代码包和插件复制到系统的/usr/local/src内(可选),然后使用tar命令解压
运行./configure进行安装前的设置,主要设置安装路径、FastDFS插件模块目录、pcre库目录、zlib库目录。
如果提示错误,可能缺少依赖的软件包,需先安装依赖包,再次运行./configure
运行make进行编译,确保编译成功。
运行make install进行安装。
将FastDFS的nginx插件模块的配置文件copy到FastDFS配置文件目录。
安装完成后,nginx所有文件在/usr/local/nginx下:
至此nginx以及FastDFS的nginx插件模块安装完成。
2. 配置
编辑/usr/local/nginx/conf配置文件目录下的nginx.conf,设置添加storage信息并保存。
将server段中的listen端口号改为8080:
listen 8080;
在server段中添加:
location ~/group[1-3]/M00 {
root /fdfs/storage/data;
ngx_fastdfs_module;
}
编辑/etc/fdfs配置文件目录下的mod_fastdfs.conf,设置storage信息并保存。
一般只需改动以下几个参数即可:
base_path=/fdfs/storage #保存日志目录
tracker_server=192.168.244.131:22122 #tracker服务器的IP地址以及端口号
tracker_server=192.168.244.132:22122
storage_server_port=23000 #storage服务器的端口号
group_name=group1 #当前服务器的group名
url_have_group_name = true #文件url中是否有group名
store_path_count=1 #存储路径个数,需要和store_path个数匹配
store_path0=/fdfs/storage #存储路径
http.need_find_content_type=true #从文件扩展名查找文件类型(nginx时为true)
group_count = 3 #设置组的个数
在末尾增加3个组的具体信息:
[group1]
group_name=group1
storage_server_port=23000
store_path_count=1
store_path0=/fdfs/storage
[group2]
group_name=group2
storage_server_port=23000
store_path_count=1
store_path0=/fdfs/storage
[group3]
group_name=group3
storage_server_port=23000
store_path_count=1
store_path0=/fdfs/storage
建立M00至存储目录的符号连接。
至此,nginx以及FastDFS插件模块设置完成。
3. 运行
运行nginx之前,先要把防火墙中对应的端口打开(本例中为8080)。
也可查看nginx的日志是否启动成功或是否有错误。
在error.log中没有错误,既启动成功。可以打开浏览器,直接访问http://172.16.1.203:8080,查看是否弹出nginx欢迎页面。
之后依次在192.168.244.133~138上全部安装上nginx并确认运行正常。
设置开机自动启动。
将运行命令行添加进文件:/usr/local/nginx/sbin/nginx
(五) 在tracker上安装nginx
在tracker上安装的nginx主要为了提供http访问的反向代理、负载均衡以及缓存服务。
1. 安装
首先将代码包和插件复制到系统的/usr/local/src内(可选),然后使用tar命令解压
行./configure进行安装前的设置,主要设置安装路径、nginx cache purge插件模块目录、pcre库目录、zlib库目录。
如果提示错误,可能缺少依赖的软件包,需先安装依赖包,再次运行./configure
运行make进行编译,确保编译成功。
运行make install进行安装。
至此nginx以及nginx cache purge插件模块安装完成。
2. 配置
编辑/usr/local/nginx/conf配置文件目录下的nginx.conf,设置负载均衡以及缓存。
worker_processes 4; #根据CPU核心数而定
events {
worker_connections 65535; #最大链接数
use epoll; #新版本的Linux可使用epoll加快处理性能
}
http {
#设置缓存参数
server_names_hash_bucket_size 128;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
client_max_body_size 300m;
sendfile on;
tcp_nopush on;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 16k;
proxy_buffers 4 64k;
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 128k;
#设置缓存存储路径、存储方式、分配内存大小、磁盘最大空间、缓存期限
proxy_cache_path /var/cache/nginx/proxy_cache levels=1:2 keys_zone=http-cache:500m max_size=10g inactive=30d;
proxy_temp_path /var/cache/nginx/proxy_cache/tmp;
#设置group1的服务器
upstream fdfs_group1 {
server 192.168.244.133:8080 weight=1 max_fails=2 fail_timeout=30s;
server 192.168.244.134:8080 weight=1 max_fails=2 fail_timeout=30s;
}
#设置group2的服务器
upstream fdfs_group2 {
server 192.168.244.135:8080 weight=1 max_fails=2 fail_timeout=30s;
server 192.168.244.136:8080 weight=1 max_fails=2 fail_timeout=30s;
}
#设置group3的服务器
upstream fdfs_group3 {
server 192.168.244.137:8080 weight=1 max_fails=2 fail_timeout=30s;
server 192.168.244.138:8080 weight=1 max_fails=2 fail_timeout=30s;
}
server {
#设置服务器端口
listen 8080;
#设置group1的负载均衡参数
location /group1/M00 {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_cache http-cache;
proxy_cache_valid 200 304 12h;
proxy_cache_key $uri$is_args$args;
proxy_pass http://fdfs_group1;
expires 30d;
}
#设置group2的负载均衡参数
location /group2/M00 {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_cache http-cache;
proxy_cache_valid 200 304 12h;
proxy_cache_key $uri$is_args$args;
proxy_pass http://fdfs_group2;
expires 30d;
}
#设置group3的负载均衡参数
location /group3/M00 {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_cache http-cache;
proxy_cache_valid 200 304 12h;
proxy_cache_key $uri$is_args$args;
proxy_pass http://fdfs_group3;
expires 30d;
}
#设置清除缓存的访问权限
location ~ /purge(/.*) {
allow 127.0.0.1;
allow 172.16.1.0/24;
deny all;
proxy_cache_purge http-cache $1$is_args$args;
}
至此,nginx以及nginx cache purge插件模块设置完成。
3. 运行
运行nginx之前,先要把防火墙中对应的端口打开(本例中为8080)。
启动nginx,确认启动是否成功。(查看是否对应端口8080是否开始监听)
尝试上传一个文件到FastDFS,然后访问试试。先配置client.conf文件。
修改以下参数:
base_path=/fdfs/tracker #日志存放路径
tracker_server=192.168.244.131:22122 #tracker服务器IP地址和端口号
tracker_server=192.168.244.132:22122
http.tracker_server_port=8080 #tracker服务器的http端口号
使用/usr/local/bin/fdfs_upload_file上传一个文件,程序会自动返回文件的URL。
http://192.168.244.131:8080/group3/M00/0000/....jpg可以访问
最优解决方案是,在两台tracker服务器的上面,再增加一台nginx负载均很,与代理
让这个主机地址映射到131,132这样在,客户端图片访问的时候,就会映射到对应的位置了
可以看到文件被正确读取出来了。
查看nginx的access.log日志,可以看到访问返回200成功。
查看nginx的cache目录,可以看到已经生成了缓存文件。
l 设置开机自动启动。
将运行命令行添加进文件:/usr/local/nginx/sbin/nginx
至此,tracker服务器上的http反向代理+负载均衡+缓存已经安装完成。
package com.digi_zones.fdfs;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtil;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* <p>Description: FastDFS文件上传下载工具类 </p>
* @version 1.0
* @date 2016/10/19
*/
public class FastDFSClient {
private static final String CONFIG_FILENAME = "src/main/resources/fdfs/fdfs_client.conf";
private static StorageClient1 storageClient1 = null;
// 初始化FastDFS Client
static {
try {
ClientGlobal.init(CONFIG_FILENAME);
TrackerClient trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
TrackerServer trackerServer = trackerClient.getConnection();
if (trackerServer == null) {
throw new IllegalStateException("getConnection return null");
}
StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
if (storageServer == null) {
throw new IllegalStateException("getStoreStorage return null");
}
storageClient1 = new StorageClient1(trackerServer,storageServer);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 上传文件
* @param file 文件对象
* @param fileName 文件名
* @return
*/
public static String uploadFile(File file, String fileName) {
return uploadFile(file,fileName,null);
}
/**
* 上传文件
* @param file 文件对象
* @param fileName 文件名
* @param metaList 文件元数据
* @return
*/
public static String uploadFile(File file, String fileName, Map<String,String> metaList) {
try {
byte[] buff = IOUtil.toByteArray(new FileInputStream(file));
NameValuePair[] nameValuePairs = null;
if (metaList != null) {
nameValuePairs = new NameValuePair[metaList.size()];
int index = 0;
for (Iterator<Map.Entry<String,String>> iterator = metaList.entrySet().iterator(); iterator.hasNext();) {
Map.Entry<String,String> entry = iterator.next();
String name = entry.getKey();
String value = entry.getValue();
nameValuePairs[index++] = new NameValuePair(name,value);
}
}
return storageClient1.upload_file1(buff,FileUtils.getExtension(fileName),nameValuePairs);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取文件元数据
* @param fileId 文件ID
* @return
*/
public static Map<String,String> getFileMetadata(String fileId) {
try {
NameValuePair[] metaList = storageClient1.get_metadata1(fileId);
if (metaList != null) {
HashMap<String,String> map = new HashMap<String, String>();
for (NameValuePair metaItem : metaList) {
map.put(metaItem.getName(),metaItem.getValue());
}
return map;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 删除文件
* @param fileId 文件ID
* @return 删除失败返回-1,否则返回0
*/
public static int deleteFile(String fileId) {
try {
return storageClient1.delete_file1(fileId);
} catch (Exception e) {
e.printStackTrace();
}
return -1;
}
/**
* 下载文件
* @param fileId 文件ID(上传文件成功后返回的ID)
* @param outFile 文件下载保存位置
* @return
*/
public static int downloadFile(String fileId, File outFile) {
FileOutputStream fos = null;
try {
byte[] content = storageClient1.download_file1(fileId);
fos = new FileOutputStream(outFile);
IOUtil.copy(content,fos);
return 0;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return -1;
}
}
Java客户端配置文件(fdfs_client.conf):
connect_timeout = 10 # 连接tracker服务器超时时长
network_timeout = 30 # socket连接超时时长
charset = UTF-8 # 文件内容编码
http.tracker_http_port = 8888 # tracker服务器端口
http.anti_steal_token = no
http.secret_key = FastDFS1234567890
tracker_server = 192.168.244.131:22122 # tracker服务器IP和端口(可以写多个)
tracker_server = 192.168.244.132:22122 # tracker服务器IP和端口(可以写多个)
Java客户端文件上传、下载、删除和元数据获取测试:
package com.digi_zones.fdfs;
import org.junit.Test;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2016</p>
* @version 1.0
* @date 2016/10/19
*/
public class FastDFSClientTest {
/**
* 文件上传测试
*/
@Test
public void testUpload() {
File file = new File("C:\\Users\\yangfang\\Pictures\\angularjs_share.jpg");
Map<String,String> metaList = new HashMap<String, String>();
metaList.put("width","1024");
metaList.put("height","768");
metaList.put("author","杨信");
metaList.put("date","20161018");
String fid = FastDFSClient.uploadFile(file,file.getName(),metaList);
System.out.println("upload local file " + file.getPath() + " ok, fileid=" + fid);
//上传成功返回的文件ID: group1/M00/00/00/wKgAyVgFk9aAB8hwAA-8Q6_7tHw351.jpg
}
/**
* 文件下载测试
*/
@Test
public void testDownload() {
int r = FastDFSClient.downloadFile("group1/M00/00/00/wKgAyVgFk9aAB8hwAA-8Q6_7tHw351.jpg", new File("DownloadFile_fid.jpg"));
System.out.println(r == 0 ? "下载成功" : "下载失败");
}
/**
* 获取文件元数据测试
*/
@Test
public void testGetFileMetadata() {
Map<String,String> metaList = FastDFSClient.getFileMetadata("group1/M00/00/00/wKgAyVgFk9aAB8hwAA-8Q6_7tHw351.jpg");
for (Iterator<Map.Entry<String,String>> iterator = metaList.entrySet().iterator(); iterator.hasNext();) {
Map.Entry<String,String> entry = iterator.next();
String name = entry.getKey();
String value = entry.getValue();
System.out.println(name + " = " + value );
}
}
/**
* 文件删除测试
*/
@Test
public void testDelete() {
int r = FastDFSClient.deleteFile("group1/M00/00/00/wKgAyVgFk9aAB8hwAA-8Q6_7tHw351.jpg");
System.out.println(r == 0 ? "删除成功" : "删除失败");
}
}
附录: