FastDFS是一个开源的轻量级分布式文件系统,开发语言为C,适合以小型文件为载体的在线服务,如相册网站、图片服务器等等。
github地址:https://github.com/happyfish100/fastdfs
架构图如下

几个重要的概念:tracker、storage、client
client就是调用方,tracker负责元数据,要上传文件、下载文件先从tracker获取相应的storage,然后client和storage交互,进行实际的文件上传、下载等操作。
FastDFS 没有实现自己的存储,而是使用操作系统的文件系统进行存储的,实际存储是按两级目录来保存文件的。
一、安装
实际安装的是5.11版本,安装目录设置为 /opt
1、安装libfastcommon
fastdfs依赖这个库
cd /optwget https://github.com/happyfish100/libfastcommon/archive/master.zipunzip libfastcommon-master.zipcd libfastcommon-mastermake.sh/make.sh install
2、安装FastDFS
cd optwget https://github.com/happyfish100/fastdfs/archive/master.zipunzip fastdfs-master.zipcd fastdfs-master./make.sh./make.sh install
3、配置
#配置拷贝cd /etc/fdfs/lsclient.conf.sample storage.conf.sample tracker.conf.samplecp client.conf.sample client.confcp storage.conf.sample storage.confcp tracker.conf.sample tracker.conf
tracker中一些重要的参数如下
base_path
max_connections
connect_timeout
network_timeout
work_threads
sync_log_buff_interval
storage一些重要参数:
connect_timeout
network_timeout
heart_beat_interval
base_path
max_connections
work_threads
tracker_server(可以设置多行)
这里不具体详述每个参数的意义,具体可以参考官方文档。
二、使用
1、php
安装扩展,代码在FastDFS 的php_client目录,按标准的扩展安装即可。
安装完在php.ini加上如下,路径根据自己安装目录调整
fastdfs_client.base_path=/opt/fastdfsfastdfs_client.tracker_group_count = 1fastdfs_client.tracker_group0 = /etc/fdfs/client.conf
示例代码如下
<?php//上传文件function uploadFile(){$fdfs = new FastDFS();$tracker = $fdfs->tracker_get_connection();$storager = $fdfs->tracker_query_storage_store('group1', $tracker);$localFileName = '/home/liujh/projects/xman/url.txt';$fileRes = $fdfs->storage_upload_by_filename($localFileName, "txt", ["image" => "url"], "group1", $tracker, $storager);var_dump($fileRes);$fdfs->tracker_close_all_connections();}//获取文件信息function getFile(){$fileName = 'M00/00/00/rBVq5F1DyCOAURnnAAAPAnkf924742.txt';$fdfs = new FastDFS();$buf = $fdfs->storage_download_file_to_buff('group1', $fileName);var_dump($buf);}//获取文件元信息function getMeta(){$fileName = 'M00/00/00/rBVq5F1DyCOAURnnAAAPAnkf924742.txt';$fdfs = new FastDFS();$buf = $fdfs->storage_get_metadata('group1', $fileName);var_dump($buf);}//删除文件function delete(){$fileName = 'M00/00/00/rBVq5F1DyCOAURnnAAAPAnkf924742.txt';$fdfs = new FastDFS();$buf = $fdfs->storage_delete_file('group1', $fileName);var_dump($buf);}getFile();
2、Java
先在init方法进行初始化
public class FastDFSClintFactor{@Value("#{'${connectTimeout}'}")private String connectTimeout;@Value("#{'${tracker_server}'}")private String trackerServers;//初始化private void init(){// 链接超时if(connectTimeout != null && connectTimeout.length > 0){ClientGlobal.setG_connect_timeout(Integer.valueOf(connectTimeout));} else {ClientGlobal.setG_connect_timeout(ClientGlobal.DEFAULT_CONNECT_TIMEOUT);}// 服务器if((trackerServers!= null && trackerServers.length > 0!)){InetSocketAddress[] addresss = this.getTrackerServerArray(trackerServers);ClientGlobal.setG_tracker_group(new TrackerGroup(addresss));} else {throw new NullPointerException("the value of item \"tracker_server\" is null. ");}}}
再创建trackerServer
// 链接服务器trackerServer = new TrackerClient().getConnection();
最后是创建client及使用
public StorageClient getStorageClient(){return new StorageClient(trackerServer, null);}// 文件属性List<NameValuePair> nvpList = new ArrayList<NameValuePair>();nvpList.add(new NameValuePair(FILENAME_KEY, fileSrcName));nvpList.add(new NameValuePair(FILEEXTNAME_KEY, fileExtName));NameValuePair[] metas = nvpList.toArray(new NameValuePair[0]);// 上传文件try {StorageClient sc = fastDFSManager.getStorageClient();String[] result = sc.upload_file(bytes, fileExtName, metas);}catch (Exception e) {logger.error("上传文件到FastDFS服务器异常,文件名:" + fileName, e);return null;}
三、使用踩坑
刚上线时有时候一些文件写入时大小为0,看了代码目前是长连接的实现方式,在MSHUT_DONW中才关闭连接,实际生产环境php-fpm的max_request会配置较大,造成服务端关闭连接但客户端还没关闭,因而许多连接取不到数据,修复方案改为短连接,修改文件fastdfs_client.c,代码如下:
//启用zend_module_entry fastdfs_client_module_entry = {STANDARD_MODULE_HEADER,"fastdfs_client",fastdfs_client_functions,PHP_MINIT(fastdfs_client),PHP_MSHUTDOWN(fastdfs_client),NULL,//PHP_RINIT(fastdfs_client),PHP_RSHUTDOWN(fastdfs_client),//PHP_RSHUTDOWN(fastdfs_client),PHP_MINFO(fastdfs_client),"1.00",STANDARD_MODULE_PROPERTIES};PHP_RSHUTDOWN_FUNCTION(fastdfs_client){FDFSConfigInfo *pConfigInfo;FDFSConfigInfo *pConfigEnd;if (!g_use_connection_pool){if (config_list != NULL){pConfigEnd = config_list + config_count;for (pConfigInfo=config_list; pConfigInfo<pConfigEnd; \pConfigInfo++){if (pConfigInfo->pTrackerGroup != NULL){tracker_close_all_connections_ex( \pConfigInfo->pTrackerGroup);}}}}return SUCCESS;}
四、写在最后
从架构图来看,FastDFS是高可用的,但故障发生时会丢失数据吗?答案是会丢,因为storage之间的文件同步是异步的,所以在client上传文件完后,storage已经返回响应给client了,如果这个时候文件还没有同步到其它的storage,则这个文件就丢了。
这里还有个问题,如果storage cluster有2个实例 st1, st2,如果client将文件上传到st1上,这个时间如果文件还没有同步到st2,这个时间client访问到st2了,这个时间就取不到数据了。针对这个问题,可以安装nginx模块
fastdfs-nginx-module来解决,不过这样一来运维成本也增加了,系统的复杂性也增加了。
总的来说,FastDFS是一个勉强能用的分布式文件系统,离真正的高可用、不丢数据、运维方便还有些距离。

本文详细介绍FastDFS的安装步骤,包括libfastcommon和FastDFS的安装,以及配置tracker和storage的重要参数。同时,提供了FastDFS在PHP和Java中的使用示例,并分享了在实际部署中遇到的问题及解决方案。
162

被折叠的 条评论
为什么被折叠?



