FastDFS
- FastDFS简介
FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。
- FastDFS架构
主要包括Tracker和Storage。客户端请求Tracker server进行文件的上传和下载,实际是通过Tracker server调度最终由Storage server完成文件的上传和下载。
- 上传流程
第一步:Storage Server定时向Tracker Server上传状态信息给Tracker Server。
第二步:Client发的请求到Tracker Server,它会查询可用的Storage,然后把storage的ip和端口号返回给Client
第三步:上传文件(file content和metadata)生成file_id
第四步:将上传内容写入磁盘
第五步:返回文件的id和文件信息,储存在数据库中。
- 返回的ID解析
这里返回的是一个虚拟路径
1、group1,它是组名,因为Storage它是一组一组的集群,所以这个是组名
2、M00,它是storage配置的虚拟路径,与磁盘选项的store_path*对应。如果配置了store_path0则是M00,配置了store_path1就是M01,以此类推。
3、02/04就是文件的两级目录
4、下面就是文件名
- FastDFS搭建
5.1安装FastDFS镜像
拉取镜像
docker pull morunchang/fastdfs
运行tracker
docker run -d --name tracker --net=host morunchang/fastdfs sh tracker.sh
运行storage
docker run -d --name storage --net=host -e TRACKER_IP=192.168.211.132:22122 -e GROUP_NAME=group1 morunchang/fastdfs sh storage.sh
说明一下这条命令:
1、-net使用的网络模式是–net=host, 192.168.211.132是宿主机的IP(替换成自己的)
2、group1是组名,即storage的组
如果想要增加新的storage服务器,再次运行该命令,注意更换新组名
配置Nginx,不拦截上传内容
首先修改nginx.conf
docker exec -it storage /bin/bash
然后执行:
vi /etc/nginx/conf/nginx.conf
在文件中添加一下内容
location ~ /M00 {
root /data/fast_data/data;
ngx_fastdfs_module;
}
设置禁止缓存:
add_header Cache-Control no-store;
为什么设置禁止缓存?
因为比如在删除图片之后,服务器端的Storage已经删除了图片,可是还能访问到,那就是缓存的问题,所以禁止缓存。
退出容器
exit
重启storage容器
docker restart storage
查看启动容器
docker ps
开启启动设置
docker update --restart=always tracker
docker update --restart=always storage
SpringBoot整合FastDFS
1、导入依赖
<dependency>
<groupId>net.oschina.zcx7878</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27.0.0</version>
</dependency>
2、FastDFS配置
在resources文件夹下创建fasfDFS的配置文件fdfs_client.conf,并写入
connect_timeout=60
network_timeout=60
charset=UTF-8
http.tracker_http_port=8080
tracker_server=这个写自己的ip和端口
connect_timeout:连接超时时间,单位为秒。
network_timeout:通信超时时间,单位为秒。发送或接收数据时。假设在超时时间后还不能发送或接收数据,则本次网络通信失败
charset: 字符集
http.tracker_http_port :.tracker的http端口
tracker_server: tracker服务器IP和端口设置
3、application.yml配置
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
application:
name: file
server:
port: 18082
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:7001/eureka
instance:
prefer-ip-address: true
feign:
hystrix:
enabled: true
4、文件上传
文件信息封装
文件上传一般都有文件的名字、文件的内容、文件的扩展名、文件的md5值、文件的作者等相关属性,我们可以创建一个对象封装这些属性,代码如下:
package com.shop.file.test;
import org.csource.fastdfs.*;
import org.junit.Test;
import java.io.*;
import java.net.InetSocketAddress;
/**
* 描述
*
* @author lqf
* @version 1.0
* @package PACKAGE_NAME *
* @since 1.0
*/
public class FastdfsClientTest {
/**
* 文件上传
*
* @throws Exception
*/
@Test
public void upload() throws Exception {
//加载全局的配置文件
ClientGlobal.init("C:\\Users\\Administrator\\IdeaProjects\\beike\\changgou\\changgou-service\\changgou-service-file\\src\\main\\resources\\fdfs_client.conf");
//创建TrackerClient客户端对象
TrackerClient trackerClient = new TrackerClient();
//通过TrackerClient对象获取TrackerServer信息
TrackerServer trackerServer = trackerClient.getConnection();
//获取StorageClient对象
StorageClient storageClient = new StorageClient(trackerServer, null);
//执行文件上传
String[] jpgs = storageClient.upload_file("C:\\Users\\Administrator\\Pictures\\5b13cd6cN8e12d4aa.jpg", "jpg", null);
for (String jpg : jpgs) {
System.out.println(jpg);
}
}
@Test
public void delete() throws Exception {
//加载全局的配置文件
ClientGlobal.init("C:\\Users\\Administrator\\IdeaProjects\\beike\\changgou\\changgou-service\\changgou-service-file\\src\\main\\resources\\fdfs_client.conf");
//创建TrackerClient客户端对象
TrackerClient trackerClient = new TrackerClient();
//通过TrackerClient对象获取TrackerServer信息
TrackerServer trackerServer = trackerClient.getConnection();
//获取StorageClient对象
StorageClient storageClient = new StorageClient(trackerServer, null);
//执行文件上传
int group1 = storageClient.delete_file("group1", "M00/00/00/wKjThF1VEiyAJ0xzAANdC6JX9KA522.jpg");
System.out.println(group1);
}
@Test
public void download() throws Exception {
//加载全局的配置文件
ClientGlobal.init("C:\\Users\\Administrator\\IdeaProjects\\beike\\changgou\\changgou-service\\changgou-service-file\\src\\main\\resources\\fdfs_client.conf");
//创建TrackerClient客户端对象
TrackerClient trackerClient = new TrackerClient();
//通过TrackerClient对象获取TrackerServer信息
TrackerServer trackerServer = trackerClient.getConnection();
//获取StorageClient对象
StorageClient storageClient = new StorageClient(trackerServer, null);
//执行文件上传
byte[] bytes = storageClient.download_file("group1", "M00/00/00/wKjThF1VFfKAJRJDAANdC6JX9KA980.jpg");
File file = new File("D:\\ceshi\\1234.jpg");
FileOutputStream fileOutputStream = new FileOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
bufferedOutputStream.write(bytes);
bufferedOutputStream.close();
fileOutputStream.close();
}
//获取文件的信息数据
@Test
public void getFileInfo() throws Exception {
//加载全局的配置文件
ClientGlobal.init("C:\\Users\\Administrator\\IdeaProjects\\beike\\changgou\\changgou-service\\changgou-service-file\\src\\main\\resources\\fdfs_client.conf");
//创建TrackerClient客户端对象
TrackerClient trackerClient = new TrackerClient();
//通过TrackerClient对象获取TrackerServer信息
TrackerServer trackerServer = trackerClient.getConnection();
//获取StorageClient对象
StorageClient storageClient = new StorageClient(trackerServer, null);
//执行文件上传
FileInfo group1 = storageClient.get_file_info("group1", "M00/00/00/wKjThF1VFfKAJRJDAANdC6JX9KA980.jpg");
System.out.println(group1);
}
//获取组相关的信息
@Test
public void getGroupInfo() throws Exception {
//加载全局的配置文件
ClientGlobal.init("C:\\Users\\Administrator\\IdeaProjects\\beike\\changgou\\changgou-service\\changgou-service-file\\src\\main\\resources\\fdfs_client.conf");
//创建TrackerClient客户端对象
TrackerClient trackerClient = new TrackerClient();
//通过TrackerClient对象获取TrackerServer信息
TrackerServer trackerServer = trackerClient.getConnection();
StorageServer group1 = trackerClient.getStoreStorage(trackerServer, "group1");
System.out.println(group1.getStorePathIndex());
//组对应的服务器的地址 因为有可能有多个服务器.
ServerInfo[] group1s = trackerClient.getFetchStorages(trackerServer, "group1", "M00/00/00/wKjThF1VFfKAJRJDAANdC6JX9KA980.jpg");
for (ServerInfo serverInfo : group1s) {
System.out.println(serverInfo.getIpAddr());
System.out.println(serverInfo.getPort());
}
}
@Test
public void getTrackerInfo() throws Exception {
//加载全局的配置文件
ClientGlobal.init("C:\\Users\\Administrator\\IdeaProjects\\beike\\changgou\\changgou-service\\changgou-service-file\\src\\main\\resources\\fdfs_client.conf");
//创建TrackerClient客户端对象
TrackerClient trackerClient = new TrackerClient();
//通过TrackerClient对象获取TrackerServer信息
TrackerServer trackerServer = trackerClient.getConnection();
InetSocketAddress inetSocketAddress = trackerServer.getInetSocketAddress();
System.out.println(inetSocketAddress);
}
}
因为有很多重复代码,上述代码可以优化,自己可以私下优化
5、Postman测试文件上传
然后复制上边的链接就可以访问图片地址了
8080是storage的容器的nginx端口,如果想修改该端口可以直接进入到storage容器,然后修改即可
docker exec -it storage /bin/bash
vi /etc/nginx/conf/nginx.conf
修改listen:8080,然后重启就可以访问了
补充文件的访问流程
client根据url访问,通过egnix找到storage
拜拜