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 包。
<dependency>
<groupId>org.csource.fastdfs</groupId>
<artifactId>fastdfs</artifactId>
<version>1.2</version>
</dependency>
<!--用于前端上传文件-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
2)、添加配置文件 fast_client.conf (将其中的服务器地址设置为:自己的 FastDFS 地址)
# connect timeout in seconds
# default value is 30s
connect_timeout=30
# network timeout in seconds
# default value is 30s
network_timeout=60
# the base path to store log files
base_path=/home/fastdfs
# tracker_server can ocur more than once, and tracker_server format is
# "host:port", host can be hostname or ip address
tracker_server=192.168.25.133:22122
#standard log level as syslog, case insensitive, value list:
### emerg for emergency
### alert
### crit for critical
### ERROR
### warn for warning
### notice
### info
### debug
log_level=info
# if use connection pool
# default value is false
# since V4.05
use_connection_pool = false
# connections whose the idle time exceeds this time will be closed
# unit: second
# default value is 3600
# since V4.05
connection_pool_max_idle_time = 3600
# if load FastDFS parameters from tracker server
# since V4.05
# default value is false
load_fdfs_parameters_from_tracker=false
# if use storage ID instead of IP address
# same as tracker.conf
# valid only when load_fdfs_parameters_from_tracker is false
# default value is false
# since V4.05
use_storage_id = false
# specify storage ids filename, can use relative or absolute path
# same as tracker.conf
# valid only when load_fdfs_parameters_from_tracker is false
# since V4.05
storage_ids_filename = storage_ids.conf
#HTTP settings
http.tracker_server_port=80
#use "#include" directive to include HTTP other settiongs
##include http.conf
3)、创建 main 方法如下:主要设置配置文件的路径与本地上传图片的路径
package com.pinyougou.fastDFS;
import java.io.filenotfoundException;
import java.io.IOException;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
public class fastDemo {
public static void main(String[] args) throws FileNotFoundException, IOException, Exception {
//加载配置文件
ClientGlobal.init("E:\\learnWorkspaces\\demo\\fastDFS\\src\\main\\resources\\fdfs_client.conf");
//构建一个管理者客户端
TrackerClient trackerClient = new TrackerClient();
//连接管理者服务端
TrackerServer trackerServer = trackerClient.getConnection();
//声明存储服务器
StorageServer storageServer = null;
//获取村粗服务器客户端对象
StorageClient storageClient = new StorageClient(trackerServer, storageServer);
//上传文件
String[] upload_file = storageClient.upload_file("D:\\tools\\FastDFS\\aa.jpg", "jpg", null);
//显示上传结果
for(String file:upload_file) {
System.out.println(file);
}
}
}
控制台输出结果格式:
group1
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 中配置多媒体解析器,解析图片信息。
<!-- 配置多媒体解析器 -->
<bean id="multipartresolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"></property>
<!-- 设定文件上传的最大值5MB,5*1024*1024 -->
<property name="maxUploadSize" value="5242880"></property>
</bean>
2)、写一个FastDFS客户端公共方法(工具类:可直接复制使用)
public class FastDFSClient {
private TrackerClient trackerClient = null;
private TrackerServer trackerServer = null;
private StorageServer storageServer = null;
private StorageClient1 storageClient = null;
public FastDFSClient(String conf) throws Exception {
if (conf.contains("classpath:")) {
conf = conf.replace("classpath:", this.getClass().getResource("/").getPath());
}
ClientGlobal.init(conf);
trackerClient = new TrackerClient();
trackerServer = trackerClient.getConnection();
storageServer = null;
storageClient = new StorageClient1(trackerServer, storageServer);
}
/**
* 上传文件方法
* <p>title: uploadFile</p>
* <p>Description: </p>
* @param fileName 文件全路径
* @param extName 文件扩展名,不包含(.)
* @param metas 文件扩展信息
* @return
* @throws Exception
*/
public String uploadFile(String fileName, String extName, namevaluepair[] metas) throws Exception {
String result = storageClient.upload_file1(fileName, extName, metas);
return result;
}
public String uploadFile(String fileName) throws Exception {
return uploadFile(fileName, null, null);
}
public String uploadFile(String fileName, String extName) throws Exception {
return uploadFile(fileName, extName, null);
}
/**
* 上传文件方法
* <p>Title: uploadFile</p>
* <p>Description: </p>
* @param filecontent 文件的内容,字节数组
* @param extName 文件扩展名
* @param metas 文件扩展信息
* @return
* @throws Exception
*/
public String uploadFile(byte[] fileContent, String extName, NameValuePair[] metas) throws Exception {
String result = storageClient.upload_file1(fileContent, extName, metas);
return result;
}
public String uploadFile(byte[] fileContent) throws Exception {
return uploadFile(fileContent, null, null);
}
public String uploadFile(byte[] fileContent, String extName) throws Exception {
return uploadFile(fileContent, extName, null);
}
}
3)、controller类处理逻辑展示,具体注释说明:
@RestController
public class uploadController {
//当配置文件已经有springmvc.xml引入后,可以通过如下方式获取到
//配置文件中配置如下:FILE_SERVER_URL=http://192.168.25.133/
@Value("${FILE_SERVER_URL}")
private String FILE_SERVER_URL;
@requestMAPPing("/upload")
public Result upload(MultipartFile file) {
//1、获取文件名称(全名)
String filename = file.getOriginalFilename();
//截取文件的后缀名(不包含.)
String exName=filename.substring(filename.lastindexof(".")+1);
try {
//2、获取FastDFS客户端
FastDFSClient fastDFSClient = new FastDFSClient("classpath:config/fdfs_client.conf");
//3、执行上传
String path = fastDFSClient.uploadFile(filename, exName);
//4、将返回的图片地址与服务器http:ip地址组装
String url = FILE_SERVER_URL+path;
//5、返回url
return new Result(true, url);
} catch (Exception e) {
e.printstacktrace();
return new Result(false, "上传失败");
}
}
}
4)、前端Server.js请求的规范书写
app.service("uploadService",function($http){
this.uploadFile=function(){
/*
* FormData对象用以将数据编译成键值对,以便用XMLHttpRequest来发送数据。
* 其主要用于发送表单数据,但亦可用于发送带键数据(keyed data),而独立于表单使用。
*/
var formData = new FormData();
/*
* 我们再看这行代码的背景,HTML5支持multiple属性,
* 即<input type="file">可能会添加multiple属性并赋值:multiple="multiple",
* 即<input type="file" multiple="multiple">,这样一次性可同时上传多张图片,
* 所以获得一张图片的方法就是:$('xx')[0].files[0]
*/
formData.append("file",file.files[0]);
return $http({
method:"POST",
url:"../upload.do",
data:"formData",
/*
* anjularjs对于post和get请求默认的Content-Type header 是application/json。
* 通过设置‘Content-Type’: undefined,这样浏览器会帮我们把Content-Type
* 设置为 multipart/form-data。
*/
headers:{'Content-Type':undefined},
/*
* 通过设置 transformRequest: angular.identity ,
* anjularjs transformRequest function 将序列化我们的formdata object.
*/
transformRequest: angular.identity
});
}
});
5)、可以将返回的 url 赋值给 src="" 中,便可以通过浏览器渲染获得图片信息。
相关阅读
C#中Directory.GetFiles() 函数的使用方法(读取目录中
转自:http://www.365jz.com/article/24023 C#中Directory.GetFiles(string path , string searchPattern, SearchOption sea
UBUNTU18安装rosVO框架的搭建 高翔书中的源程序出错 cmake…时说没有.opencv31,我的电脑中装的时4.0版本,需要重新安装3.1安装过程中,3.1也出错
就像生物体一样,信息也会随着时间的推移而更新。今年有用的信息,过几年可能就没那么重要了。所以给你的内容加上时间戳是很重要的。
本文转载自:Linux中apt与apt-get命令的区别与解释以及Linux命令apt-get使用方式Ubuntu 16.04 发布时,一个引人注目的新特性便是 apt
前言 毕业论文中需要使用Ctex来写,但是之前完全没有接触过这个软件,所以就打算记录一下自己的学习过程。本来打算自己写一下相关