FastDFS使用
FastDFS简介
为什么
- 在分布式集群环境下,文件上传至节点A,这时通过负载均衡算法,访问到节点B,则不能访问到文件,这时 会出现有时能访问有时不能访问的问题 2. 同时要考虑为文件做冗余备份、负载均衡、线性扩容等功能,这些都是单节点文件上传所不具备的 FastDFS体系结构
FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问 (文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网 站、视频网站等等。
FastDFS体系结构
- FastDFS为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标, 使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。
FastDFS 架构包括 Tracker server 和 Storage server。客户端请求 Tracker server 进行文件上传、下载,通过 Tracker server 调度终由 Storage server 完成文件上传和下载。 Tracker server 作用是负载均衡和调度,通过 Tracker server 在文件上传时可以根据一些策略找到Storage server 提供文件上传服务。可以将 tracker 称为追踪服务器或调度服务器。Storage server 作用是文件存储,客户端上传 的文件终存储在 Storage 服务器上,Storageserver 没有实现自己的文件系统而是利用操作系统的文件系统来管 理文件。可以将storage称为存储服务器。
使用docker安装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=虚拟机ip:22122 -e GROUP_NAME=group1 morunchang/fastdfs sh storage.sh
使用的网络模式是–net=host,host模式可以不用映射容器端口宿主机, 替换为你机器的Ip即可 是组名,即storage的组 如果想要增加新的storage服务器,再次运行该命令,注意更换 新组名
在项目中使用
1.引入依赖
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.26.7</version>
</dependency>
2.在配置文件中配置:(这里用application.yml)
fdfs:
# 链接超时
connect-timeout: 60
# 读取时间 so-timeout: 60 # 生成缩略图参数
thumb-image:
width: 150
height: 150
tracker-list: 虚拟机ip:22122
3.编写一个配置类
import com.github.tobato.fastdfs.FdfsClientConfig; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableMBeanExport; import org.springframework.context.annotation.Import; import org.springframework.jmx.support.RegistrationPolicy;
@Configuration
@Import(FdfsClientConfig.class)
public class DfsConfig {
}
4.使用方法
private static final Logger LOGGER = LoggerFactory.getLogger(FileDfsUtil.class); @Resource
private FastFileStorageClient storageClient ;
/** * 上传文件 */
public String upload(MultipartFile multipartFile) throws Exception{
String originalFilename = multipartFile.getOriginalFilename(). substring(multipartFile.getOriginalFilename().
lastIndexOf(".") + 1);
StorePath storePath = this.storageClient.uploadImageAndCrtThumbImage( multipartFile.getInputStream(), multipartFile.getSize(),originalFilename , null);
return storePath.getFullPath() ;
}
/** * 删除文件 */
public void deleteFile(String fileUrl) {
if (StringUtils.isEmpty(fileUrl)) {
LOGGER.info("fileUrl == >>文件路径为空...");
return;
}
try {
StorePath storePath = StorePath.parseFromUrl(fileUrl); storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
} catch (Exception e) {
LOGGER.info(e.getMessage());
}
}