Author:Gorit
Date:2021年1月16日
Refer:B站、腾讯课堂
2021年发表博文: 5/50
单系统、单应用
缺点:
优点:
FastDFS 是一个开源轻量级分布式文件系统,为互联网应用量身定做。采用 c 语言开发。是一个软件/软件服务器,它对文件进行管理,但是所管理的文件通常不在一个节点上。功能如下:
解决了大容量存储 和 负载均衡的问题,特别适合中小文件(4KB < file_size < 500MB)。如相册网站,视频网站等
FastDFS 充分考虑了冗余备份,线程扩容机制,并注重高可用。高性能等指标。使用 FastDFS 很容易搭建一套高性能的而文件服务器集群提供文件上传。下载服务
FastDFS 文件系统由两大部分构成,一个是**客户端,**一个是服务端。
客户端是指我们的应用程序,比如我们的 Java 程序 去连接 FastDFS、操作 FastDFS。Java 程序就是一个客户端,FastDFS 提供专有 API 访问,目前提供了 C、Java 和 PHP 的几种变成语言 API。用来访问 FastDFS 文件系统
FastDFS 服务端有两个角色,代表两个服务:
为了支持大容量,存储节点(服务器)采用了分卷(或分组)。存储系统由一个或多个卷组成,卷与卷之间的文件是相互独立的。所有卷的文件容量累加就是整个存储系统中的文件容量。一个卷可以由一个或多个存储服务器组成。一个卷下的存储服务器中的文件都是相同的。卷中多台存储服务器起到了冗余备份 和 负载均衡
FastDFS 文件标识分为两个部分:
PS:上述第二条规则有个例外,就是新增加一台 storage server 时,由已有的一台 storage server 将已有的所有数据(包括源头数据 和 备份数据)同步给新增服务器
安装 fastDFS 需要分别安装 fastdfs-nginx-module,fastdfs,nginx,libfastcommon
先安装依赖环境,再安装 FastDFS
如果学了 Docker ,我们使用 Docker 来安装就会简单很多
参考文章:
下载
docker pull delron/fastdfs
查看镜像
docker images
构建 tracker 服务(跟踪服务器,实现任务调度的作用)
docker run -d --network=host --name tracker -v /root/tracker:/var/root delron/fastdfs tracker
构建 storage 容器(存储服务器,提供容量和备份服务),,这里storage容器需要依赖tracker服务,传入你的tracker服务的ip地址,端口默认是22122,ip地址也就是你宿主机的ip
docker run -d --network=host --name storage -e TRACKER_SERVER=139.196.43.98:22122 -v /root/storage:/var/root -e GROUP_NAME=group1 delron/fastdfs storage
docker ps
[root@VM-16-5-centos storage]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e36862cc1e63 delron/fastdfs "/usr/bin/start1.sh …" 9 seconds ago Up 8 seconds storage
d3dfdfea80b7 delron/fastdfs "/usr/bin/start1.sh …" 2 minutes ago Up 2 minutes tracker
进入正在工作中的 storage 容器
docker exec -it storage /bin/bash
PS:保证云服务器的 8888 端口(Nginx 对外提供的端口),22122 端口,23000 端口都能相互访问
pom.xml 编写,主要依赖配置如下
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.github.tobatogroupId>
<artifactId>fastdfs-clientartifactId>
<version>1.26.5version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
<exclusions>
<exclusion>
<groupId>org.junit.vintagegroupId>
<artifactId>junit-vintage-engineartifactId>
exclusion>
exclusions>
dependency>
dependencies>
application.yml 配置
spring:
application:
name: fastdfs-demo
servlet:
multipart:
max-file-size: 100MB # 最大支持文件大小
max-request-size: 100MB # 最大请求大小
enabled: true
fdfs:
so-timeout: 1500 # socket 连接时长
connect-timeout: 600 # 连接 tracker 服务器超时时长
# 这两个是你服务器的 IP 地址,注意 23000 端口也要打开,阿里云服务器记得配置安全组。tracker 要和 stroage 服务进行交流
tracker-list: 服务器公网IP:22122
web-server-url: 服务器公网IP:8888
pool:
jmx-enabled: false
# 生成缩略图
thumb-image:
height: 500
width: 500
server:
port: 80
Java 配置类,配置 FastDFS Client
package com.example.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.jmx.support.RegistrationPolicy;
/**
* @Classname FastdfsConfiguration
* @Description TODO
* @Date 2021/1/23 22:27
* @Created by CodingGorit
* @Version 1.0
*/
@Configuration // 导入 FastDFS-Client 组件
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING) // 解决 Jmx重复注册bean的问题
public class FastdfsConfiguration {
}
配置静态文件访问
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Classname WebMvcConfig
* @Description TODO
* @Date 2021/1/23 22:55
* @Created by CodingGorit
* @Version 1.0
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");
}
}
前端页面编写 upload.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传测试title>
head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="提交">
form>
<form action="/delete" method="get">
<input type="text" name="file">
<input type="submit" value="提交">
form>
body>
html>
fastDFS 工具类
package com.example.util;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
/**
* @Classname FastdfsUtil
* @Description TODO
* @Date 2021/1/23 22:43
* @Created by CodingGorit
* @Version 1.0
*/
@Component
public class FastdfsUtil {
private static final Logger log = LoggerFactory.getLogger(FastdfsUtil.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 String deleteFile(String fileUrl) {
if (StringUtils.isEmpty(fileUrl)) {
log.info("fileUrl == >>文件路径为空...");
return "文件路径不能为空";
}
try {
StorePath storePath = StorePath.parseFromUrl(fileUrl);
storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
} catch (Exception e) {
log.error(e.getMessage());
}
return "删除成功";
}
/**
* 下载文件
*/
}
控制器类
package com.example.controller;
import com.example.util.FastdfsUtil;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
/**
* @Classname FileController
* @Description TODO
* @Date 2021/1/23 22:45
* @Created by CodingGorit
* @Version 1.0
*/
@RestController
public class FileController {
@Resource
private FastdfsUtil fastdfsUtil;
/**
* 文件上传
*/
@RequestMapping(value = "/upload",headers="content-type=multipart/form-data", method = RequestMethod.POST)
public Object uploadFile (@RequestParam("file") MultipartFile file){
String result ;
try{
String path = fastdfsUtil.upload(file) ;
if (!StringUtils.isEmpty(path)){
result = path ;
} else {
result = "上传失败" ;
}
} catch (Exception e){
e.printStackTrace() ;
result = "服务异常" ;
}
return result;
}
/**
* 文件删除
*/
@RequestMapping(value = "/delete", method = RequestMethod.GET)
public Object deleteByPath (@RequestParam("file") String file){
if (StringUtils.isEmpty(file)) {
return "路径不能为空";
}
String res = fastdfsUtil.deleteFile(file);
// group1/M00/00/00/rBEQBWAMJLOAHtzOAC-ojGdpZlE261.png 必须得删除这个路径
return res;
}
}
http://localhost/upload.html