由于资源问题本次案例是以单个docker为例子教导如何部署分部署fastDFS
创建两个tracker 以及两个storage(如果一个docker只部署一个fastDFS则忽略下面的tracker2和storage2所有配置)
docker 镜像 morunchang/fastdfs
创建本地目录
创建tracker1
mkdir -p /opt/docker/fastdfs/tracker1/data /opt/docker/fastdfs/tracker1/conf
创建tracker2
mkdir -p /opt/docker/fastdfs/tracker2/data /opt/docker/fastdfs/tracker2/conf
创建storage1
mkdir -p /opt/docker/fastdfs/storage1/storage_data /opt/docker/fastdfs/storage1/conf /opt/docker/fastdfs/storage1/data /opt/docker/fastdfs/storage1/logs/
创建storage2
mkdir -p /opt/docker/fastdfs/storage2/storage_data /opt/docker/fastdfs/storage2/conf /opt/docker/fastdfs/storage2/data /opt/docker/fastdfs/storage2/logs/
创建tracker
首先在docker创建tracker服务用于把配置拷贝到本地
docker run -d --name tracker --net=host morunchang/fastdfs sh tracker.sh
把tracker分别拷贝到tracker1与tracker2
docker cp tracker:/etc/fdfs/tracker.conf /opt/docker/fastdfs/tracker1/conf/tracker.conf
docker cp tracker:/etc/fdfs/tracker.conf /opt/docker/fastdfs/tracker2/conf/tracker.conf
关闭并且删除tracker(某些版本是 docker rm -rf tracker )
docker rm -f tracker
修改tracker1 以及 tracker2配置
vi /opt/docker/fastdfs/tracker1/conf/tracker.conf
vi /opt/docker/fastdfs/tracker2/conf/tracker.conf
修改以下值
tracker1 port=22122 http.server_port=8080
tracker2 port=22123 http.server_port=8081
创建tracker1
docker run -d --name tracker1 --net=host --restart always \
-v /opt/docker/fastdfs/tracker1/data:/data/fast_data/data \
-v /opt/docker/fastdfs/tracker1/conf/tracker.conf:/etc/fdfs/tracker.conf \
morunchang/fastdfs sh tracker.sh
创建tracker2
docker run -d --name tracker2 --net=host --restart always \
-v /opt/docker/fastdfs/tracker2/data:/data/fast_data/data \
-v /opt/docker/fastdfs/tracker2/conf/tracker.conf:/etc/fdfs/tracker.conf \
morunchang/fastdfs sh tracker.sh
创建storage
搭建一个storage,弄出一份配置文件,修改成我们需要的 (下面ip是本机ip)
docker run -d --name storage --net=host \
-e "TRACKER_IP=10.127.32.20:22122" \
-e "GROUP_NAME=group1" -e "STORAGE_PORT=23001" \
morunchang/fastdfs sh storage.sh
配置分别拷贝storage1 以及 storage2
storage1
docker cp storage:/storage.sh /opt/docker/fastdfs/storage1/conf/
docker cp storage:/etc/fdfs/mod_fastdfs.conf /opt/docker/fastdfs/storage1/conf/
docker cp storage:/etc/fdfs/storage.conf /opt/docker/fastdfs/storage1/conf/
docker cp storage:/data/fastdfs/conf/client.conf /opt/docker/fastdfs/storage1/conf/
docker cp storage:/data/fast_data/logs/storaged.log /opt/docker/fastdfs/storage1/logs/
配置修改如下
/opt/docker/fastdfs/storage1/conf/storage.conf:
tracker_server=10.127.32.20:22122
tracker_server=10.127.32.20:22123
/opt/docker/fastdfs/storage1/conf/mod_fastdfs.conf
tracker_server=10.127.32.20:22122
tracker_server=10.127.32.20:22123
/opt/docker/fastdfs/storage1/conf/storage.sh 内容改成如下
#!/bin/sh
/data/fastdfs/storage/fdfs_storaged /etc/fdfs/storage.conf
tail -f /data/fast_data/logs/storaged.log
storage2
docker cp storage:/storage.sh /opt/docker/fastdfs/storage2/conf/
docker cp storage:/etc/fdfs/mod_fastdfs.conf /opt/docker/fastdfs/storage2/conf/
docker cp storage:/etc/fdfs/storage.conf /opt/docker/fastdfs/storage2/conf/
docker cp storage:/data/fastdfs/conf/client.conf /opt/docker/fastdfs/storage2/conf/
docker cp storage:/data/fast_data/logs/storaged.log /opt/docker/fastdfs/storage2/logs/
配置修改如下
/opt/docker/fastdfs/storage2/conf/storage.conf:
group_name=group2
port=23001
tracker_server=10.127.32.20.80:22122
tracker_server=10.127.32.20:22123
/opt/docker/fastdfs/storage2/conf/mod_fastdfs.conf
group_name=group2 (有多个值)
storage_server_port=23001
tracker_server=10.127.32.20:22122
tracker_server=10.127.32.20:22123
/opt/docker/fastdfs/storage2/conf/storage.sh 内容改成如下
#!/bin/sh
/data/fastdfs/storage/fdfs_storaged /etc/fdfs/storage.conf
tail -f /data/fast_data/logs/storaged.log
关闭并且删除storage(某些版本是 docker rm -rf tracker )
docker rm -f storage
创建storage1
docker run -d --name storage1 --net=host --restart always \
-v /etc/localtime:/etc/localtime \
-v /opt/docker/fastdfs/storage1/data:/data/fast_data/ \
-v /opt/docker/fastdfs/storage1/conf/storage.sh:/storage.sh \
-v /opt/docker/fastdfs/storage1/conf/storage.conf:/etc/fdfs/storage.conf \
-v /opt/docker/fastdfs/storage1/conf/mod_fastdfs.conf:/etc/fdfs/mod_fastdfs.conf \
-v /opt/docker/fastdfs/storage1/conf/client.conf:/data/fastdfs/conf/client.conf \
-v /opt/docker/fastdfs/storage1/logs/storaged.log:/data/fast_data/logs/storaged.log \
morunchang/fastdfs sh storage.sh
创建storage2
docker run -d --name storage2 --net=host --restart always \
-v /etc/localtime:/etc/localtime \
-v /opt/docker/fastdfs/storage2/conf/data:/data/fast_data/ \
-v /opt/docker/fastdfs/storage2/conf/storage.sh:/storage.sh \
-v /opt/docker/fastdfs/storage2/conf/storage.conf:/etc/fdfs/storage.conf \
-v /opt/docker/fastdfs/storage2/conf/mod_fastdfs.conf:/etc/fdfs/mod_fastdfs.conf \
-v /opt/docker/fastdfs/storage2/conf/client.conf:/data/fastdfs/conf/client.conf \
-v /opt/docker/fastdfs/storage2/logs/storaged.log:/data/fast_data/logs/storaged.log \
morunchang/fastdfs sh storage.sh
查看fastdfs 监控状态
docker exec -it storage1 fdfs_monitor /etc/fdfs/storage.conf
参数说明:
参数说明:
server_count:2 --表示2个Tracker Server
tracker server is 198.168.1.121:22122 --表示Leader Tracker
group count: 1 --表示有1个group
group name = group1 --组名称是group1
storage server count = 2 --组内有2个storage
active server count = 2 --活动的storage有2个
storage server port = 23002 --storage的端口
storage HTTP port = 9101 --storage的文件访问端口
store path count = 1 --storage只挂了一个存储目录
total_upload_count = 11 --总共上传了多少个文件
total_upload_bytes = 691405 --总共上传了多少字节
success_upload_bytes = 691405 --成功上传了多少字节
total_download_count = 2 --总共下载了多少文件(使用java客户端)
防火墙
如果外部ping不通
firewall-cmd --zone=public --add-port=22122/tcp --permanent
firewall-cmd --zone=public --add-port=22123/tcp --permanent
firewall-cmd --zone=public --add-port=23000/tcp --permanent
firewall-cmd --zone=public --add-port=23001/tcp --permanent
重启防火墙
service firewalld restart
代码示例
pom
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.27.2</version>
</dependency>
application.yml
fdfs:
so-timeout: 1501
connect-timeout: 601
tracker-list: # tracker地址
- 10.127.32.20:22122
- 10.127.32.20:22123
springboot启动类需要加上这两个注释
@Import(FdfsClientConfig.class)
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
Controller
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadCallback;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
* @author leekun
* @description
* @time 2020/9/10 上午10:03
*/
@RequestMapping("/file")
@RestController
public class UploadController {
@Autowired
private FastFileStorageClient storageClient;
/**
* 文件名称
*/
private static final String META_DATA_NAME_FILE_NAME = "FILE_NAME";
/**
* 上传
*
* @param file 文件
* @return 文件路径
* @throws IOException 异常
*/
@PostMapping("/upload")
public String upload(MultipartFile file) throws IOException {
Map<String, String> result = uploadFile(file);
return result.get("uri");
}
/**
* 上传并返回文件路径和文件名
*
* @param file 文件
* @return 文件信息
* @throws IOException 异常
*/
private Map<String, String> uploadFile(MultipartFile file) throws IOException {
String fileName = file.getOriginalFilename();
String filePrefix = FilenameUtils.getExtension(fileName);
StorePath storePath;
storePath = this.storageClient.uploadFile(file.getInputStream(), file.getSize(), filePrefix, null);
Map<String, String> result = new HashMap<>();
result.put("uri", storePath.getFullPath());
result.put("name", fileName);
return result;
}
public InputStream download(String groupName, String path ) {
InputStream ins = storageClient.downloadFile(groupName, path, new DownloadCallback<InputStream>(){
@Override
public InputStream recv(InputStream ins) throws IOException {
// 将此ins返回给上面的ins
return ins;
}}) ;
return ins ;
}
@GetMapping(value = "/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public void download(@RequestParam String filePath, HttpServletRequest request, HttpServletResponse response) throws IOException {
String[] paths = filePath.split("/");
String groupName = null ;
for (String item : paths) {
if (item.indexOf("group") != -1) {
groupName = item;
break ;
}
}
String path = filePath.substring(filePath.indexOf(groupName) + groupName.length() + 1, filePath.length());
InputStream input = download(groupName, path);
//根据文件名获取 MIME 类型
String fileName = paths[paths.length-1] ;
System.out.println("fileName :" + fileName); // wKgIZVzZEF2ATP08ABC9j8AnNSs744.jpg
String contentType = request.getServletContext().getMimeType(fileName);
String contentDisposition = "attachment;filename=" + fileName;
// 设置头
response.setHeader("Content-Type",contentType);
response.setHeader("Content-Disposition",contentDisposition);
// 获取绑定了客户端的流
ServletOutputStream outputStream = response.getOutputStream();
IOUtils.copy(input,outputStream);
input.close();
}
}