一、简介
fastdfs是一个开源的,高性能的的分布式文件系统,他主要的功能包括:文件存储,同步和访问,设计基于高可用和负载均衡,fastfd非常适用于基于文件服务的站点,例如图片分享和视频分享网站
fastfds有两个角色:跟踪服务和存储服务,跟踪服务控制,调度文件以负载均衡的方式访问;存储服务包括:文件存储,文件同步,提供文件访问接口,同时以key value的方式管理文件的元数据
跟踪和存储服务可以由1台或者多台服务器组成,同时可以动态的添加,删除跟踪和存储服务而不会对在线的服务产生影响,在集群中,tracker服务是对等的
存储系统由一个或多个卷组成,卷与卷之间的文件是相互独立的,所有卷的文件容量累加就是整个存储系统中的文件容量。一个卷可以由一台或多台存储服务器组成,一个卷下的存储服务器中的文件都是相同的,卷中的多台存储服务器起到了冗余备份和负载均衡的作用。在卷中增加服务器时,同步已有的文件由系统自动完成,同步完成后,系统自动将新增服务器切换到线上提供服务。当存储空间不足或即将耗尽时,可以动态添加卷。只需要增加一台或多台服务器,并将它们配置为一个新的卷,这样就扩大了存储系统的容量。
可以实现图片分布式存储,实现冗余,方便扩容。
二、最简单击部署、java客户端访问
部署结构:1个tracker、1个storage(1组),tracker、storage在同一台centos上,默认base_path,tracker、storage公用一个。如果其他服务器要加storage,只需要配置启动storage就行。
1、安装libevent
#卸载系统自带libevent,自带版本过低,安装fastdfs会出错
rpm -qa|grep libevent
# 或者
yum remove libevent*
#下载安装libevent
wget http://cloud.github.com/downloads/libevent/libevent/libevent-2.0.19-stable.tar.gz;
tar -zxvf libevent-2.0.19-stable.tar.gz;
cd libevent-2.0.19-stable;
#make clean;
./configure --prefix=/usr/local/libevent
make && make install;
#为libevent创建软链接到/lib库下,64位系统对应/lib64
ln -s /usr/local/libevent/lib/libevent-2.0.so.5 /usr/lib/libevent-2.0.so.5
ln -s /usr/local/libevent/lib/libevent-2.0.so.5 /usr/lib64/libevent-2.0.so.5
2、安装fastdfs
#自行下载 4.06 http://sourceforge.net/projects/fastdfs/files/
wget http://fastdfs.googlecode.com/files/FastDFS_v4.06.tar.gz
tar -zxvf FastDFS_v4.06.tar.gz
cd FastDFS
#由于定义/usr/local/fastdfs为fastdfs安装目录,所以需要修改make.sh
vim make.sh
#/etc/fdfs 全部替换为 /usr/local/fastdfs/conf
%s/\/etc\/fdfs/\/usr\/local\/fastdfs\/conf/g
#TARGET_PREFIX=/usr/local 修改为 /usr/local/fastdfs
sed -i 's:TARGET_PREFIX=.*:TARGET_PREFIX=/usr/local/fastdfs:g' make.sh
#安装
./make.sh C_INCLUDE_PATH=/usr/local/libevent/include LIBRARY_PATH=/usr/local/libevent/lib
./make.sh install
#修改配置
tracker.conf :bind_addr=192.168.211.230
storage.conf :tracker_server=192.168.211.230:22122 #注意不要给bind_addr配置ip
client.conf: tracker_server=192.168.211.230:22122 #测试上传时候使用
#创建base_path
mkdir -p /home/yuqing/fastdfs
#启动tracker、storage
./fdfs_trackerd ../conf/tracker.conf
./fdfs_storaged ../conf/storage.conf
#重启
./restart.sh fdfs_trackerd ../conf/tracker.conf
./restart.sh fdfs_storaged ../conf/storage.conf
#停止
./stop.sh fdfs_trackerd ../conf/tracker.conf
./stop.sh fdfs_storaged ../conf/storage.conf
#查看端口是否正常
netstat -nat |grep 22122
netstat -nat |grep 23000
#测试
[root@Master bin]# netstat -nat |grep 22122
tcp 0 0 192.168.211.230:22122 0.0.0.0:* LISTEN
[root@Master bin]# netstat -nat |grep 23000
tcp 0 0 0.0.0.0:23000 0.0.0.0:* LISTEN
[root@Master bin]# ./fdfs_monitor ../conf/storage.conf
[2014-02-15 09:55:38] DEBUG - base_path=/home/yuqing/fastdfs, connect_timeout=30, network_timeout=60, tracker_server_count=1, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0
server_count=1, server_index=0
tracker server is 192.168.211.230:22122
group count: 1
Group 1:
group name = group1
disk total space = 7315 MB
disk free space = 2733 MB
trunk free space = 0 MB
storage server count = 1
active server count = 1
storage server port = 23000
storage HTTP port = 8888
store path count = 1
subdir count per path = 256
current write server index = 0
current trunk file id = 0
Storage 1:
id = 192.168.211.230
ip_addr = 192.168.211.230 ACTIVE
http domain =
version = 4.06
join time = 2014-02-15 09:54:47
up time = 2014-02-15 09:54:47
total storage = 7315 MB
free storage = 2733 MB
upload priority = 10
store_path_count = 1
subdir_count_per_path = 256
storage_port = 23000
storage_http_port = 8888
current_write_path = 0
source storage id=
if_trunk_server= 0
total_upload_count = 0
success_upload_count = 0
total_append_count = 0
success_append_count = 0
total_modify_count = 0
success_modify_count = 0
total_truncate_count = 0
success_truncate_count = 0
total_set_meta_count = 0
success_set_meta_count = 0
total_delete_count = 0
success_delete_count = 0
total_download_count = 0
success_download_count = 0
total_get_meta_count = 0
success_get_meta_count = 0
total_create_link_count = 0
success_create_link_count = 0
total_delete_link_count = 0
success_delete_link_count = 0
total_upload_bytes = 0
success_upload_bytes = 0
total_append_bytes = 0
success_append_bytes = 0
total_modify_bytes = 0
success_modify_bytes = 0
stotal_download_bytes = 0
success_download_bytes = 0
total_sync_in_bytes = 0
success_sync_in_bytes = 0
total_sync_out_bytes = 0
success_sync_out_bytes = 0
total_file_open_count = 0
success_file_open_count = 0
total_file_read_count = 0
success_file_read_count = 0
total_file_write_count = 0
success_file_write_count = 0
last_heart_beat_time = 2014-02-15 09:55:22
last_source_update = 1970-01-01 08:00:00
last_sync_update = 1970-01-01 08:00:00
last_synced_timestamp = 1970-01-01 08:00:00
[root@Master conf]# /usr/local/fastdfs/bin/fdfs_test /usr/local/fastdfs/conf/client.conf upload /root/test/1.jpg
This is FastDFS client test program v4.06
Copyright (C) 2008, Happy Fish / YuQing
FastDFS may be copied only under the terms of the GNU General
Public License V3, which may be found in the FastDFS source kit.
Please visit the FastDFS Home Page http://www.csource.org/
for more detail.
[2014-02-15 10:33:42] DEBUG - base_path=/home/yuqing/fastdfs, connect_timeout=30, network_timeout=60, tracker_server_count=1, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0
tracker_query_storage_store_list_without_group:
server 1. group_name=, ip_addr=192.168.211.230, port=23000
group_name=group1, ip_addr=192.168.211.230, port=23000
storage_upload_by_filename
group_name=group1, remote_filename=M00/00/00/wKjT5lL-0gaAdOjxAAA2MkBlNFg473.jpg
source ip address: 192.168.211.230
file timestamp=2014-02-15 10:33:42
file size=13874
file crc32=1080374360
file url: http://192.168.211.230:8080/group1/M00/00/00/wKjT5lL-0gaAdOjxAAA2MkBlNFg473.jpg
storage_upload_slave_by_filename
group_name=group1, remote_filename=M00/00/00/wKjT5lL-0gaAdOjxAAA2MkBlNFg473_big.jpg
source ip address: 192.168.211.230
file timestamp=2014-02-15 10:33:43
file size=13874
file crc32=1080374360
file url: http://192.168.211.230:8080/group1/M00/00/00/wKjT5lL-0gaAdOjxAAA2MkBlNFg473_big.jpg
3安装nginx + fastdfs-nginx-module:
#下载并解压
wget https://fastdfs.googlecode.com/files/fastdfs-nginx-module_v1.15.tar.gz
wget http://nginx.org/download/nginx-1.4.2.tar.gz
wget http://zlib.net/zlib-1.2.8.tar.gz
wget http://jaist.dl.sourceforge.net/project/pcre/pcre/8.32/pcre-8.32.tar.gz
#其它依赖库,模块 都需要指定解压后的源码路径,才能编译到nginx里面
./configure --prefix=/usr/local/nginx --with-pcre=/usr/local/softpackage/pcre-8.32 --with-zlib=/usr/local/softpackage/zlib-1.2.8 --add-module=/usr/local/softpackage/fastdfs-nginx-module/src
make && make install
#配置
[root@Master sbin]# cp /usr/local/softpackage/fastdfs-nginx-module/src/mod_fastdfs.conf /usr/local/fastdfs/conf/mod_fastdfs.conf
修改ip:tracker_server=192.168.211.230:22122
location /M00 {
root /home/yuqing/fastdfs/data;
ngx_fastdfs_module;
}
#启动nginx
./nginx
#测试
浏览器访问:http://192.168.211.230/M00/00/00/wKjT5lL-0gaAdOjxAAA2MkBlNFg473_big.jpg
4、java客户端:https://fastdfs.googlecode.com/files/fastdfs_client_v1.24.jar
public class FastdfsService { private static String clientFileName = "fast-client.conf"; static { String classPath = null; try { classPath = new File(FastdfsService.class.getResource("/").getFile()).getCanonicalPath(); String configFilePath = classPath + File.separator + clientFileName; ClientGlobal.init(configFilePath); //ClientGlobal.setG_tracker_group(tracker_group).setG_tracker_http_port("192.168.223.106 "); } catch (Exception e) { e.printStackTrace(); } } /** * @Description: uploadFile服务 * * @param bytes 上传文件字节流 * @param fileExtName (默认可以null)上传文件的后缀名,如jpg * @return String * @create 2013-5-3 下午3:31:08 */ public static String uploadFile(byte[] bytes, String fileExtName) { long startTime = 0l; String[] results = null; String accessPath = null; StorageClient storageClient = null; try { TrackerClient trackerClient = new TrackerClient(); TrackerServer trackerServer = trackerClient.getConnection(); storageClient = new StorageClient(trackerServer, null); startTime = System.currentTimeMillis(); results = storageClient.upload_file(bytes, fileExtName, null); if (results == null) { return accessPath; } accessPath = results[0] + "/" + results[1];//0groupname,1filename } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return accessPath; } /** * @Description: 通过文件路径转化文件到字节流 * * @param path 文件路径 * @return byte[]字节 */ public static byte[] getFileBytes(String path) { FileInputStream fis = null; byte[] file_buff = null; try { File file = new File(path); fis = new FileInputStream(file); if (fis != null) { int len; len = fis.available(); file_buff = new byte[len]; fis.read(file_buff); } } catch (FileNotFoundException fe) { fe.printStackTrace(); } catch (IOException ie) { ie.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return file_buff; } /** * @Description: 通过文件对象转化文件到字节流 * * @param file 文件对象 * @return byte[]字节 */ public static byte[] getFileBytes(File file) { FileInputStream fis = null; byte[] file_buff = null; try { fis = new FileInputStream(file); if (fis != null) { int len; len = fis.available(); file_buff = new byte[len]; fis.read(file_buff); } } catch (FileNotFoundException fe) { fe.printStackTrace(); } catch (IOException ie) { ie.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return file_buff; } //测试 public static void main(String[] args){ String path = "F:\\3.jpg"; byte[] bytes = FastdfsService.getFileBytes(path); String filePath = FastdfsService.uploadFile(bytes, "jpg"); } } 配置文件fdfs_client.conf connect_timeout = 2 network_timeout = 30 charset = ISO8859-1 http.tracker_http_port = 8088 http.anti_steal_token = no http.secret_key = FastDFS1234567890 tracker_server = 192.168.211.230:22122