整理知識點時翻出來的,想想還是發個部落格好了,圖檔來源的部落格找不到了,隻能厚顔上個原創…
一、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稱為存儲伺服器。
組名:檔案上傳後所在的 storage 組名稱,在檔案上傳成功後有storage 伺服器傳回,需要用戶端自行儲存。
虛拟磁盤路徑:storage 配置的虛拟路徑,與磁盤選項store_path*對應。如果配置了store_path0 則是 M00,如果配置了 store_path1 則是 M01,以此類推。
資料兩級目錄:storage 伺服器在每個虛拟磁盤路徑下建立的兩級目錄,用于存儲資料檔案。
檔案名:與檔案上傳時不同。是由存儲伺服器根據特定資訊生成,檔案名包含:源存儲伺服器 IP 位址、檔案建立時間戳、檔案大小、随機數和檔案拓展名等資訊。
二、docker下搭建FastDFS
1:拉取鏡像
docker pull morunchang/fastdfs
2:運作tracker
docker run -d --name tracker --net=host morunchang/fastdfs sh tracker.sh
3:運作storage
docker run -d --name storage --net=host -e TRACKER_IP=<your tracker server address>:22122 -e GROUP_NAME=<group name> morunchang/fastdfs sh storage.sh
- 使用的網絡模式是–net=host, 替換為你伺服器的Ip即可
- 是組名,即storage的組 (例:group01)
- 如果想要增加新的storage伺服器,再次運作該指令,注意更換 新組名
4:修改nginx的配置
進入storage的容器内部,修改nginx.conf
docker exec -it storage /bin/bash
進入後
vi /data/nginx/conf/nginx.conf
添加以下内容
location /group1/M00 {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_cache http-cache;
proxy_cache_valid 200 304 12h;
proxy_cache_key $uri$is_args$args;
proxy_pass http://fdfs_group1;
expires 30d;
}
5:修改檔案存儲配置storage.conf
修改檔案存儲路徑
進入storage的容器内部,修改storage.conf //檔案存儲伺服器配置檔案
docker exec -it storage /bin/bash
進入後
vi storage.conf
base_path=/data/fast_data
store_path0=/data/fast_data
tracker_server=伺服器ip位址:22122
6:退出并重新開機容器
exit
docker restart storage
3、檔案存儲微服務
springboot+springclooud
1:依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>net.oschina.zcx7878</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27.0.0</version>
</dependency>
</dependencies>
2:配置檔案
在resources檔案夾下建立fasfDFS的配置檔案fdfs_client.conf
connect_timeout = 60
network_timeout = 60
charset = UTF-8
http.tracker_http_port = 8080
tracker_server = 伺服器ip:22122
- connect_timeout:連接配接逾時時間,機關為秒。
- network_timeout:通信逾時時間,機關為秒。發送或接收資料時。假設在逾時時間後還不能發送或接收資料,則本次網絡通信失敗
- charset: 字元集
- http.tracker_http_port :.tracker的http端口
- tracker_server: tracker伺服器IP和端口設定
在resources檔案夾下建立application.yml
spring:
servlet:
multipart:
max-file-size: 10MB #單個檔案大小
max-request-size: 10MB #設定總上傳檔案大小
application:
name: file #微服務的應用名稱
server:
port: 9007
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:6868/eureka
instance:
prefer-ip-address: true
feign:
hystrix:
enabled: true
3:檔案資訊封裝
檔案上傳一般都有檔案的名字、檔案的内容、檔案的擴充名、檔案的md5值、檔案的作者等相關屬性,我們可以建立一個對象封裝這些屬性
public class FastDFSFile {
//檔案名字
private String name;
//檔案内容
private byte[] content;
//檔案擴充名
private String ext;
//檔案MD5摘要值
private String md5;
//檔案建立作者
private String author;
public FastDFSFile(String name, byte[] content, String ext, String height,
String width, String author) {
super();
this.name = name;
this.content = content;
this.ext = ext;
this.author = author;
}
public FastDFSFile(String name, byte[] content, String ext) {
super();
this.name = name;
this.content = content;
this.ext = ext;
}
// getter and setter ...
}
4:檔案操作
工具類,實作FastDFS資訊擷取以及檔案的相關操作
package com.laoshentou.file.utils;
import com.laoshentou.file.pojo.FastDFSFile;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
public class FastDFSClient {
private static Logger logger = LoggerFactory.getLogger(FastDFSClient.class);
private static TrackerServer trackerServer = null;
private static TrackerClient trackerClient = null;
private static StorageServer storageServer = null;
private static StorageClient1 storageClient1 = null;
/**
* 靜态代碼塊
* 為了上傳檔案,初始化加載檔案的上傳配置檔案(檔案中包含:上傳檔案的位址/連接配接時間/讀取時間/編碼集等
*/
static {
try {
//擷取fdfs_client.conf的絕對路徑
String absolutePath = new ClassPathResource("fdfs_client.conf").getFile().getAbsolutePath();
ClientGlobal.init(absolutePath);
trackerClient = new TrackerClient();
trackerServer = trackerClient.getConnection();
storageClient1 = new StorageClient1(trackerServer, storageServer);
} catch (Exception e) {
e.printStackTrace();
logger.error("ClientGlobal is fail:{}", e.getMessage());
}
}
/**
* 上傳檔案
*
* @param file
* @return 檔案的路徑
*/
public static String uploadFile(FastDFSFile file) {
System.out.println("上傳檔案");
NameValuePair[] nameValuePairs = new NameValuePair[1];
nameValuePairs[0] = new NameValuePair(file.getAuthor());
try {
return storageClient1.upload_file1(file.getContent(), file.getExt(), nameValuePairs);
} catch (Exception e) {
e.printStackTrace();
logger.error("upload file is fail: {} ", e.getMessage());
}
return null;
}
/**
* 下載下傳檔案
*
* @param path
* @return 檔案對象
*/
public static InputStream downFile(String path) {
try {
byte[] bytes = storageClient1.download_file1(path);
return new ByteArrayInputStream(bytes);
} catch (Exception e) {
e.getStackTrace();
logger.error("download file is fail : {}", e.getMessage());
}
return null;
}
/**
* 删除檔案
*
* @param path
*/
public static void deleteFile(String path) {
try {
storageClient1.delete_file1(path);
} catch (Exception e) {
e.printStackTrace();
logger.error("delete file is fail : {}", e.getMessage());
}
}
/***
* 擷取Tracker服務位址
* @return
* @throws IOException
*/
public static String getTrackerUrl() throws IOException {
return "http://" + trackerServer.getInetSocketAddress().getHostString() + ":" + ClientGlobal.getG_tracker_http_port() + "/";
}
}
檔案上傳控制器
package com.laoshentou.file.controller;
import com.laoshentou.Result;
import com.laoshentou.StatusCode;
import com.laoshentou.file.pojo.FastDFSFile;
import com.laoshentou.file.utils.FastDFSClient;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@RestController
@RequestMapping("/file")
public class FastDFSFileController {
private Logger logger = LoggerFactory.getLogger(FastDFSFileController.class);
/**
* 上傳檔案
*
* @param file
* @return 傳回對象
*/
@PostMapping("/uploadFile")
public Result uploadFile(MultipartFile file) {
//建立檔案對象
try {
FastDFSFile fastDFSFile = new
FastDFSFile(file.getOriginalFilename(), file.getBytes(), FilenameUtils.getExtension(file.getOriginalFilename()));
//上傳檔案
String path = FastDFSClient.uploadFile(fastDFSFile);
//擷取檔案的通路路徑
return new Result(true, StatusCode.OK, "上傳成功", FastDFSClient.getTrackerUrl() + path);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
5:Postman測試檔案上傳
選擇post請求
填寫headers
Key:Content-Type
Value:multipart/form-data
填寫body
選擇form-data,然後選擇檔案file
linux中檔案存儲路徑
docker exec -it storage /bin/bash
cd /data/fast_data/data/00/00/
ll
浏覽器中檢視上傳的圖檔
http://122.51.207.162:8080/group1/M00/00/00/rBEACF3so9SAK91PAAmPA24UZhs566.jpg