【工具类】分布式文件存储-FastDFS
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稱為存儲服務器。
上傳流程
客戶端上傳文件后存儲服務器將文件 ID 返回給客戶端,此文件 ID 用于以后訪問該文件的索引信息。文件索引信息包括:組名,虛擬磁盤路徑,數據兩級目錄,文件名。
組名:文件上傳后所在的 storage 組名稱,在文件上傳成功后有storage 服務器返回,需要客戶端自行保存。
虛擬磁盤路徑:storage 配置的虛擬路徑,與磁盤選項store_path*對應。如果配置了 store_path0 則是 M00,如果配置了 store_path1 則是 M01,以此類推。
數據兩級目錄:storage 服務器在每個虛擬磁盤路徑下創建的兩級目錄,用于存儲數據文件。
文件名:與文件上傳時不同。是由存儲服務器根據特定信息生成,文件名包含:源存儲服務器 IP 地址、文件創建時間戳、文件大小、隨機數和文件拓展名等信息。
FastDFS搭建
使用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=<your tracker server address>:22122 ‐e GROUP_NAME=<group name> morunchang/fastdfs sh storage.sh
- 使用的網絡模式是–net=host, 替換為你機器的Ip即可
- 是組名,即storage的組
- 如果想要增加新的storage服務器,再次運行該命令,注意更換 新組名
修改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; }退出容器 exit
重啟storage容器
文件存儲微服務
修改pom.xml,引入依賴
<dependency> <groupId>net.oschina.zcx7878</groupId><artifactId>fastdfs‐client‐java</artifactId> <version>1.27.0.0</version> </dependency>在resources文件夾下創建fasfDFS的配置文件fdfs_client.conf
connect_timeout = 60 network_timeout = 60 charset = UTF‐8 http.tracker_http_port = 8080 tracker_server = 192.168.200.128: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是單個文件大小# max-request-size是設置總上傳的數據大小 max‐file‐size: 10MB max‐request‐size: 10MB server: port: 9008 eureka: client: service‐url: defaultZone: http://127.0.0.1:6868/eureka instance: prefer‐ip‐address: true feign: hystrix: enabled: true創建file包,創建啟動類FileApplication
@SpringBootApplication @EnableEurekaClient public class FileApplication { public static void main(String[] args) { SpringApplication.run(FileApplication.class); } }文件上傳
文件信息封裝:文件上傳一般都有文件的名字、文件的內容、文件的擴展名、文件的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 ...文件操作:創建工具類,在該類中實現FastDFS信息獲取以及文件的相關操作, 代碼如下:
import org.csource.common.NameValuePair; import org.csource.fastdfs.*; 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 org.slf4j.Logger logger = LoggerFactory.getLogger(FastDFSClient.class);/**** 初始化加載FastDFS的TrackerServer配置*/static {try {String filePath = new ClassPathResource("fdfs_client.conf").getFile().getAbsolutePath();ClientGlobal.init(filePath);} catch (Exception e) {logger.error("FastDFS Client Init Fail!",e);}}/**** 文件上傳* @param file* @return 1.文件的組名 2.文件的路徑信息*/public static String[] upload(FastDFSFile file) {//獲取文件的作者NameValuePair[] meta_list = new NameValuePair[1];meta_list[0] = new NameValuePair("author", file.getAuthor());//接收返回數據String[] uploadResults = null;StorageClient storageClient=null;try {//創建StorageClient客戶端對象storageClient = getTrackerClient();/**** 文件上傳* 1)文件字節數組* 2)文件擴展名* 3)文件作者*/uploadResults = storageClient.upload_file(file.getContent(), file.getExt(), null);} catch (Exception e) {logger.error("Exception when uploadind the file:" + file.getName(), e);}if (uploadResults == null && storageClient!=null) {logger.error("upload file fail, error code:" + storageClient.getErrorCode());}//獲取組名String groupName = uploadResults[0];//獲取文件存儲路徑String remoteFileName = uploadResults[1];return uploadResults;}/**** 獲取文件信息* @param groupName:組名* @param remoteFileName:文件存儲完整名* @return*/public static FileInfo getFile(String groupName, String remoteFileName) {try {StorageClient storageClient = getTrackerClient();return storageClient.get_file_info(groupName, remoteFileName);} catch (Exception e) {logger.error("Exception: Get File from Fast DFS failed", e);}return null;}/**** 文件下載* @param groupName* @param remoteFileName* @return*/public static InputStream downFile(String groupName, String remoteFileName) {try {//創建StorageClientStorageClient storageClient = getTrackerClient();//下載文件byte[] fileByte = storageClient.download_file(groupName, remoteFileName);InputStream ins = new ByteArrayInputStream(fileByte);return ins;} catch (Exception e) {logger.error("Exception: Get File from Fast DFS failed", e);}return null;}/**** 文件刪除* @param groupName* @param remoteFileName* @throws Exception*/public static void deleteFile(String groupName, String remoteFileName)throws Exception {//創建StorageClientStorageClient storageClient = getTrackerClient();//刪除文件int i = storageClient.delete_file(groupName, remoteFileName);}/**** 獲取Storage組* @param groupName* @return* @throws IOException*/public static StorageServer[] getStoreStorages(String groupName)throws IOException {//創建TrackerClientTrackerClient trackerClient = new TrackerClient();//獲取TrackerServerTrackerServer trackerServer = trackerClient.getConnection();//獲取Storage組return trackerClient.getStoreStorages(trackerServer, groupName);}/**** 獲取Storage信息,IP和端口* @param groupName* @param remoteFileName* @return* @throws IOException*/public static ServerInfo[] getFetchStorages(String groupName,String remoteFileName) throws IOException {TrackerClient trackerClient = new TrackerClient();TrackerServer trackerServer = trackerClient.getConnection();return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName);}/**** 獲取Tracker服務地址* @return* @throws IOException*/public static String getTrackerUrl() throws IOException {return "http://"+getTrackerServer().getInetSocketAddress().getHostString()+":"+ClientGlobal.getG_tracker_http_port()+"/";}/**** 獲取Storage客戶端* @return* @throws IOException*/private static StorageClient getTrackerClient() throws IOException {TrackerServer trackerServer = getTrackerServer();StorageClient storageClient = new StorageClient(trackerServer, null);return storageClient;}/**** 獲取Tracker* @return* @throws IOException*/private static TrackerServer getTrackerServer() throws IOException {TrackerClient trackerClient = new TrackerClient();TrackerServer trackerServer = trackerClient.getConnection();return trackerServer;} }文件上傳
創建一個FileController,在該控制器中實現文件上傳操作,代碼如下:
@RestController @RequestMapping("/file") public class FileController {@PostMapping("/upload")public Result uploadFile(MultipartFile file){try{//判斷文件是否存在if (file == null){throw new RuntimeException("文件不存在");}//獲取文件的完整名稱String originalFilename = file.getOriginalFilename();if (StringUtils.isEmpty(originalFilename)){throw new RuntimeException("文件不存在");}//獲取文件的擴展名稱 abc.jpg jpgString extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);//獲取文件內容byte[] content = file.getBytes();//創建文件上傳的封裝實體類FastDFSFile fastDFSFile = new FastDFSFile(originalFilename,content,extName);//基于工具類進行文件上傳,并接受返回參數 String[]String[] uploadResult = FastDFSClient.upload(fastDFSFile);//封裝返回結果String url = FastDFSClient.getTrackerUrl()+uploadResult[0]+"/"+uploadResult[1];return new Result(true,StatusCode.OK,"文件上傳成功",url);}catch (Exception e){e.printStackTrace();}return new Result(false, StatusCode.ERROR,"文件上傳失敗");} }總結
以上是生活随笔為你收集整理的【工具类】分布式文件存储-FastDFS的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【消息中间件】AMQPRabbitMQ工
- 下一篇: 【模板引擎】Springboot整合Th