fastdfs分布式文件存储
认识fastdfs
了解fastdfs
FastDFS是由国人余庆所开发,其项目地址https://github.com/happyfish100
FastDFS是一个轻量级的开源分布式文件系统,主要解决了大容量的文件存储和高并发访问的问题,文件存取时实现了负载均衡。
支持存储服务器在线扩容,支持相同的文件只保存一份,节约磁盘。
FastDFS只能通过Client API访问,不支持POSIX访问方式。
FastDFS适合中大型网站使用,用来存储资源文件(如:图片、文档、视频等)
FastDFS组成部分
FastDFS由跟踪服务器(tracker server)、存储服务器(storage server)和客户端(client)三个部分组成,主要解决了海量数据存储问题,特别适合以中小文件(建议范围:4KB < file_size <500MB)为载体的在线服务。
Tracker server(跟踪服务器)
跟踪服务器:用来调度来自客户端的请求。且在内存中记录所有存储组和存储服务器的信息状态。
Storage server(存储服务器)
用来存储文件(data)和文件属性(metadata)
Client客户端
提供基本文件访问接口,比如upload、download、append、delete等,以客户端库的方式提供给用户使用。
FastDFS服务器架构
- 存储服务器会定期向跟踪服务器发送状态信息(心跳包)。
- 客户端发起上传请求时,向跟踪服务器查询可用的存储服务器。
- 客户端向存储服务器上传文件内容,存储服务器保存文件并生成文件路径以及文件名
- 存储服务器将路径及文件名返回给客户端
使用
jar包准备
- Maven
<dependency>
<groupId>org.csource</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27</version>
</dependency>
<!--用于读字节数组 方法FileUtils-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
配置文件
resources文件夹下fdfs_client.conf( text格式 )
connect_timeout = 2 //连接超时时间
network_timeout = 30 //网络连接超时时间
charset = UTF-8
http.tracker_http_port = 8111
tracker_server = 192.168.20.252:22122 //跟踪服务器IP地址
使用客户端api
public class DfsUtil {
private static TrackerClient client = null;
private static String httpPort = null;
private static String REAL_NAME = "realName";
private static String FILE_SIZE = "size";
private static String UPLOAD_TIME = "uploadTime";
//初始化fastdfs服务
static {
String conf_path = DfsUtil.class.getClassLoader().getResource("fdfs_client.conf").getPath();
try {
//加载conf配置文件
ClientGlobal.init(conf_path);
//所有的跟踪服务器信息在TrackerClient对象中。
//知道所有的跟踪服务器组
client = new TrackerClient();
// 得到http服务端口
httpPort = ClientGlobal.getG_tracker_http_port() + "";
} catch (Exception e) {
e.printStackTrace();
}
}
//上传(文件信息,文件的元数据信息)
//byte[] bytes 一般用于10M以下文件
public static String upload(byte[] bytes,String realName,long size){
TrackerServer ts = null;
//创建存储服务器对象
StorageServer ss = null;
StorageClient1 storageClient1 = null;
try {
//从跟踪服务器组拿到一个具体的跟踪服务器
ts = client.getConnection();
//即使传入的存储服务器对象为null也会自动分配
//也可以指定具体存储服务器对象 一般为null
storageClient1 = new StorageClient1(ts, ss);
//获取文件后缀名
String extName = realName.substring(realName.lastIndexOf(".") + 1);
//元数据列表,(类似写的注释)上传文件习惯把上传日期,文件大小,文件真实名
NameValuePair[] metaList = new NameValuePair[]{
new NameValuePair(REAL_NAME,realName),
new NameValuePair(FILE_SIZE,size+""),
new NameValuePair(UPLOAD_TIME,System.currentTimeMillis()+""),
};
//上传 并返回上传结果
String s = storageClient1.upload_file1(bytes, extName, metaList);
return s;
} catch (Exception e) {
e.printStackTrace();
}finally {
//释放连接
if(storageClient1!=null)storageClient1=null;
if(ss!=null) {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(ts!=null){
try {
ts.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
//获取文件元数据信息
public static Map<String,String> getMetaList(String path){
TrackerServer ts = null;
StorageServer ss = null;
StorageClient1 storageClient1 = null;
try {
ts = client.getConnection();
storageClient1 = new StorageClient1(ts, ss);
//根据得来的路径从数据库拉取资源 返回数组
NameValuePair[] metadata1 = storageClient1.get_metadata1(path);
//遍历数组 放入集合map
Map<String,String> result = new HashMap<>();
for(NameValuePair nv:metadata1){
result.put(nv.getName(),nv.getValue());
}
return result;
} catch (Exception e) {
e.printStackTrace();
}finally {
if(storageClient1!=null)storageClient1=null;
if(ss!=null) {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(ts!=null){
try {
ts.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
//下载
public static byte[] download(String path){
TrackerServer ts = null;
StorageServer ss = null;
StorageClient1 storageClient1 = null;
try {
ts = client.getConnection();//
storageClient1 = new StorageClient1(ts, ss);
byte[] bytes = storageClient1.download_file1(path);
return bytes;
} catch (Exception e) {
e.printStackTrace();
}finally {
if(storageClient1!=null)storageClient1=null;
if(ss!=null) {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(ts!=null){
try {
ts.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
//删除
public static boolean delete(String path){
TrackerServer ts = null;
StorageServer ss = null;
StorageClient1 storageClient1 = null;
try {
ts = client.getConnection();//
storageClient1 = new StorageClient1(ts, ss);
//表示删除文件,0成功,2失败
int i = storageClient1.delete_file1(path);
return i==0?true:false;
} catch (Exception e) {
e.printStackTrace();
}finally {
if(storageClient1!=null)storageClient1=null;
if(ss!=null) {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(ts!=null){
try {
ts.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return false;
}
//生成HttpUrl 用于图片展示等
public static String getHttpPath(String path){
String url ="http://";
try {
//得到一台具体的跟踪服务器
TrackerServer connection = client.getConnection();
//得到跟踪服务器的主机名
String hostName = connection.getInetSocketAddress().getHostName();
url = url+hostName+":"+httpPort+"/"+path;
return url;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
//Test
public class AppTest
{
/**
* Rigorous Test :-)
*/
//上传
@Test
public void upload() throws IOException {
File f = new File("C:/Users/JAVASM/Desktop/学习笔记/学习中/java/java图片/4.jpg");
byte[] bytes = FileUtils.readFileToByteArray(f);
String name = f.getName();
long length = f.length();
String upload = DfsUtil.upload(bytes, name, length);
System.out.println(upload);
//group1/M00/00/12/wKgU_F9yra6AUyizAACoxG3uRvc315.jpg group1-存储服务器
}
//获取文件元数据信息
@Test
public void getMetaDatas(){
String path = "group1/M00/00/12/wKgU_F9yra6AUyizAACoxG3uRvc315.jpg";
Map<String, String> metaList = DfsUtil.getMetaList(path);
System.out.println(metaList);
}
//下载 用到了
@Test
public void download() throws IOException {
String path = "group1/M00/00/12/wKgU_F9yra6AUyizAACoxG3uRvc315.jpg";
byte[] download = DfsUtil.download(path);
File f = new File("D:/aa.png");
FileUtils.writeByteArrayToFile(f,download);
}
//删除
@Test
public void del() throws IOException {
String path = "group1/M00/00/12/wKgU_F9yra6AUyizAACoxG3uRvc315.jpg";
boolean delete = DfsUtil.delete(path);
}
//生成HttpUrl
@Test
public void getHttpPath(){
String path = "group1/M00/00/12/wKgU_F9yra6AUyizAACoxG3uRvc315.jpg";
String httpPath = DfsUtil.getHttpPath(path);
System.out.println(httpPath);
}
}