FastDFS ¶
FastDFS入门 ¶
FastDFS 是一个开源的轻量级分布式文件系统
FastDFS服务端由两个部分组成:跟踪器(tracker)、存储节点(storage)
- 跟踪器:主要是调度工作,在内存中记录存储节点(storage)的状态信息,是前端 Client 和后端存储节点 storage 的枢纽。Tracker server的性能非常高,一个大的集群(上百个group)中有3台就足够了
- 存储节点:用于存储文件,包括文件和文件属性(meta data) 都保存到存储服务器磁盘上,完成文件管理的所有功能:文件存储、文件同步和提供文件访问
安装
检查机器是否包含如下依赖:gcc、libevent、libevent-devel
bash1#安装 gcc、libevent、libevent-devel 2yum install gcc libevent libevent-devel -ygithub地址:
https://github.com/happyfish100,下载安装:libfastcommon库、FastDFS-masterbash1#解压libfastcommon库、FastDFS-master 2unzip libfastcommon-master.zip 3unzip FastDFS-master.zip 4 5#进入相应的目录编译安装 6./make.sh 7./make.sh install查看安装文件
bash1#进入 /usr/bin,查看fdfs相关命令 2ll | grep fdfs 3 4#进入 /etc/fdfs,查看fdfs相关配置文件 5ll 6-rw-r--r-- 1 root root 1909 Aug 15 19:52 client.conf #客户端配置 7-rw-r--r-- 1 root root 10246 Aug 15 19:52 storage.conf #存储节点配置 8-rw-r--r-- 1 root root 620 Aug 15 19:52 storage_ids.conf #存储节点id 9-rw-r--r-- 1 root root 9138 Aug 15 19:52 tracker.conf #跟踪器配置拷贝
FastDFS-master/conf目录下的http.conf、mime.types到配置目录/etc/fdfsbash1cp http.conf /etc/fdfs/ 2cp mime.types /etc/fdfs/
启动
修改必要配置:日志、文件存放位置,并手动创建相应的存放目录
bash1#备份配置文件 2cp tracker.conf tracker.conf.bak 3cp storage.conf storage.conf.bak 4 5#修改tracker.conf配置文件中,store和log存放位置 6# the base path to store data and log files 7base_path = /opt/FastDFS/tracker 8 9#修改storage.conf配置文件中,sotre和log存放位置、file存放位置、tracerIp 10# the base path to store data and log files 11base_path = /opt/FastDFS/storeage 12# store_path#, based on 0, to configure the store paths to store files 13store_path0 = /opt/FastDFS/storeage/files 14# tracker_server can ocur more than once for multi tracker servers. 15tracker_server = 127.0.0.1:22122使用命令启动
跟踪器、存储节点bash1#启动 跟踪器 2fdfs_trackerd /etc/fdfs/tracker.conf start 3 4#启动 存储节点 5fdfs_storaged /etc/fdfs/storage.conf start 6 7#查看启动 8ps -ef | grep fdfs 9root 10 1 0 21:19 ? 00:00:00 fdfs_trackerd tracker.conf start 10 11#发现存储节点启动没成功,查看logs 12$cat opt/fdfs/storage/logs/storaged.log 13[2021-08-15 21:26:04] ERROR - file: fdfs_shared_func.c, line: 474, host "127.0.0.1" is invalid, error in fo: Unknown host 14[2021-08-15 21:26:04] CRIT - exit abnormally! 15 16#发现tracerIp配置错误,修改后重新启动,并查看启动情况 17$ps -ef | grep fdfs 18root 10 1 0 21:19 ? 00:00:00 fdfs_trackerd /etc/fdfs/tracker.conf start 19root 5122 1 30 21:32 ? 00:00:13 fdfs_storaged /etc/fdfs/storage.conf start服务关闭
bash1#关闭跟踪器 2fdfs_trackerd /etc/fdfs/tracker.conf stop 3 4#关闭存储节点 5fdfs_storaged /etc/fdfs/storage.conf stop
FastDFS测试 ¶
测试时需要配置
client.conf文件中的traverIp和base_pathini1# the base path to store log files 2base_path = /opt/FastDFS/client 3 4# tracker_server can ocur more than once for multi tracker servers. 5tracker_server = 192.168.45.12:22122测试上传
bash1#上传 2fdfs_test /etc/fdfs/client.conf upload 1.txt 3#group_name 组名 remote_filename M00/:配置的path,00/00/:磁盘路径,wKgtDGE...:文件名 4group_name=group1, remote_filename=M00/00/00/wKgtDGEZI7uAMqbkAAAACpEbkw40686912 5 6#查看上传文件 7ll /opt/FastDFS/storeage/files/data/00/00/ 8wKgtDGEZI7uAMqbkAAAACpEbkw406869121.txt #上传的文件 9wKgtDGEZI7uAMqbkAAAACpEbkw406869121.txt-m #上传的文件属性 10wKgtDGEZI7uAMqbkAAAACpEbkw40686912_big1.txt #上传的文件备份 11wKgtDGEZI7uAMqbkAAAACpEbkw40686912_big1.txt-m测试下载
bash1fdfs_test /etc/fdfs/client.conf download group1 M00/00/00/wKgtDGEZI7uAMqbkAAAACpEbkw40686912.txt测试删除
bash1fdfs_test /etc/fdfs/client.conf delete group1 M00/00/00/wKgtDGEZI7uAMqbkAAAACpEbkw40686912.txt_big
分布式文件系统http访问 ¶
nginx的FastDFS扩展模块整合
FastDFS github下载
FastDFS-nginx-module-master,并解压bash1unzip FastDFS-nginx-module-master.zip安装nginx,添加
FastDFS模块bash1tar -zxvf nginx-1.20.1.tar.gz 2 3cd nginx-1.20.1/ 4 5#debain系列下可能需要安装先运行如下命令安装依赖 6apt-get install libpcre3 libpcre3-dev 7 8./configure --prefix=/etc/nginx-fdfs --sbin-path=/usr/bin/nginx-fdfs --add-module=/root/FastDFS-nginx-module-master/src/ 9 10make 11 12make install配置模块
ini1#将模块配置文件拷贝到 fdfs 配置目录下 2cp FastDFS-nginx-module-master/src/mod_FastDFS.conf /etc/fdfs/ 3 4#修改配置文件,基础目录(该目录必须已存在)、url带组名访问、跟踪器 5# the base path to store log files 6base_path=/opt/FastDFS/FastDFS_mod 7# if the url / uri including the group name 8url_have_group_name = true 9# FastDFS tracker_server can ocur more than once, and tracker_server 10tracker_server=192.168.45.12:22122 11# store_path must same as storage.conf 12store_path0=/opt/FastDFS/storeage/files配置nginx
ini1#拦截请求文件的路径,并使用FastDFS的nginx模块进行转发 2location ~/group[1-9]/M0[0-9]{ 3 ngx_FastDFS_module; 4}启动nginx
bash1#检测配置文件是否正确 2nginx-fdfs -c /etc/nginx-fdfs/conf/nginx.conf -t 3 4#指定配置文件启动 5nginx-fdfs -c /etc/nginx-fdfs/conf/nginx.conf 6 7#查看启动状态 8ps -ef | grep nginx浏览器访问:
http://127.0.0.1/group1/M00/00/00/wKgtDGEZI7uAMqbkAAAACpEbkw40686912
扩展模块执行流程

FastDFS在java中使用 ¶
下载
happyfish100/FastDFS-client-javajava 操作 FastDFS 源代码FastDFS-client-java是一个普通的maven项目,使用maven install安装到本地仓库创建普通的 maven 项目,添加依赖
xml1<!-- 该依赖为刚刚maven安装的 --> 2<dependency> 3 <groupId>org.csource</groupId> 4 <artifactId>FastDFS-client-java</artifactId> 5 <version>1.29-SNAPSHOT</version> 6</dependency>创建配置文件,FastDFS.properties
properties1FastDFS.tracker_servers = 192.168.45.185:22122,192.168.10.130:22122 2FastDFS.connection_pool.enabled = true 3FastDFS.connection_pool.max_count_per_entry = 500 4FastDFS.connection_pool.max_idle_time = 3600 5FastDFS.connection_pool.max_wait_time_in_ms = 1000创建
FastDFSUtil工具类java1public class FastDFSUtil { 2 private static TrackerServer trackerServer=null; //tracker 服务器对象 3 private static StorageServer storageServer=null; //storage 服务器对象 4 private static TrackerClient trackerClient=null; //tracker 客户端对象 5 private static StorageClient storageClient=null; //storage 客户端对象 6 private FastDFSUtil(){}; 7 static { 8 try { 9 // 加载Properties配置文件 10 ClientGlobal.initByProperties("FastDFS.properties"); 11 trackerClient=new TrackerClient(); 12 trackerServer=trackerClient.getTrackerServer(); 13 storageServer=trackerClient.getStoreStorage(trackerServer); 14 storageClient=new StorageClient(trackerServer,storageServer); 15 } catch (IOException e) { 16 e.printStackTrace(); 17 } catch (MyException e) { 18 e.printStackTrace(); 19 } 20 } 21 22 /** 23 * 适合上传本地图片,web上传,可以使用 uploadFile 重载方法,上传byte数组 24 * @param localFilename 本地文件名 25 * @param extName 文件扩展名 26 * @param metas 文件属性 27 * @return {@link String[]} 返回文件存储在 FastDFS 中信息,很重要 28 */ 29 public static String[] uploadFile(String localFilename, String extName, NameValuePair[] metas) throws Exception { 30 return storageClient.upload_file(localFilename,extName,metas); 31 } 32 33 /** 34 * 直接下载文件到本地,web程序可以使用download_file的重载方法,可以返回byte数组 35 * @param groupName 在fdfs服务器中存储的组,文件上传时会返回 36 * @param remoteName 在fdfs服务器中存储的具体位置,文件上传时会返回 37 * @param localName 下载到本地存储的名称 38 * @return int 返回0,代表下载成功 39 */ 40 public static int downloadFile(String groupName,String remoteName,String localName) throws Exception { 41 return storageClient.download_file(groupName,remoteName,localName); 42 } 43 44 /** 45 * 文件删除 46 * @param groupName 在fdfs服务器中存储的组,文件上传时会返回 47 * @param remoteName 在fdfs服务器中存储的具体位置,文件上传时会返回 48 * @return int 返回0代表删除成功 49 * @throws Exception 50 */ 51 public static int delFile(String groupName,String remoteName) throws Exception { 52 return storageClient.delete_file(groupName,remoteName); 53 } 54}创建测试Demo
java1public static void main(String[] args) throws Exception{ 2 //上传 3 String[] result=FastDFSUtil.uploadFile("E:\\123.jpg","jpg",null); 4 Arrays.stream(result).forEach(System.out::println); 5 // result值为:["group1","M00/00/00/wKgtuWEhM7WAG15kAAYIjBrlJRI160.jpg"] 6 7 String group="group1"; 8 String remote="M00/00/00/wKgtuWEhM7WAG15kAAYIjBrlJRI160.jpg"; 9 10 //下载 11 FastDFSUtil.downloadFile(group, remote, "e:\\1.jpg"); 12 13 //删除 14 FastDFSUtil.delFile(group,remote); 15}
注意:
需要将文件上传后返回的 String 数组保存好(一般存在数据库),它包含了上传文件在 FastDFS 服务器中存储的相关信息
FastDFS在web中使用 ¶
添加依赖,
fileupload和FastDFSxml1<dependency> 2 <groupId>commons-fileupload</groupId> 3 <artifactId>commons-fileupload</artifactId> 4 <version>1.3.3</version> 5</dependency> 6<dependency> 7 <groupId>org.csource</groupId> 8 <artifactId>FastDFS-client-java</artifactId> 9 <version>1.29-SNAPSHOT</version> 10</dependency>注册
StorageClientbeanjava1@Bean 2public StorageClient storageClient() throws MyException, IOException { 3 ClientGlobal.initByProperties("FastDFS.properties"); 4 TrackerClient trackerClient=new TrackerClient(); 5 TrackerServer trackerServer=trackerClient.getTrackerServer(); 6 StorageServer storageServer=trackerClient.getStoreStorage(trackerServer); 7 StorageClient storageClient=new StorageClient(trackerServer,storageServer); 8 return storageClient; 9}编写
文件上传控制器java1@RestController 2@RequestMapping("/file") 3public class FileController { 4 5 @Autowired 6 private StorageClient client; 7 8 @PostMapping("/upload") 9 public Object upload(@RequestParam("files") MultipartFile[] files, ) throws Exception { 10 if (files==null||files.length==0){ 11 return ResponWrapper.setSuccess(false); 12 } 13 MultipartFile file=files[0]; 14 String fileName=file.getOriginalFilename(); 15 int extIndex=fileName.lastIndexOf(".")+1; 16 String fileExtName=""; 17 if (extIndex!=0){ 18 fileExtName=fileName.substring(extIndex); 19 } 20 String[] result=client.upload_file(file.getBytes(),fileExtName,null); 21 if (result.length!=2){ 22 return ResponWrapper.setSuccess(false); 23 } 24 FileDto fileDto=new FileDto(); 25 fileDto.setGroupName(result[0]); 26 fileDto.setRemoteName(result[1]); 27 return ResponWrapper.setSuccess(true); 28 } 29 30 @RequestMapping("/download") 31 public void download(String id, HttpServletResponse response) throws Exception { 32 FileDto fileDto=fileService.selectById(id); 33 byte[] bytes=client.download_file(fileDto.getGroupName(),fileDto.getRemoteName()); 34 response.reset(); //设置页面不缓存,清空buffer 35 response.setCharacterEncoding("UTF-8"); //设置字符编码 36 response.setContentType("multipart/form-data"); //设置二进制传输数据 37 // 设置响应头 38 response.setHeader("Content-Disposition", "attachment;fileName=" + fileDto.getId()); 39 response.getOutputStream().write(bytes); 40 response.getOutputStream().flush(); 41 } 42 @RequestMapping("/delete") 43 public ResponWrapper delete(String fid,String uid) throws Exception { 44 FileDto fileDto=fileService.selectById(fid); 45 int res=client.delete_file(fileDto.getGroupName(),fileDto.getRemoteName()); 46 fileService.deleteById(uid,fid); 47 return ResponWrapper.setSuccess(true); 48 } 49}
Spring文件上传大小配置 ¶
1#springMVC允许上传单个文件最大大小
2spring.servlet.multipart.max-file-size=1MB
3#spring允许表单上传最大大小
4spring.servlet.multipart.max-request-size=10MBFastDFS集群部署 ¶

部署FastDFS集群,架构图如上,需准备7台服务器
其中 group1 有两台主机,group2 有两台主机;两台 tracker主机,需要安装 nginx,方便web访问;一台nginx主机,用作统一入口,并实现负载均衡
安装linux虚拟机(7台)
安装必要软件
bash1#lrzsz 为linux上传下载文件使用的工具 2#rz 上传 3#sz 下载 4yum install perl gcc libevent libevent-devel unzip lrzsz -y安装 tracker
bash1#安装fdfs公共库 2unzip libfastcommon-master.zip && cd ibfastcommon-master 3./make.sh 4./make.sh install 5 6#安装fdfs 7unzip FastDFS-master.zip && cd FastDFS-master 8./make.sh 9./make.sh install 10 11#拷贝必要配置文件 12cp FastDFS-master/conf/http.conf /etc/fdfs/ 13cp FastDFS-master/conf/mime.types /etc/fdfs/ 14 15#修改tracker配置文件 16base_path = /opt/FastDFS/tracker 17 18#启动tracker 19fdfs_trackerd /etc/fdfs/tracker.conf start 20 21#检查是否成功启动 22ps -ef | grep fdfs安装storage
bash1#安装fdfs公共库 2unzip libfastcommon-master.zip && cd ibfastcommon-master 3./make.sh 4./make.sh install 5 6#安装fdfs 7unzip FastDFS-master.zip && cd FastDFS-master 8./make.sh 9./make.sh install 10 11#拷贝必要配置文件 12cp FastDFS-master/conf/http.conf /etc/fdfs/ 13cp FastDFS-master/conf/mime.types /etc/fdfs/ 14 15#修改storage配置文件 16group_name = group1 / group_name = group2 17base_path = /opt/FastDFS/storeage 18store_path0 = /opt/FastDFS/storeage/files 19tracker_server = 192.168.10.129:22122 20tracker_server = 192.168.10.130:22122 21 22#启动storage 23fdfs_storaged /etc/fdfs/storage.conf start 24 25#检查是否成功启动 26ps -ef | grep fdfs关闭主机防火墙,修改tracker负载均衡策略,并使用java客户端测试程序
bash1#关闭防火墙 2systemctl status firewall #查看防火墙状态 3systemctl stop firewalld #关闭防火墙 4systemctl start firewalld #启动防火墙 5systemctl stop firewalld #重启防火墙 6 7#修改 tracker 配置文件负载策略 8# 0: round robin 9# 1: specify group 10# 2: load balance, select the max free space group to upload file 11store_lookup = 0 12 13#java客户端测试,tracker负载策略改为0时,此时tracker应轮流上传到两个group配置trcker 主机上的 nginx
bash1#单纯的为了负载均衡,配置如下 2#安装nginx 3tar -zxvf nginx-1.20.1.tar.gz & cd nginx-1.20.1/ 4./configure --prefix=/usr/local/nginx 5make 6make install 7 8#修改nginx配置文件 9upstream myweb { 10 server 192.168.10.131:80; 11 server 192.168.10.132:80; 12 server 192.168.10.133:80; 13 server 192.168.10.134:80; 14} 15location ~/group[1-9]/M0[0-9]{ 16 proxy_pass http://myweb; 17} 18 19#启动,加-t参数,校验配置文件 20/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf 21 22#检测是否启动成功 23ps -ef | grep nginx配置storage nginx
bash1#安装fdfs_nginx 2unzip FastDFS-nginx-module-master.zip 3tar -zxvf nginx-1.20.1.tar.gz & cd nginx-1.20.1/ 4./configure --prefix=/etc/nginx-fdfs --sbin-path=/usr/bin/nginx-fdfs --add-module=/root/FastDFS-nginx-module-master/src/ 5make 6make install 7cp FastDFS-nginx-module-master/src/mod_FastDFS.conf /etc/fdfs/ 8 9#配置mod_FastDFS.conf配置文件,group_name针对不同的当前storage所属的group配置 10base_path=/opt/FastDFS/FastDFS_mod 11group_name=group1 / group_name=group2 12store_path0=/opt/FastDFS/storeage/files 13url_have_group_name = true 14tracker_server=192.168.10.130:22122 15tracker_server=192.168.10.129:22122 16group_count = 2 17[group1] 18group_name=group1 19storage_server_port=23000 20store_path_count=1 21store_path0=/opt/FastDFS/storeage/files 22[group2] 23group_name=group2 24storage_server_port=23000 25store_path_count=1 26store_path0=/opt/FastDFS/storeage/files 27 28#配置nginx配置文件 29location ~/group[1-9]/M0[0-9]{ 30 ngx_FastDFS_module; 31} 32 33#启动,加-t参数,校验配置文件 34nginx-fdfs -c /etc/nginx-fdfs/conf/nginx.conf 35 36#检测是否启动成功 37ps -ef | grep nginx配置nginx负载均衡,统一入口
bash1#安装nginx 2#配置nginx配置文件 3upstream myweb { 4 server 192.168.10.129:80; 5 server 192.168.10.130:80; 6} 7location ~/group[1-9]/M0[0-9]{ 8 proxy_pass http://myweb; 9} 10 11#启动nginx,并在浏览器访问 12/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf 13 14#浏览器访问:http://192.168.10.128/group1/M00/00/00/wKgKhWFcpDSAH-LoAAPNBgx7Frs765.jpg 15#可以看到文件分析运行流程
mermaid1graph TD 2A[nginx] -->|1.携带地址负载访问带扩展模块的nginx|B[nginx_fdfs & storage] 3 B --> |2.根据扩展模块携带地址访问Tracker|C[tracker] 4 C --> |3.根据地址返回对应的Storage的ip|B 5 B --> |4.根据tracker返回的IP地址找到对应的nginx_fdfs|B 6 B --> |5.返回文件流|A