FastDFS 使用流程

 

一、什么是FastDFS?


FastDFS 是用 C 语言编写的一款开源的分布式文件系统,对文件进行管理,主要功能包括:文件存储文件同步文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务。如相册网站、视频网站等等。

FastDFS 为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用 FastDFS 很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。

二、FastDFS组成要素。


 

  1)、FastDFS 架构包括跟踪器(Tracker Server)和存储服务节点(Storage Server)。客户端(Client)请求 Tracker Server进行文件上传、下载,此跟踪器主要做调度工作,在访问上起负载均衡的作用,返回给客户端一个 Storager 的 IP地址和端口。最终是通过调度 Storage Server 完成文件上传、下载等服务。
  2)、跟踪器和存储节点都可以由一台或者多台服务器构成。跟踪器和存储节点中的服务器均可以随时增加和下线而不影响线上服务。其中跟踪器中的所有服务都是对等的,可以根据服务器的压力情况随时增加和减少。
  3)、Storage Server 的作用是文件存储,客户端上传的文件最终存储在 Storage Server 服务器上,Storage Server 没有实现自己的文件系统而是利用操作系统的文件系统来管理文件。可以将 Storage 称为存储器。如上图所示:为了支持大容量,存储节点(服务器)采用了分卷(或分组)的组织方式。存储系统有一个或者多个卷组成,卷与卷之间的文件是相互独立的,所有卷的文件容量累加就是整个存储系统中的文件容量。一个卷可以由一台或多台存储服务器组成,一个卷下的存储服务器中的文件都是相同的,卷中的多台存储服务器起到了冗余备份和负载均衡的作用。
  4)、在卷中增加服务器时,同步已有的文件是由系统自动完成的,同步完成后,系统自动将新增服务器切换到线上提供服务。
  5)、当存储空间不足或即将耗尽时,可以动态添加卷。只需要增加一台或多台服务器,并将它们配置为一个新的卷,这样就扩大了存储系统的容量。
  6)、重要:FastDFS中的文件标识分为两个部分:卷名和文件名,二者缺一不可。(存储成功后,返回给客户端的两个信息)

三、文件上传及下载流程


【1】文件上传流程:

客户端上传文件后存储服务器将 文件ID 返回给客户端,此文件ID 用户以后访问该文件的索引信息。文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名,如下图:

  ♀ 组名:文件上传后所在 Storage卷名称,在上传成功后由 Storage服务器返回,客户端自行保存。
  ♂ 虚拟磁盘路径:Storage配置的虚拟路径,与磁盘选项 store_path*对应,如果配置 store_path0则是 M00,如果配置了store_1则是 M01,以此类推。
  ♀ 数据两级目录:Storage服务器在每个虚拟磁盘下创建的两级目录,用户存储文件。
  ♂ 文件名:与文件上传时不同。是由服务器根据特定信息生成,文件名包含:源存储服务器IP地址、文件创建时间戳、文件大小、随机数、文件扩展名等信息。

【2】文件下载流程:
   

四、最简单的FastDFS架构:将 tracker追踪服务器和 storage服务器部署到同一台服务器上,就是一个最简单的架构。


   

五、FastDFS安装


☞  参考:《FastDFS安装部署文档》
可以解压提供的虚拟机(留言邮箱可私发),双击 vmx文件,修改网络配置为“仅主机模式”,启动时选择“我已移动虚拟机”这样会保留原有的配置IP等信息,同时需要设置虚拟机的网段为25网段(编辑——虚拟网络编辑器——选中“仅主机”——更改设置——选中“仅主机”——选择“仅主机模式”——修改子网IP:192.168.25.0)。

六、FastDFS使用 Demo


需求:将图片上传到服务器,在控制台打印服务器返回的信息。

【1】创建 Maven 工程 fastDFSdemo:由于 FastDFS 客户端 jar 包并没有在中央仓库中,所以需要使用下列命令手动安装 jar 包到 Maven 本地仓库(将 jar 包放到d盘setup目录)

mvn install:install-file -DgroupId=org.csource.fastdfs -DartifactId=fastdfs  -Dversion=1.2 -Dpackaging=jar -Dfile=d:\setup\fastdfs_client_v1.20.jar

pom.xml 中引入:fastDFS 和 fileupload 的 jar 包。

 1 <dependency>
 2     <groupId>org.csource.fastdfs</groupId>
 3     <artifactId>fastdfs</artifactId>
 4     <version>1.2</version>
 5 </dependency>
 6 <!--用于前端上传文件-->
 7 <dependency>
 8     <groupId>commons-fileupload</groupId>
 9     <artifactId>commons-fileupload</artifactId>
10     <version>1.3.1</version>
11 </dependency>

【2】添加配置文件 fast_client.conf (将其中的服务器地址设置为:自己的 FastDFS地址)

 1 # connect timeout in seconds
 2 # default value is 30s
 3 connect_timeout=30
 4 
 5 # network timeout in seconds
 6 # default value is 30s
 7 network_timeout=60
 8 
 9 # the base path to store log files
10 base_path=/home/fastdfs
11 
12 # tracker_server can ocur more than once, and tracker_server format is
13 #  "host:port", host can be hostname or ip address
14 tracker_server=192.168.25.133:22122
15 
16 #standard log level as syslog, case insensitive, value list:
17 ### emerg for emergency
18 ### alert
19 ### crit for critical
20 ### error
21 ### warn for warning
22 ### notice
23 ### info
24 ### debug
25 log_level=info
26 
27 # if use connection pool
28 # default value is false
29 # since V4.05
30 use_connection_pool = false
31 
32 # connections whose the idle time exceeds this time will be closed
33 # unit: second
34 # default value is 3600
35 # since V4.05
36 connection_pool_max_idle_time = 3600
37 
38 # if load FastDFS parameters from tracker server
39 # since V4.05
40 # default value is false
41 load_fdfs_parameters_from_tracker=false
42 
43 # if use storage ID instead of IP address
44 # same as tracker.conf
45 # valid only when load_fdfs_parameters_from_tracker is false
46 # default value is false
47 # since V4.05
48 use_storage_id = false
49 
50 # specify storage ids filename, can use relative or absolute path
51 # same as tracker.conf
52 # valid only when load_fdfs_parameters_from_tracker is false
53 # since V4.05
54 storage_ids_filename = storage_ids.conf
55 
56 
57 #HTTP settings
58 http.tracker_server_port=80
59 
60 #use "#include" directive to include HTTP other settiongs
61 ##include http.conf

【3】创建 main 方法如下:主要设置配置文件的路径与本地上传图片的路径

 1 package com.pinyougou.fastDFS;
 2 
 3 import java.io.FileNotFoundException;
 4 import java.io.IOException;
 5 
 6 import org.csource.fastdfs.ClientGlobal;
 7 import org.csource.fastdfs.StorageClient;
 8 import org.csource.fastdfs.StorageServer;
 9 import org.csource.fastdfs.TrackerClient;
10 import org.csource.fastdfs.TrackerServer;
11 
12 public class fastDemo {
13     public static void main(String[] args) throws FileNotFoundException, IOException, Exception {
14                 //加载配置文件
15         ClientGlobal.init("E:\\learnWorkspaces\\demo\\fastDFS\\src\\main\\resources\\fdfs_client.conf");
16         //构建一个管理者客户端
17         TrackerClient trackerClient = new TrackerClient();
18                 //连接管理者服务端
19         TrackerServer trackerServer = trackerClient.getConnection();
20                 //声明存储服务器
21         StorageServer storageServer = null;
22                 //获取村粗服务器客户端对象
23         StorageClient storageClient = new StorageClient(trackerServer, storageServer);
24                 //上传文件
25         String[] upload_file = storageClient.upload_file("D:\\tools\\FastDFS\\aa.jpg", "jpg", null);
26                 //显示上传结果
27         for(String file:upload_file) {
28             System.out.println(file);
29         }
30     }
31 }

控制台输出结果格式:

1 group1
2 M00/00/00/wKgZhVkMP4KAZEy-AAA-tCf93Fo973.jpg

在浏览器汇中输入 url就可以访问图片:http://192.168.25.133/group1/M00/00/00/wKgZhVkMP4KAZEy-AAA-tCf93Fo973.jpg

七、基于 Demo扩展到实战


【1】springmvc.xml 中配置多媒体解析器,解析图片信息。

1 <!-- 配置多媒体解析器 -->
2 <bean id="multipartResolver"     class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
3     <property name="defaultEncoding" value="UTF-8"></property>
4     <!-- 设定文件上传的最大值5MB,5*1024*1024 -->
5     <property name="maxUploadSize" value="5242880"></property>
6 </bean>

【2】写一个 FastDFS客户端公共方法(工具类:可直接复制使用)

 1 public class FastDFSClient {
 2 
 3     private TrackerClient trackerClient = null;
 4     private TrackerServer trackerServer = null;
 5     private StorageServer storageServer = null;
 6     private StorageClient1 storageClient = null;
 7     
 8     public FastDFSClient(String conf) throws Exception {
 9         if (conf.contains("classpath:")) {
10             conf = conf.replace("classpath:", this.getClass().getResource("/").getPath());
11         }
12         ClientGlobal.init(conf);
13         trackerClient = new TrackerClient();
14         trackerServer = trackerClient.getConnection();
15         storageServer = null;
16         storageClient = new StorageClient1(trackerServer, storageServer);
17     }
18     
19     /**
20      * 上传文件方法
21      * <p>Title: uploadFile</p>
22      * <p>Description: </p>
23      * @param fileName 文件全路径
24      * @param extName 文件扩展名,不包含(.)
25      * @param metas 文件扩展信息
26      * @return
27      * @throws Exception
28      */
29     public String uploadFile(String fileName, String extName, NameValuePair[] metas) throws Exception {
30         String result = storageClient.upload_file1(fileName, extName, metas);
31         return result;
32     }
33     
34     public String uploadFile(String fileName) throws Exception {
35         return uploadFile(fileName, null, null);
36     }
37     
38     public String uploadFile(String fileName, String extName) throws Exception {
39         return uploadFile(fileName, extName, null);
40     }
41     
42     /**
43      * 上传文件方法
44      * <p>Title: uploadFile</p>
45      * <p>Description: </p>
46      * @param fileContent 文件的内容,字节数组
47      * @param extName 文件扩展名
48      * @param metas 文件扩展信息
49      * @return
50      * @throws Exception
51      */
52     public String uploadFile(byte[] fileContent, String extName, NameValuePair[] metas) throws Exception {
53         
54         String result = storageClient.upload_file1(fileContent, extName, metas);
55         return result;
56     }
57     
58     public String uploadFile(byte[] fileContent) throws Exception {
59         return uploadFile(fileContent, null, null);
60     }
61     
62     public String uploadFile(byte[] fileContent, String extName) throws Exception {
63         return uploadFile(fileContent, extName, null);
64     }
65 }

【3】Controller类处理逻辑展示,具体注释说明:

 1 @RestController
 2 public class uploadController {
 3     //当配置文件已经有springmvc.xml引入后,可以通过如下方式获取到
 4     //配置文件中配置如下:FILE_SERVER_URL=http://192.168.25.133/
 5     @Value("${FILE_SERVER_URL}")
 6     private String FILE_SERVER_URL;
 7     
 8     @RequestMapping("/upload")
 9     public Result upload(MultipartFile file) {
10         //1、获取文件名称(全名)
11         String filename = file.getOriginalFilename();
12         //截取文件的后缀名(不包含.)
13         String exName=filename.substring(filename.lastIndexOf(".")+1);
14         try {
15             //2、获取FastDFS客户端
16             FastDFSClient fastDFSClient = new FastDFSClient("classpath:config/fdfs_client.conf");
17             //3、执行上传
18             String path = fastDFSClient.uploadFile(filename, exName);
19             //4、将返回的图片地址与服务器http:ip地址组装
20             String url = FILE_SERVER_URL+path;
21             //5、返回url
22             return new Result(true, url);
23             
24         } catch (Exception e) {
25             e.printStackTrace();
26             return new Result(false, "上传失败");
27         }
28     }
29 }

【4】前端 Server.js请求的规范书写

 1 app.service("uploadService",function($http){
 2     this.uploadFile=function(){
 3         /*
 4          * FormData对象用以将数据编译成键值对,以便用XMLHttpRequest来发送数据。
 5          * 其主要用于发送表单数据,但亦可用于发送带键数据(keyed data),而独立于表单使用。
 6          */
 7         var formData = new FormData();
 8         /*
 9          * 我们再看这行代码的背景,HTML5支持multiple属性,
10          * 即<input type="file">可能会添加multiple属性并赋值:multiple="multiple",
11          * 即<input type="file" multiple="multiple">,这样一次性可同时上传多张图片,
12          * 所以获得一张图片的方法就是:$('xx')[0].files[0]
13          */
14         formData.append("file",file.files[0]);
15         return $http({
16             method:"POST",
17             url:"../upload.do",
18             data:"formData",
19             /*
20              * anjularjs对于post和get请求默认的Content-Type header 是application/json。
21              * 通过设置‘Content-Type’: undefined,这样浏览器会帮我们把Content-Type 
22              * 设置为 multipart/form-data。
23              */
24             headers:{'Content-Type':undefined},
25             /*
26              * 通过设置 transformRequest: angular.identity ,
27              * anjularjs transformRequest function 将序列化我们的formdata object.
28              */
29             transformRequest: angular.identity
30         });
31     }
32 });

【5】可以将返回的 url 赋值给 src="" 中,便可以通过浏览器渲染获得图片信息。

posted @ 2020-11-19 15:09  Java程序员进阶  阅读(686)  评论(0编辑  收藏  举报