分布式文件存储
1 FastDFS介绍
FastDFS 是一个由 C 语言实现的开源轻量级分布式文件系统,作者余庆(happyfish100),支持 Linux、FreeBSD、AID 等 Unix 系统,解决了大数据存储和读写负载均衡等问题,适合存储 4KB~500MB 之间的小文件,如图片网站、短视频网站、文档、app 下载站等,UC、京东、支付宝、迅雷、酷狗等都有使用。
该软件作者是阿里巴巴大牛、chinaUnix版主余庆个人独立开发的。
2 FastDFS上传的流程
只要 storage 返回图片的路径图片名称,我们就能通过浏览器来访问图片了
3. 创建fastdfs
我们使用Docker搭建FastDFS的开发环境,虚拟机中已经下载了fastdfs的镜像,可以通过docker images
查看,如下图:
拉取镜像(已经下载了该镜像,大家无需下载了)
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.200.128:22122 -e GROUP_NAME=group1 morunchang/fastdfs sh storage.sh
- 使用的网络模式是–net=host, 此时会将宿主机的网络应用于容器,链接容器就可以直接使用宿主机的IP192.168.200.128
-
sh tracker.sh
运行tracker.sh脚本文件 - group1是组名,即storage的组
- 如果想要增加新的storage服务器,再次运行该命令,注意更换 新组名
配置Nginx
Nginx在这里主要提供对FastDFS图片访问的支持,Docker容器中已经集成了Nginx,我们需要修改nginx的配置,进入storage的容器内部,修改nginx.conf
docker exec -it storage /bin/bash
进入后
vi /etc/nginx/conf/nginx.conf
添加以下内容:
上图配置如下:
location ~ /M00 {
ngx_fastdfs_module;
}
访问图片的时候,浏览器通常都会对图片进行缓存,如果有禁止缓存,可以设置nginx配置添加禁止缓存即可。
禁止缓存:
add_header Cache-Control no-store;
退出容器:
exit
重启storage容器:
docker restart storage
查看启动容器docker ps
9f2391f73d97 morunchang/fastdfs "sh storage.sh" 12 minutes ago Up 12 seconds storage
e22a3c7f95ea morunchang/fastdfs "sh tracker.sh" 13 minutes ago Up 13 minutes tracker
开启启动设置:
docker update --restart=always tracker
docker update --restart=always storage
安装Nginx目的:
nginx集成了FastDFS,可以通过它的ngx_fastdfs_module模块,可以通过该模块访问Tracker获取图片所存储的Storage信息,然后访问Storage信息获取图片信息。
4 利用Java客户端调用FastDFS
1、在项目配置文件加上分布式文件系统的ip
fileServer:
url: http://192.168.200.128:8080/ # fastDFS 分布式文件系统的 ip:port
2、在项目resource中添加tracker.conf 配置文件
tracker_server=192.168.200.128:22122
# 连接超时时间,针对socket套接字函数connect,默认为30秒
connect_timeout=30000
# 网络通讯超时时间,默认是60秒
network_timeout=60000
2、自己封装工具类
package com.xyxy.gmall.product.util;
import org.csource.common.MyException;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
/**
* @Author 李燕茹
* @create 2022/3/19 16:27
* 文件上传工具类
*/
public class FastDFSUtil {
static {
try {
//加载classpath下的配置文件信息
ClassPathResource classPathResource = new ClassPathResource("tracker.conf");
//初始化tracker的信息
ClientGlobal.init(classPathResource.getPath());
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}
}
/**
* 文件上传
* 2022/3/19 16:28
* @param file
* @return java.lang.String
*/
public static String fileUpload(MultipartFile file) throws IOException, MyException {
//文件上传流程
//初始化trackerClient
TrackerClient trackerClient = new TrackerClient();
//获取连接
TrackerServer trackerServer = trackerClient.getConnection();
//通过tracker获取storage的信息
StorageClient storageClient = new StorageClient(trackerServer, null);
//通过storage完成文件的上传
String[] strings = storageClient.upload_file(file.getBytes(),
StringUtils.getFilenameExtension(file.getOriginalFilename()),
null);
return strings[0] + "/" + strings[1];
}
/**
* 文件下载
* 2022/3/19 16:39
* @param groupName
* @param fileName
* @return byte[]
*/
public static byte[] fileDownload(String groupName, String fileName) throws IOException, MyException {
//文件下载流程
//初始化trackerClient
TrackerClient trackerClient = new TrackerClient();
//获取服务的连接信息
TrackerServer trackerServer = trackerClient.getConnection();
//通过tracker获取storage的信息
StorageClient storageClient = new StorageClient(trackerServer,null);
//通过storage完成文文件下载
byte[] bytes = storageClient.download_file(groupName, fileName);
return bytes;
}
/**
* 文件删除
* 2022/3/19 16:41
* @param groupName
* @param fileName
* @return int
*/
public static int fileDelete(String groupName, String fileName) throws IOException, MyException {
//文件下载流程
//初始化trackerClient
TrackerClient trackerClient = new TrackerClient();
//获取服务的连接信息
TrackerServer trackerServer = trackerClient.getConnection();
//通过tracker获取storage的信息
StorageClient storageClient = new StorageClient(trackerServer,null);
//通过storage完成文文件下载
int delete = storageClient.delete_file(groupName, fileName);
return delete;
}
public static void main(String[] args) throws IOException, MyException {
//测试下载文件到本地
byte[] bytes = fileDownload("group1", "M00/00/02/wKjIgGI2DDiAeZFDAAAi3NczRJ49.4.jpg");
File file = new File("f:\\abc.jpg");
if (!file.exists()) {
file.createNewFile();
}
FileOutputStream fileOutputStream = new FileOutputStream(file);
//写入磁盘
fileOutputStream.write(bytes);
fileOutputStream.close();
}
}
4、控制层
@RestController
@RequestMapping("/admin/product")
public class FileController {
@Value("${fileServer.url}")
private String url;//获取服务器ip和端口的URL
@ApiOperation("文件上传接口")
@PostMapping("/fileUpload")
public Result fileUpload(@RequestParam MultipartFile file) throws IOException, MyException {
String imgUrl = FastDFSUtil.fileUpload(file);
return Result.ok(url+imgUrl);
}
}
5、测试
使用postman访问文件上传接口 /admin/product/fileUpload
查看上传文件返回的URL,直接放到浏览器即可访问
6、总结