分布式文件系統如何做?終于有篇文章分布式文件上傳講清楚了

      網友投稿 877 2025-04-04

      FastDFS概念

      FastDFS是開源的輕量級分布式文件系統,實現文件管理, 主要功能:

      文件存儲

      文件同步

      文件訪問(文件上傳,文件下載)

      解決了大容量存儲和負載均衡的問題,特別適合以文件為載體的在線服務:相冊網站,視頻網站

      FastDFS為互聯網量身定制,充分考慮了冗余備份,負載均衡,線性擴容等機制,并注重高可用,高性能等指標,使用FastDFS可以很方便地搭建一套高性能的文件服務器集群提供文件上傳,下載等服務

      FastDFS文件系統架構

      FastDFS服務端有兩個角色:

      -(tracker): 主要做調度工作,在訪問上起負載均衡作用

      -和存儲節點都可以由一臺服務器或多臺服務器構成,-和存儲節點中的服務器可以隨時增加或下線而不會影響下線服務.

      -中所有服務都是對等的,可以根據服務器的壓力情況隨時增加或減少

      存儲節點(storage): 存儲文件,完成文件管理的所有功能

      就是這樣的存儲

      同步存儲接口

      提供存儲接口

      FastDFS同時對文件metadata進行管理,文件metadata是文件屬性列表,可以包含多個鍵值對

      文件metadata: 文件的相關屬性,以鍵值對方式表示

      為了支持大容量,存儲節點采用分卷的組織方式

      存儲系統由一個卷或多個卷組成,卷與卷之間的文件是相互獨立的,所有卷的文件容量累加就是整個存儲系統的文件容量

      一個卷可以由一臺或多臺存儲服務器組成,一個卷下的存儲服務器中文件都是相同的,卷中的多臺服務器起到了冗余備份和負載均衡作用

      在卷中增加服務器時,同步已有的文件由系統自動完成,同步完成后,系統自動將新增服務器切換到線上提供服務

      當存儲空間不足或即將耗盡時,可以動態添加卷,只需要增加一臺或多臺服務器,配置一個新的卷,這樣擴大存儲系統的容量

      FastDFS 文件標識分為兩部分:

      卷名

      文件名

      高可用要有崩潰恢復的能力 服務集群要有同步的功能 否則就要有負載均衡

      上傳交互過程

      client詢問tracker上傳到的storage,不需要附加參數

      tracker返回一臺可用的storage

      client直接和storage通訊完成文件上傳

      client為使用FastDFS的調用方,client也是一臺服務器,對tracker和對storage的調用均為服務器間的調用

      下載交互過程

      client詢問tracker下載文件的storage,參數為文件標識(卷名和文件名)

      tracker返回一臺可用的storage

      client直接和storage通訊完成文件下載

      client為使用FastDFS的調用方,client也是一臺服務器,對tracker和對storage的調用均為服務器間的調用

      FastDFS結合Nginx

      使用FastDFS部署分布式文件系統時,通過FastDFS的客戶端API進行文件的上傳,下載,刪除等操作,同時通過FastDFS和HTTP服務器來提供HTTP服務.但是FastDFS的HTTP服務較為簡單,無法提供負載均衡等高性能的服務.需要使用FastDFS的Nginx模塊彌補這一缺陷

      FastDFS通過tracker服務器,將文件放在storage服務器存儲,但是同組之間的服務器需要復制文件,有延遲的問題,可以通過fastdfs-nginx-module可以重定向連接到源服務器取文件,避免客戶端由于復制延遲的問題,出現錯誤

      基于Docker安裝FastDFS

      環境準備:

      libfastcommon: FastDFS分離出的一些公用函數包

      FastDFS: FastDFS本體

      fastdfs-nginx-module: FastDFS和nginx的關聯模塊

      nginx: nginx1.15.4

      創建工作目錄:

      在Linux中創建

      /usr/local/docker/fastdfs/environment /usr/local/docker/fastdfs:用于存放docker-compose.yml配置文件及FastDFS數據卷 /usr/local/docker/fastdfs/environment:用于存放Dockerfile鏡像配置文件及FastDFS所需環境

      在 /usr/local/docker/fastdfs/environment目錄中創建Dockerfile

      # 更新數據源 WORKDIR /etc/apt RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse' > sources.list RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse' >> sources.list RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse' > sources.list RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse' > sources.list RUN apt-get update # 安裝依賴 RUN apt-get install make gcc libpcre3-dev zliblg-dev --assume-yes # 復制工具包 ADD fastdfs-5.11.tar.gz /usr/local/src ADD fastdfs-nginx-module_v1.16.tar.gz /usr/local/src ADD libfastcommon.tar.gz /usr/local/src ADD nginx-1.15.4.tar.gz /usr/local/src # 安裝libfastcommon WORKDIR /usr/local/src/libfastcommon RUN ./make.sh && ./make.sh install # 安裝 FastDFS WORKDIR /usr/local/src/fastdfs-5.11 RUN ./make.sh && ./make.sh install # 配置FastDFS tracker ADD tracker.conf /etc/fdfs RUN mkdir -p /fastdfs/tracker # 配置FastDFS storage ADD storage.conf /etc/fdfs RUN mkdir -p /fastdfs/storage # 配置FastDFS客戶端 ADD client.conf /etc/fdfs # 配置fastdfs-nginx-module ADD config /usr/local/src/fastdfs-nginx-modules/src # FastDFS與Nginx集成 WORKDIR /usr/local/src/nginx-1.13.6 RUN ./configure --add-module=/usr/local/src/fastdfs-nginx-module/src RUN make && make install ADD mod_fastdfs.conf /etc/fdfs WORKDIR /usr/local/src/fastdfs-5.11/conf RUN cp http.conf mime.types /etc/fdfs/ # 配置Nginx ADD nginx.conf /usr/local/nginx/conf COPY entrypoint.sh /usr/local/bin/ ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] WORKDIR / EXPOSE 8888 CMD ["/bin/bash"]

      在/usr/local/docker/fastdfs/environment創建entrypoint.sh,創建完成的后要執行 chmod +x entrypoint.sh命令文件才可以使用

      # !/bin/sh /etc/init.d/fdfs_trackerd start /etc/init.d/fdfs_storaged start /usr/local/nginx/sbin/nginx -g 'daemon off;'

      相關配置文件

      tracker.conf: FastDFS-配置,容器路徑為:/etc/fdfs,修改:

      base_path=/fastdfs/tracker

      storage.conf: FastDFS存儲節點配置,容器路徑為:/etc/fdfs,修改:

      base_path=/fastdfs/storage store_path0=/fastdfs/storage tracker_server=192.168.32.255:22122 http.server_port=8888

      client.conf: FastDFS客戶端配置,容器中路徑為:/etc/fdfs,修改:

      base_path=/fastdfs/tracker tracker_server=192.168.32.255:22122

      config: fastdfs-nginx-module配置文件,容器中路徑為:/usr/local/src/fastdfs-nginx-module/src,修改:

      # 修改前 CORE_INCS="$CORE_INCS /usr/local/include/fastdfs /usr/local/include/fastcommon/" CORE_LIBS="$CORE_LIBS -L/usr/local/lib -lfastcommon -lfdfsclient" # 修改后 CORE_INCS="$CORE_INCS /usr/include/fastdfs /usr/include/fastcommon/" CORE_LIBS="$CORE_LIBS -L/usr/lib -lfastcommon -lfdfsclient"

      mod_fastdfs.conf: fastdfs-nginx-module配置文件,容器中路徑:/usr/local/src/fastdfs-nginx-module/src,修改:

      connect_timeout=10 tracker_server=192.168.75.128:22122 url_have_group_name=true store_path0=/fastdfs/storage

      nginx.conf: Nginx配置文件,容器中的路徑為:/usr/local/src/nginx-1.15.4/conf,修改:

      user root; worker_processes 1; events { worker_connections 1024; } http{ include mime.types; defaulte_type application/octet-stream; sendfile on; keepalive_timeout 65; server{ listen 8888; server_name localhost; location ~/group([0-9])/M00{ ngx_fastddfs_module; } error_page 500 502 503 504 /50x.html location = /50x.html { root html; } } }

      啟動容器

      docker-compose.yml: 在/usr/local/docker/fastdfs文件夾中創建docker-compose.yml

      version: '3.1' services: fastdfs: build: environment restart: always container_name: fastdfs volumes: - ./storage:/fastdfs/storage network_mode: host # 網絡模式:主機模式--將所有端口映射到主機,Docker容器與宿主機共享端口,即端口一致

      執行命令,使文件編譯生效

      docker-compose up -d

      測試上傳

      交互式進入容器:

      docker exec -it fastdfs /bin/bash

      測試文件上傳: 在/usr/bin目錄中執行(第1個是二進制可執行文件客戶端,第2個是客戶端的客戶端配置文件,第3個是需要上傳的文件)

      /usr/bin/fdfs_upload_file /etc/fdfs/client.conf /usr/local/src/fastdfs-5.11/INSTALL

      服務器反饋上傳地址: 文件的上傳路徑(非地址),通過在瀏覽器輸入Ngnix的訪問地址+文件上傳路徑即可訪問服務器上的文件

      group1/M00/00/00/wKliyyfhHHkjsio986777

      測試Nginx訪問: 通過在瀏覽器輸入Ngnix的訪問地址+文件上傳路徑即可訪問服務器上的文件

      http://192.168.32.255:8888/group1/M00/00/00/wKliyyfhHHkjsio986777

      配置 FastDFS Java客戶端

      創建項目: 創建項目名為myshop-service-upload的服務提供者項目

      安裝FastDFS Java客戶端

      從github上git clone FastDFS項目代碼:

      git clone https://github.com/happyfish100/fastdfs-client-java.git

      配置到本地倉庫: 在項目目錄的target包下有項目的jar文件

      mvn clean install

      將項目jar文件上傳到Nexus中

      在項目中添加依賴:

      org.csource fastdfs-client-java 1.27-SNAPSHOT

      創建FastDFS工具類

      定義文件存儲服務接口:

      package com.oxford.myshop.service.upload.fastdfs; public interface StorageService{ /** *上傳文件 * *@param data 文件的二進制符 *@param extName 擴展名 *@return 上傳成功后返回生成文件的id,失敗則返回null */ public String upload(byte[] data,String extName); /** *刪除文件 * *@param fileId 被刪除的文件id *@return 刪除成功后返回0,失敗后返回錯誤代碼 */ public int delete(String fileId); }

      實現文件存儲服務接口:

      分布式文件系統如何做?終于有篇文章分布式文件上傳講清楚了

      public class FastDFSStorageService implements StorageService,InitializingBean{ private static final Logger logger=LoggerFactory.getLogger(FastDFSStorageService.class); private TrackerClient trackerClient; @Value("${storage.fastdfs.tracker_server}") @Override public String upload(byte[] data,String extName){ TrackerServer trackerServer=null; StorageServer storageServer=null; StorageClient storageClient=null; try{ NameValuePair[] meta_list=null; // new NameValuePair[0] trackerServer=trackerClient.getConnection(); if(trackerServer==null){ logger.error("getConnection return null"); } storageServer=trackerClient.getStoreStorage(trackerServer); storageClient1=new StorageClient1(trackerServer,storageServer); String fileId=storageClient1.upload_file1(data,extName,meta_list); logger.debug("uploaded file <{}>",fileId); return fileId; }catch(Exception ex){ logger.error("Uploaded fail",ex); return null; }finally{ if(storageServer!=null){ try{ storageServer.close(); }catch(IOException e){ e.printStackTrace(); } } if(trackeServer!=null){ try{ trackeServer.close(); }catch(IOException e){ e.printStackTrace(); } } storageClient1=null; } } @Override public int delete(String fileId){ TrackerServer trackerServer=null; StorageServer storageServer=null; StorageClient storageClient=null; int index=fileId.indexOf('/'); String groupName=fileId.substring(0,index); try{ trackerServer=trackerClient.getConnection(); if(trackerServer==null){ logger.error("getConnection return null"); } storageServer=trackerClient.getStoreStorage(trackerServer,groupName); storageClient1=new StorageClient1(trackerServer,storageServer); int result=storageClient1.delete_file1(fileId); return result; }catch(Exception ex){ logger.error("Delete fail",ex); return 1; }finally{ ifreturn fileId; }catch(Exception ex){ logger.error("Uploaded fail",ex); return null; }finally{ if(storageServer!=null){ try{ storageServer.close(); }catch(IOException e){ e.printStackTrace(); } } if(trackeServer!=null){ try{ trackeServer.close(); }catch(IOException e){ e.printStackTrace(); } } storageClient1=null; } } @Override public void afterPropertiesSet() throws Exxception{ File confFile=File.createTempFile("fastdfs",".conf"); PrintWriter confWriter=new PrintWriter(new FileWriter(confFile)); confWriter.println("tracker_server="+trackerServer); confWriter.close(); ClientGlobal.init(confFile.getAbsolutePath()); confFile.delete(); TrackerGroup trackerGroup=ClientGlobal.g_tracker_group; trackerClient=new TrackerClient(trackerGroup) logger.info("Init FastDFS with tracker_server : {}",trackerServer); } }

      文件存儲服務工廠

      public class StorageFactory implements FactoryBean{ @Autowired private AutowireCapableBeanFactory acbf; /** * 存儲服務的類型,僅支持FastDFS */ @Value("${storage.type}") private String type; private Map> classMap; public StorageFactory(){ classMap=new HashMap<>(); classMap.put("fastdfs",FastDFSStorageService.class); } @Override public StorageService getObject() throws Exception{ Class clazz=classMap.get(type); if(class==null){ throw new RuntimeException("Unsupported storage type ["+type+"],valid are"+ classMap.keySet()); } StorageService bean=clazz.newInstance(); acbf.autowireBean(bean); acbf.initializeBean(bean,bean.getClass().getSimpleName()); return bean; } @Override public Class getObjectType(){ return StorageService.class; } @Override public boolean isSingleton(){ return true; } }

      配置文件存儲服務工廠類

      /** * Java配置方式定義StorageFactory的bean,使其可以被依賴注入 */ @Configuration public classs FastDFSConfiguration{ @Bean public StorageFactory storageFactory(){ return new StorageFactory(); } }

      創建FastDFS控制器

      增加云配置: application.yml

      # SpringBoot Application spring: application: name: myshop-service-upload # FastDFS Configuration fastdfs.base.url: htttp//192.168.32.255:8888/ storage: type: fastdfs fastdfs: tracker_server: 192.168.32.255:22122

      控制器代碼

      @CrossOrigin(origins="*",maxAge=3600) @RestController public class UploadController{ @Value("${fastdfs.base.url}") private String FASTDFS_BASE_URL; @Autowired private StorageService storageService; @RequestMapping(value="upload",method=RequestMethod.POST) public Map upload(MultipartFile dropFile,MultipartFile[] editorFiles){ Map result=new HashMap<>(); //DropZone上傳 if(dropFile!=null){ result.put("fileName",writeFile(dropFile)); } //wangEditor上傳 if(editorFiles != null && editorFiles.length > 0){ List fileNames=new ArrayList<>(); for(MultipartFile editorFile:editorFiles){ fileNames.add(writeFile(editorFile)); } result.put("error",0); result.put("data",fileNames); } return result; } /** *將圖片寫入指定目錄 */ private String writeFile(MultipartFile multipartFile){ // 獲取文件后綴 String oName=multipartFile.getOriginalFilename(); String exName=oName.substring(oName.lastIndexOf(".")+1); // 文件存放路徑 String url=null; try{ String uploadUrl=storageService.upload(multipartFile.getBytes(),exName); url=FASTDFS_BASE_URL+uploadUrl; }catch(IOException e){ e.printStackTrace(); } // 返回文件完整路徑 return url; } }

      創建SpringBoot Application,運行執行分布式文件上傳項目

      Nginx 分布式

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:如何設置wps表格線不會打印出來(wps表格打印不出來網格線)
      下一篇:如何總是顯示表格的第一行
      相關文章
      亚洲第一综合天堂另类专| 亚洲精品国产高清不卡在线| 亚洲日产乱码一二三区别| 亚洲成人免费网址| 亚洲精品国产肉丝袜久久| 亚洲av丰满熟妇在线播放| 亚洲成AV人片一区二区密柚| 亚洲中文字幕无码一区| 亚洲欧洲国产精品香蕉网| 亚洲精品成人网站在线观看| 亚洲av之男人的天堂网站| 亚洲A∨无码一区二区三区| 久久精品国产亚洲AV麻豆~| 亚洲激情中文字幕| 亚洲乱亚洲乱妇无码麻豆| 亚洲午夜福利AV一区二区无码| 亚洲色精品aⅴ一区区三区| 亚洲情综合五月天| 亚洲成年轻人电影网站www| 亚洲天堂中文资源| 91亚洲国产成人久久精品| 亚洲深深色噜噜狠狠网站| 亚洲精品无码专区在线播放| 精品久久久久久亚洲中文字幕| 亚洲?V乱码久久精品蜜桃 | 久久综合九九亚洲一区| 无码乱人伦一区二区亚洲| 亚洲精品韩国美女在线| 色婷五月综激情亚洲综合| 亚洲乱理伦片在线观看中字| 色婷婷亚洲一区二区三区| 久久久久亚洲精品天堂久久久久久| 亚洲欧洲日产国码av系列天堂 | 日韩精品亚洲专区在线影视| 亚洲精品成人在线| 亚洲精品无码专区久久久 | 亚洲国产精品第一区二区| 亚洲精品自拍视频| 亚洲一区二区三区免费视频| 在线精品亚洲一区二区| 无码天堂亚洲国产AV|