1.什么是分布式文件系统?
分布式文件系统(DFS):指文件系统管理的物理存储资源不一定直接在本地节点上,而是通过计算机网络与节点连接。
2. 什么是FastDFS?
FastDFS是淘宝的余庆先生开发的轻量级,高性能的开源分布式文件系统。
两个主要的角色:Tracker Server(跟踪服务器) 和 Storage Server(存储服务器)
- Tracker Server:跟踪服务器,主要负责调度storage节点与client通信, 在访问上
起负载均衡
的作用,和记录storage节点的运行状态,是连接 client和storage节点的枢纽。 - Storage Server:存储服务器,保存文件和文件的meta data(元数据),每个storage server会启动一个单独的线程主动向Tracker cluster 中每个tracker server报告其状态信息,包括磁盘使用情况,文件同步情况 及文件上传下载次数统计等信息
- Group:文件组,多台Storage Server的集群。上传一个文件到同组内的 一台机器上后,FastDFS会将该文件即时同步到同组内的其它所有机器上, 起到备份的作用。不同组的服务器,保存的数据不同,而且相互独立,不 进行通信。
- Tracker Cluster:跟踪服务器的集群,有一组Tracker Server(跟踪服务 器)组成。
- Storage Cluster :存储集群,有多个Group组成。
3.配置与使用
使用开源的FastDFS客户端,支持SpringBoot2.0 tobato/FastDFS_client
3.1 引入依赖
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.26.2</version>
</dependency>
3.2 引入配置类
/**
* @author fenco
*/
@Configuration
@Import(FdfsClientConfig.class)
/**
*解决JMX重复注册bean问题
*/
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class FastClientImporter {
}
3.3 编写FastDFS属性
在application.yml中进行配置
fdfs:
so-timeout: 1501 # 超时时间
connect-timeout: 601 # 连接超时时间
thumb-image: # 缩略图
width: 60
height: 60
tracker-list: # tracker地址:你的虚拟机服务器地址+端口(默认是22122)
- 192.168.43.114:22122
3.4 配置host文件
将来通过域名:image.leyou.com这个域名访问fastDFS服务器上的图片资源。所以,需要代理到虚拟机地址: 配置hosts文件,使image.leyou.com可以访问fastDFS服务器
192.168.34.114 image.leyou.com
3.5 改造上传逻辑
/**
* @author FENCO
* @date 2020/2/4 8:35
* @company HOWSO
*/
@Service
public class UploadService {
//定义一个静态常量,列举用到的contentType
private static final List<String> CONTENT_TYPES = Arrays.asList("image/gif","image/jpeg");
private static final Logger LOGGER = LoggerFactory.getLogger(UploadService.class);
@Autowired
private FastFileStorageClient storageClient;
public String uploadImage(MultipartFile file) throws IOException {
String originalFilename = file.getOriginalFilename();
//校验文件类型
String contentType = file.getContentType();
if (!CONTENT_TYPES.contains((contentType))) {
//不包含,则参数不合法
// LOGGER.info("文件类型不合法:" + originalFilename);
//更优雅的表达:{}占位符
LOGGER.info("文件类型不合法:{}", originalFilename);
return null;
}
try {
//校验文件内容
BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
if (bufferedImage == null) {
LOGGER.info("文件内容不合法:{}", originalFilename);
}
//保存到文件的服务器
// file.transferTo(new File("G:\\HEIMA\\leyou\\images" + originalFilename));
String ext = StringUtils.substringAfterLast(originalFilename, ".");
StorePath storePath = this.storageClient.uploadFile(file.getInputStream(), file.getSize(), ext, null);
//返回url,进行回显
// return "http://image.leyou.com/" + originalFilename;
return "http://image.leyou.com/" + storePath.getFullPath();
} catch (IOException e) {
LOGGER.info("服务器内部错误:" + originalFilename);
e.printStackTrace();
}
return null;
}
}