一:FastDFS簡介
1:FastDFS簡介
FastDFS是一個開源的輕量級分布式文件系統,功能包括:文件存儲、文件同步、文件訪問(文件上傳、文件下載)等,解決了大容量存儲和負載均衡的問題。特別適合中小文件(建議范圍:4KB < file_size <500MB),對以文件為載體的在線服務,如相冊網站、視頻網站等。

(1):單機時代 初創時期由於時間緊迫,在各種資源有限的情況下,通常就直接在項目目錄下建立靜態文件夾,用於用戶存放項目中的文件資源。 如果按不同類型再細分,可以在項目目錄下再建立不同的子目錄來區分。如resources\static\file、resources\static\img等 # 優點:這樣做比較便利,項目直接引用就行,實現起來也簡單,無需任何復雜技術,保存數據庫記錄和訪問起來也很方便。 # 缺點:如果只是后台系統的使用一般也不會有什么問題,但是作為一個前端網站使用的話就會存在弊端。一方面,文件和代碼耦合 在一起,文件越多存放越混亂;另一方面,如果流量比較大,靜態文件訪問會占據一定的資源,影響正常業務進行,不利於網站 快速發展。 (2):獨立文件服務器 隨着公司業務不斷發展,將代碼和文件放在同一服務器的弊端就會越來越明顯。為了解決上面的問題引入獨立圖片服務器,工作 流程如下:項目上傳文件時,首先通過ftp或者ssh將文件上傳到圖片服務器的某個目錄下,再通過ngnix或者apache來訪問此 目錄下的文件,返回一個獨立域名的圖片URL地址,前端使用文件時就通過這個URL地址讀取。 # 優點:圖片訪問是很消耗服務器資源的(因為會涉及到操作系統的上下文切換和磁盤I/O操作),分離出來后,Web/App服務器 可以更專注發揮動態處理的能力;獨立存儲,更方便做擴容、容災和數據遷移;方便做圖片訪問請求的負載均衡,方便應用各 種緩存策略(HTTP Header、Proxy Cache等),也更加方便遷移到CDN。 # 缺點:單機存在性能瓶頸,容災、垂直擴展性稍差 (3):分布式文件系統 通過獨立文件服務器可以解決一些問題,如果某天存儲文件的那台服務突然down了怎么辦?可能你會說,定時將文件系統備份, 這台down機的時候,迅速切換到另一台就OK了,但是這樣處理需要人工來干預。另外,當存儲的文件超過100T的時候怎么辦? 單台服務器的性能問題?這個時候我們就應該考慮分布式文件系統了。業務繼續發展,單台服務器存儲和響應也很快到達了瓶頸, 新的業務需要文件訪問具有高響應性、高可用性來支持系統。分布式文件系統,一般分為三塊內容來配合,服務的存儲、訪問的 仲裁系統,文件存儲系統,文件的容災系統來構成,仲裁系統相當於文件服務器的大腦,根據一定的算法來決定文件存儲的位置, 文件存儲系統負責保存文件,容災系統負責文件系統和自己的相互備份。 # 優點:擴展能力: 毫無疑問,擴展能力是一個分布式文件系統最重要的特點;高可用性: 在分布式文件系統中,高可用性包含兩 層,一是整個文件系統的可用性,二是數據的完整和一致性;彈性存儲: 可以根據業務需要靈活地增加或縮減數據存儲以及增刪 存儲池中的資源,而不需要中斷系統運行 # 缺點:系統復雜度稍高,需要更多服務器
2:FastDFS系統架構
FastDFS由跟蹤服務器(Tracker Server)、存儲服務器(Storage Server)和客戶端(Client)構成。
(1)跟蹤服務器Tracker Server
主要做調度工作,起到均衡的作用;負責管理所有的 storage server和 group,每個 storage 在啟動后會連接 Tracker,告知自己所屬 group 等信息,並保持周期性心跳。tracker根據storage的心跳信息,建立group==>[storage serverlist]的映射表。
Tracker需要管理的元信息很少,會全部存儲在內存中;另外tracker上的元信息都是由storage匯報的信息生成的,本身不需要持久化任何數據,這樣使得tracker非常容易擴展,直接增加tracker機器即可擴展為tracker cluster來服務,cluster里每個tracker之間是完全對等的,所有的tracker都接受stroage的心跳信息,生成元數據信息來提供讀寫服務。
(2)存儲服務器Storage Server
主要提供容量和備份服務;以 group 為單位,每個 group 內可以有多台 storage server,數據互為備份。以group為單位組織存儲能方便的進行應用隔離、負載均衡、副本數定制(group內storage server數量即為該group的副本數),比如將不同應用數據存到不同的group就能隔離應用數據,同時還可根據應用的訪問特性來將應用分配到不同的group來做負載均衡;缺點是group的容量受單機存儲容量的限制,同時當group內有機器壞掉時,數據恢復只能依賴group內地其他機器,使得恢復時間會很長。
group內每個storage的存儲依賴於本地文件系統,storage可配置多個數據存儲目錄,比如有10塊磁盤,分別掛載在/data/disk1-/data/disk10,則可將這10個目錄都配置為storage的數據存儲目錄。storage接受到寫文件請求時,會根據配置好的規則選擇其中一個存儲目錄來存儲文件。為了避免單個目錄下的文件數太多,在storage第一次啟動時,會在每個數據存儲目錄里創建2級子目錄,每級256個,總共65536個文件,新寫的文件會以hash的方式被路由到其中某個子目錄下,然后將文件數據作為本地文件存儲到該目錄中。
(3)客戶端Client
主要是上傳下載數據的服務器,也就是我們自己的項目所部署在的服務器。每個客戶端服務器都需要安裝Nginx
Tracker相當於FastDFS的大腦,不論是上傳還是下載都是通過tracker來分配資源;客戶端一般可以使用ngnix等靜態服務器來調用或者做一部分的緩存;存儲服務器內部分為卷(或者叫做組),卷於卷之間是平行的關系,可以根據資源的使用情況隨時增加,卷內服務器文件相互同步備份,以達到容災的目的。
(4)FastDFS的存儲策略
為了支持大容量,存儲節點(服務器)采用了分卷(或分組)的組織方式。存儲系統由一個或多個卷組成,卷與卷之間的文件是相互獨立的,所有卷的文件容量累加就是整個存儲系統中的文件容量。一個卷可以由一台或多台存儲服務器組成,一個卷下的存儲服務器中的文件都是相同的,卷中的多台存儲服務器起到了冗余備份和負載均衡的作用。
在卷中增加服務器時,同步已有的文件由系統自動完成,同步完成后,系統自動將新增服務器切換到線上提供服務。當存儲空間不足或即將耗盡時,可以動態添加卷。只需要增加一台或多台服務器,並將它們配置為一個新的卷,這樣就擴大了存儲系統的容量。
(5)FastDFS的上傳過程
FastDFS向使用者提供基本文件訪問接口,比如upload、download、append、delete等,以客戶端庫的方式提供給用戶使用。
我們知道Storage Server會定期的向Tracker Server發送自己的存儲信息。當Tracker Server Cluster中的Tracker Server不止一個時,各個Tracker之間的關系是對等的,所以客戶端上傳時可以選擇任意一個Tracker。
當Tracker收到客戶端上傳文件的請求時,會為該文件分配一個可以存儲文件的group,當選定了group后就要決定給客戶端分配group中的哪一個storage server。當分配好storage server后,客戶端向storage發送寫文件請求,storage將會為文件分配一個數據存儲目錄。然后為文件分配一個fileid,最后根據以上的信息生成文件名存儲文件。文件名的格式如下:
(6)FastDFS的文件同步
寫文件時,客戶端將文件寫至group內一個storage server即認為寫文件成功,storage server寫完文件后,會由后台線程將文件同步至同group內其他的storage server。
每個storage寫文件后,同時會寫一份binlog,binlog里不包含文件數據,只包含文件名等元信息,這份binlog用於后台同步,storage會記錄向group內其他storage同步的進度,以便重啟后能接上次的進度繼續同步;進度以時間戳的方式進行記錄,所以最好能保證集群內所有server的時鍾保持同步。
storage的同步進度會作為元數據的一部分匯報到tracker上,tracke在選擇讀storage的時候會以同步進度作為參考。
(7)FastDFS的文件下載
客戶端uploadfile成功后,會拿到一個storage生成的文件名,接下來客戶端根據這個文件名即可訪問到該文件。
跟upload file一樣,在downloadfile時客戶端可以選擇任意tracker server。tracker發送download請求給某個tracker,必須帶上文件名信息,tracke從文件名中解析出文件的group、大小、創建時間等信息,然后為該請求選擇一個storage用來服務讀請求。
二:搭建FastDFS環境(單機版)
1:基本准備
(1):系統准備 ①:剛重置的騰訊雲 CentOS 7.6 系統 (2):文件准備 ①:libfastcommon :是FastDFS文件系統運行需要的公共 C 語言函數庫 ②:FastDFS :主體文件需要安裝部署在Linux環境下 ③:fastdfs-client-java : java客戶端基本代碼(需maven手動編譯) ④:fastdfs-nginx-module :擴展模塊,集成Nginx里實現負載均衡等功能 ⑤:Nginx :實現負載均衡及文件的訪問是用到
(3):上傳准備的文件,出fastdfs-client-java 其它全部上傳
切換到根目錄下上傳 個人喜好 cd /root
執行上傳命令:rz -y
(1):環境檢查是否有 gcc 、libevent 、libevent-devel
檢查命令: yum list installed | grep gcc yum list installed | grep libevent yum list installed | grep libevent-devel 安裝命令,如果有新版則更新 yum install gcc libevent libevent-devel -y
2:安裝 libfastcommon 庫
libfastcommon 庫是 FastDFS 文件系統運行需要的公共 C 語言函數庫;注意:v1.0.39和FastDFS5.11不兼容
>>解壓 tar -zxvf libfastcommon-1.0.48.tar.gz >>進入解壓后的目錄 cd libfastcommon-1.0.48/ >>編譯解壓的文件 這里需要gcc環境 ./make.sh >>安裝編譯后的文件 ./make.sh install >>完成
3:安裝 FastDFS 主體文件
FastDFS沒有Windows版本,不能在Windows下使用。FastDFS需要安裝部署在Linux環境下
>>解壓 tar -zxvf fastdfs-6.07.tar.gz >>進入解壓后的目錄 cd fastdfs-6.07/ >>編譯解壓的文件 和 安裝編譯的文件 ./make.sh && ./make.sh install
>>檢查是否安裝了 (安裝后命令會存在/usr/bin)
ls /usr/bin | grep fdfs
(1):查看 FastDFS 配置文件
安裝FastDFS后配置文件存放在 /etc/fdfs 下;注:另外注意需要把之前解壓的fastdfs-6.0.7/conf目錄下的兩個文件拷貝到安裝后產生的/etc/fdfs/目錄下 ,否則后續會有很多奇怪問題不好解決 http.conf 和 mime.types
cp /root/fastdfs-6.07/conf/http.conf /etc/fdfs
cp /root/fastdfs-6.07/conf/mime.types /etc/fdfs
因為這些文件后綴都是 .sample 示例的,所有我們把 .sample后綴都去除
mv /etc/fdfs/client.conf.sample client.conf mv /etc/fdfs/tracker.conf.sample tracker.conf mv /etc/fdfs/storage.conf.sample storage.conf mv /etc/fdfs/storage_ids.conf.sample storage_ids.conf
4:FastDFS的配置 /etc/fdfs/xx.conf
要想運行我們的FastDFS服務,我們得配置我們必要的信息,啟動tracker服務則需要配置tracker.conf,啟動storage服務也需要配置對應文件
(1):負載均衡 tracker.conf 配置文件的配置修改
如果不方便使用vim更改的話,可以使用 rz -y 上傳 和 sz file名稱 下載 到本地編輯
配置 tracker 存儲數據的目錄(自定義配置后期tracker產生的數據和日志保存的地方)
配置:base_path = /opt/fastdfs/tracker 注:設置的路徑我們必須要手動創建

# 配置tracker.conf 文件是否生效 false生效 true屏蔽 disabled = false # 程序的監聽地址,如果不設定則監聽所有地址(0.0.0.0) bind_addr = # tracker監聽的端口 port = 22122 # 連接超時時間(秒)。 # 默認值為30。 # 注意:在內網(LAN)中,2秒就足夠了。 connect_timeout = 5 # 發送和接收的網絡超時時間(秒)。 # 默認值為30 # tracker server的網絡超時,單位為秒。發送或接收數據時,如果在超時時間后還不能發送 # 或接收數據,則本次網絡通信失敗。 network_timeout = 60 # ------------------------------------------------------ # base_path 目錄地址(根目錄必須存在,子目錄會自動創建) # 附目錄說明: # tracker server目錄及文件結構: # ${base_path} # |__data # | |__storage_groups.dat:存儲分組信息 # | |__storage_servers.dat:存儲服務器列表 # |__logs # |__trackerd.log:tracker server日志文件 # 數據文件storage_groups.dat和storage_servers.dat中的記錄之間以換行符(\n)分隔,字段之間以西文逗號(,)分隔。 # storage_groups.dat中的字段依次為: # 1. group_name:組名 # 2. storage_port:storage server端口號 # # storage_servers.dat中記錄storage server相關信息,字段依次為: # 1. group_name:所屬組名 # 2. ip_addr:ip地址 # 3. status:狀態 # 4. sync_src_ip_addr:向該storage server同步已有數據文件的源服務器 # 5. sync_until_timestamp:同步已有數據文件的截至時間(UNIX時間戳) # 6. stat.total_upload_count:上傳文件次數 # 7. stat.success_upload_count:成功上傳文件次數 # 8. stat.total_set_meta_count:更改meta data次數 # 9. stat.success_set_meta_count:成功更改meta data次數 # 10. stat.total_delete_count:刪除文件次數 # 11. stat.success_delete_count:成功刪除文件次數 # 12. stat.total_download_count:下載文件次數 # 13. stat.success_download_count:成功下載文件次數 # 14. stat.total_get_meta_count:獲取meta data次數 # 15. stat.success_get_meta_count:成功獲取meta data次數 # 16. stat.last_source_update:最近一次源頭更新時間(更新操作來自客戶端) # 17. stat.last_sync_update:最近一次同步更新時間(更新操作來自其他storage server的同步) base_path = /home/yuqing/fastdfs # 此服務器支持的最大並發連接數。 # 默認值為256 max_connections = 1024 # 接受線程數。 # 默認值為1,推薦使用。 # 從V4.07開始 # 該參數決定接收客戶端連接的線程數,默認值為1,適當放大該參數可改善Storage處理連接的能力,改 # 成2[線上環境cpu為32核心可支持足夠多的線程數]。 accept_threads = 1 # 工作線程數。 # 處理網絡IO的工作線程數。 # 默認值為4。 # 從V2.00開始 # 工作線程用來處理網絡IO,默認值為4,該參數影響Stroage可以同時處理的連接數 work_threads = 4 # 最小網絡緩沖區大小。 # 默認值8KB # 接收/發送數據的buff大小,必須大於8KB min_buff_size = 8KB # 最大網絡緩沖區大小。 # 默認值128KB # 接收/發送數據的buff大小必須小於128KB max_buff_size = 128KB # 在存儲文件時選擇group的策略。 # 0:輪詢。 # 1:指定組。 # 2:負載均衡,選擇上傳文件的最大可用空間組 store_lookup = 2 # 上傳文件到哪組。 # 當 store_lookup設置為1時,必須將 store_group設置為指定上傳的組名 store_group = group2 # 上傳文件到哪台存儲服務器。 # 0:循環(默認)。 # 1:第一台按IP地址排序的服務器。 # 2:根據優先級排序,第一個(最小)。 # 注意:如果 use_trunk_file設置為 true,則必須將 set store_server設置為1或2 store_server = 0 # 選擇文件上傳到storage中的哪個(目錄/掛載點),storage可以有多個存放文件的base # path 0:輪訓策略 2:負載均衡,選擇空閑空間最大的 store_path = 0 # 選擇那個storage作為主下載服務器, # 0:輪訓策略 1:主上傳storage作為主下載服務器 download_server = 0 # 系統預留空間,當一個group中的任何storage的剩余空間小於定義的值,整個group就不能上傳文件了 reserved_storage_space = 20% # 設置日志級別 ### emerg for emergency ### alert ### crit for critical ### error ### warn for warning ### notice ### info ### debug log_level = info # 進程以那個用戶/用戶組運行,不指定默認是當前用戶 run_by_group= run_by_user = # 允許那些機器連接tracker默認是所有機器 allow_hosts = * # 定時將日志緩沖區同步到磁盤。 # 默認值為10秒 sync_log_buff_interval = 1 # 檢測 storage server 存活的時間隔,單位為秒。 # storage server定期向 tracker server 發心跳,如果tracker server在一個check_active_interval # 內還沒有收到storage server的一次心跳,那就認為該storage server已經下線。所以本參數值必須大於 # storage server配置的心跳時間間隔。通常配置為storage server心跳時間間隔的2倍或3倍。 check_active_interval = 120 # 線程棧的大小。FastDFS server端采用了線程方式。更正一下, # tracker server線程棧不應小於64KB,不是512KB。 thread_stack_size = 256KB # 存儲服務器IP地址更改時自動調整。 # 默認值為true # storage的ip改變后服務端是否自動調整,storage進程重啟時才自動調整 storage_ip_changed_auto_adjust = true # 存儲同步文件最大延遲秒數。 # 默認值為86400秒(一天)。 # 從V2.00開始 storage_sync_file_max_delay = 86400 # 文件同步最大存儲時間。 # 默認值為300秒。 # 從V2.00開始 # 就是存儲服務器同步一個文件需要消耗的最大時間,單位為300s,即5分鍾。 storage_sync_file_max_time = 300 # 是否使用小文件合並存儲特性 [false代表關閉] use_trunk_file = false # 最小插槽大小,應<=4KB。 # 默認值為256字節。 # 從V3.00開始 # trunk file分配的最小字節數。比如文件只有16個字節,系統也會分配 slot_min_size個字節。 slot_min_size = 256 # 最大插槽大小,應>插槽最小大小。 # 當上傳文件大小<=此值時,將上傳文件存儲到主干文件。 # 默認值為16MB。 # 從V3.00開始 # 只有文件大小<=這個參數值的文件,才會合並存儲。 # 如果一個文件的大小大於這個參數值,將直接保存到一個文件中(即不采用合並存儲方式) slot_max_size = 1MB # 對齊大小越大,磁盤碎片的可能性越小,但浪費的空間也更多。 trunk_alloc_alignment_size = 256 # 是否合並中繼文件的連續可用空間 # since V6.05 trunk_free_space_merge = true # files 刪除/回收未使用的中繼文件 # since V6.05 delete_unused_trunk_files = false # trunk file 大小 # since V3.00 trunk_file_size = 64MB # 是否提前創建 trunk file # since V3.06 trunk_create_file_advance = false # 提前創建trunk file的起始時間點(基准時間),02:00表示第一次創建的時間點是凌晨2點 trunk_create_file_time_base = 02:00 # 創建 trunk file 時間間隔, 86400 即隔一天 trunk_create_file_interval = 86400 # 提前創建trunk file時,需要達到的空閑trunk大小 # 比如本參數為20G,而當前空閑trunk為4GB,那么只需要創建16GB的trunk file即可。 trunk_create_file_space_threshold = 20G # trunk初始化時,是否檢查可用空間是否被占用 trunk_init_check_occupying = false # 是否無條件從trunk binlog中加載trunk可用空間信息 # FastDFS缺省是從快照文件storage_trunk.dat中加載trunk可用空間, # 該文件的第一行記錄的是trunk binlog的offset,然后從binlog的offset開始加載 trunk_init_reload_from_binlog = false # 壓縮 trunk binlog 文件的最小間隔 trunk_compress_binlog_min_interval = 86400 # 壓縮 trunk binlog 文件的間隔時間 (默認1天) trunk_compress_binlog_interval = 86400 # 壓縮 trunk binlog 文件的時間點 trunk_compress_binlog_time_base = 03:00 # trunk binlog 文件最大備份數 trunk_binlog_max_backups = 7 # 是否使用server ID作為storage server標識 use_storage_id = false # 指定存儲ID文件名,可以使用相對路徑或絕對路徑。 # 只有當use_storage_id設置為true時,該參數才有效。 storage_ids_filename = storage_ids.conf # 文件名中存儲服務器的#id類型,值為: ## IP:存儲服務器的IP地址。 ## id:存儲服務器的服務器id。 # 僅當use_storage_id設置為true時,此參數才有效。 # 默認值為ip。 # since V4.03 id_type_in_filename = id # 存儲從文件是否使用符號鏈接 store_slave_file_use_link = false # 是否定期輪轉error log,目前僅支持一天輪轉一次 rotate_error_log = false # error log定期輪轉的時間點,只有當rotate_error_log設置為true時有效 error_log_rotate_time = 00:00 # 是否壓縮舊的錯誤日志 compress_old_error_log = false # 壓縮幾天前的錯誤日志 (compress_old_error_log = false本參數不生效) compress_error_log_days_before = 7 # 當日志文件超過此大小時輪換錯誤日志。 # 設置為0表示不按文件大小輪轉,否則當error log達到該大小,就會輪轉到新文件中 rotate_error_log_size = 0 # 日志文件保留幾天(0代表永久保留) log_file_keep_days = 0 # 是否使用連接池 use_connection_pool = true # 連接空閑時長,超過則連接被關閉 (單位秒) connection_pool_max_idle_time = 3600 # 此跟蹤器服務器上的HTTP端口 http.server_port = 8080 # 檢查存儲HTTP服務器活動間隔秒數。 # <=0表示從不檢查。 # 默認值為30 http.check_alive_interval = 30 # 檢查存儲HTTP服務器活動類型,值為: # TCP:僅使用HTTP端口連接到存儲服務器。 # 不請求,不獲取響應。 # http:存儲檢查活動url必須返回http狀態200。 # 默認值為tcp http.check_alive_type = tcp # 檢查存儲HTTP服務器活動uri/url。 # 注意:Storage Embedded HTTP服務器支持uri:/status.html http.check_alive_uri = /status.html
(2):文件存儲服務器 storage.conf 配置文件的配置修改
配置 storage.conf 是指定后期運行產生的數據和真實的文件存儲位置,注設置的路徑我們必須手動創建
配置storage存儲數據的目錄:base_path = /opt/fastdfs/storage 配置真正存放文件的目錄: store_path0=/opt/fastdfs/storage/files 配置當前存儲節點的跟蹤器地址(就是tracker):tracker_server=119.29.68.209:22122

# 配置storage.conf 文件是否生效 false生效 true屏蔽 disabled = false # 該存儲服務器所屬的組名。 # 注釋或刪除此項目以從跟蹤器服務器獲取, # 在這種情況下,tracker.conf中的use_storage_id必須設置為true。 # 和storage_ids.conf必須正確配置。 group_name = group1 # 程序的監聽地址,如果不設定則監聽所有地址(0.0.0.0) bind_addr = # bind_addr通常是針對server的。當指定bind_addr時,本參數才有效。 # 本storage server作為client連接其他服務器(如tracker server、 # 其他storage server),是否綁定bind_addr。 client_bind = true # storage 默認端口 port = 23000 # 連接超時時間(秒)。 # 默認值為30。 # 注意:在內網(LAN)中,2秒就足夠了。 connect_timeout = 5 # 發送和接收的網絡超時時間(秒)。 # 默認值為30 network_timeout = 60 # 心跳間隔(秒)。 # 存儲服務器定期向Tracker服務器發送心跳。 # 默認值為30 heart_beat_interval = 30 # 磁盤使用情況報告間隔(秒)。 # 存儲服務器定期向Tracker服務器發送磁盤使用情況報告。 # 默認值為300 stat_report_interval = 60 # 數據存儲目錄地址 base_path = /home/yuqing/fastdfs # 最大連接數 max_connections = 1024 # 設置隊列結點的buffer大小。工作隊列消耗的內存大小 = buff_size * max_connections # 設置得大一些,系統整體性能會有所提升。 buff_size = 256KB # 接收數據的線程數 accept_threads = 1 # 工作線程數,一般為cpu個數,當然CPU核數太多的話可以稍小一點。如我們是12CPU,這里設置為8 work_threads = 4 # 磁盤IO讀寫是否分離。磁盤讀/寫分離為false則為混合讀寫, # 如果為true則為分離讀寫的。默認值為V2.00以后為true。 disk_rw_separated = true # 針對單個存儲路徑的讀線程數,默認值為1。 # 讀寫分離時: # 系統中的讀線程數 = disk_reader_threads * store_path_count # 讀寫混合時: # 系統中的讀寫線程數 = (disk_reader_threads + disk_writer_threads) * store_path_count disk_reader_threads = 1 # 針對單個存儲路徑的寫線程數,默認值為1。 # 讀寫分離時: # 系統中的寫線程數 = disk_writer_threads * store_path_count # 讀寫混合時: # 系統中的讀寫線程數 = (disk_reader_threads + disk_writer_threads) * store_path_count disk_writer_threads = 1 # 同步文件時,如果從binlog中沒有讀到要同步的文件,休眠N毫秒后重新讀取。0表示不休眠,立即再次嘗試讀取。 # 出於CPU消耗考慮,不建議設置為0。如何希望同步盡可能快一些,可以將本參數設置得小一些,比如設置為10ms sync_wait_msec = 50 # 同步上一個文件后,再同步下一個文件的時間間隔,單位為毫秒,0表示不休眠,直接同步下一個文件。 sync_interval = 0 # 下面二個一起解釋。允許系統同步的時間段 (默認是全天) 。一般用於避免高峰同步產生一些問題而設定 sync_start_time = 00:00 sync_end_time = 23:59 # 同步 N 個文件后就寫入標記文件 write_mark_file_freq = 500 # 硬盤恢復線程數 disk_recovery_threads = 3 # storage在存儲文件時支持多路徑,默認只設置一個 store_path_count = 1 # store_path(0~⚮),根據0配置存儲文件的存儲路徑。 # 如果store_path0不存在,則取值為base_path(不推薦)。 # 路徑必須存在 store_path0 = /home/yuqing/fastdfs #store_path1 = /home/yuqing/fastdfs2 # subdir_count * subdir_count個目錄會在store_path下創建,采用兩級存儲 subdir_count_per_path = 256 # 設置tracker_server 服務器地址 多個代表多個Tracker集群 tracker_server = 192.168.209.121:22122 tracker_server = 192.168.209.122:22122 # 日志級別 ### emerg for emergency ### alert ### crit for critical ### error ### warn for warning ### notice ### info ### debug log_level = info # 進程以那個用戶/用戶組運行,不指定默認是當前用戶 run_by_group = run_by_user = # 允許那些機器連接tracker默認是所有機器 allow_hosts = * # 文件分發到數據路徑的方式。 # 0: 輪流存放,在一個目錄下存儲設置的文件數后 #(參數file_distribute_rotate_count中設置文件數),使用下一個目錄進行存儲。 # 1: 隨機存儲,根據文件名對應的hash code來分散存儲。 file_distribute_path_mode = 0 # 當上面的參數file_distribute_path_mode配置為0(輪流存放方式)時,本參數有效。 # 當一個目錄下的文件存放的文件數達到本參數值時,后續上傳的文件存儲到下一個目錄中。 file_distribute_rotate_count = 100 # 當寫入大文件時,每寫入N個字節,調用一次系統函數fsync將內容強行同步到硬盤。0表示從不調用fsync fsync_after_written_bytes = 0 # 同步或刷新日志信息到硬盤的時間間隔,單位為秒 # 注意:storage server 的日志信息不是時時寫硬盤的,而是先寫內存。 sync_log_buff_interval = 1 # 同步binglog(更新操作日志)到硬盤的時間間隔,單位為秒 # 本參數會影響新上傳文件同步延遲時間 sync_binlog_buff_interval = 1 # 把storage的stat文件同步到磁盤的時間間隔,單位為秒。 # 注:如果stat文件內容沒有變化,不會進行同步 sync_stat_file_interval = 300 # 線程棧大小,線程棧越大,一個線程占用的系統資源就越多。 thread_stack_size = 512KB # 本storage server作為源服務器,上傳文件的優先級,可以為負數。值越小, # 優先級越高。這里就和 tracker.conf 中store_server= 2時的配置相對應了 upload_priority = 10 # 網卡別名,用ifconfig -a可以看到很多本機的網卡別名,類似eth0,eth0:0等等。 # 多個網卡別名使用逗號分割,默認為空,讓系統自動選擇。 if_alias_prefix = # 是否檢測上傳文件已經存在。如果已經存在,則不存在文件內容,建立一個符號鏈接以節省磁盤空間。 # 這個應用要配合FastDHT 使用,所以打開前要先安裝FastDHT # 1或yes 是檢測,0或no 是不檢測 check_file_duplicate = 0 # 文件去重時,文件內容的簽名方式: ## hash:4個hash code ## md5:MD5 file_signature_method = hash #當check_file_duplicate設置為1時,此值必須設置 key_namespace = FastDFS # FastDHT建立連接的方式 0:短連接 1:長連接 keep_alive = 0 # 是否將文件操作記錄到access log use_access_log = false # 是否定期輪轉access log,目前僅支持一天輪轉一次 rotate_access_log = false # access log定期輪轉的時間點,只有當rotate_access_log設置為true時有效 access_log_rotate_time = 00:00 # 是否壓縮舊的訪問日志 compress_old_access_log = false # 壓縮幾天前的訪問日期 compress_access_log_days_before = 7 # 是否每天輪轉錯誤日志 rotate_error_log = false # 錯誤日志輪轉時間 error_log_rotate_time = 00:00 # 壓縮舊的錯誤日志 compress_old_error_log = false # 壓給它幾天前的錯誤日志 compress_error_log_days_before = 7 # access log按文件大小輪轉 # 設置為0表示不按文件大小輪轉,否則當access log達到該大小,就會輪轉到新文件中 rotate_access_log_size = 0 # error log按文件大小輪轉 # 設置為0表示不按文件大小輪轉,否則當error log達到該大小,就會輪轉到新文件中 rotate_error_log_size = 0 # 保留日志文件的日期0表示不刪除舊的日志文件 log_file_keep_days = 0 # 文件同步的時候,是否忽略無效的binlog記錄 file_sync_skip_invalid_record = false # 是否使用連接池 use_connection_pool = true # 連接的空閑時間超過這個時間將被關閉,單位:秒 connection_pool_max_idle_time = 3600 # 是否使用gzip壓縮二進制日志文件 compress_binlog = true # 壓給它二進制日志時間點 compress_binlog_time = 01:30 # 是否檢查存儲路徑的標記以防止混淆,建議開啟,如果兩個服務使用 # 一個相同的存儲路徑,此參數要設置為 false check_store_path_mark = true # 服務域名, 如果為空則表示使用 IP 地址 http.domain_name = # http 端口 http.server_port = 8888
(3):創建我們之前在配置里指定的一些路徑
必須創建,否則無法啟動 mkdir -p /opt/fastdfs/tracker mkdir -p /opt/fastdfs/storage mkdir -p /opt/fastdfs/storage/files
5:啟動FastDFS服務
我們修改好配置后,並且在配置文件配置的文件路徑也被我們手動創建后就可以來啟動服務了
# 啟動 Tracker 追蹤器服務 fdfs_trackerd /etc/fdfs/tracker.conf # 啟動 Storage 存儲服務器服務 fdfs_storaged /etc/fdfs/storage.conf # 重啟 fdfs_trackerd /etc/fdfs/tracker.conf restart fdfs_storaged /etc/fdfs/storage.conf restart # 關閉 fdfs_trackerd /etc/fdfs/tracker.conf stop fdfs_storaged /etc/fdfs/storage.conf stop
(1):查詢tracker文件下是否被自動創建了data 和 log 文件
命令:ls /opt/fastdfs/tracker/
(2):查詢storage文件下是否自動創建了data 和 log 和files具體文件路徑
6:FastDFS測試上傳、刪除
我們完成了上面的配置后並且也可以運行服務后,我們就可以來測試我們的FastDFS是否存在問題了,在測試前我們需要配置一個 /etc/fdfs/client.conf 的文件
配置client存儲數據的目錄:base_path = /opt/fastdfs/client 注:別忘了把文件夾創建出來 配置當前存儲節點的跟蹤器地址(就是tracker):tracker_server=119.29.68.209:22122

# 連接的超時時間 connect_timeout = 5 # 網絡超時(秒),默認值 60s network_timeout = 60 # 存儲日志文件的基本路徑 base_path = /home/yuqing/fastdfs # tracker server的列表 多個tracker就設置多個 tracker_server = 192.168.0.196:22122 tracker_server = 192.168.0.197:22122 # 日志級別 ### emerg for emergency ### alert ### crit for critical ### error ### warn for warning ### notice ### info ### debug log_level = info # 是否使用連接池 use_connection_pool = false # 連接的空閑時間超過這個時間將被關閉,單位:秒 connection_pool_max_idle_time = 3600 # 是否加載來自跟蹤服務器的FastDFS參數,默認值為false。這里可以設置為true。 load_fdfs_parameters_from_tracker = false # 是否使用storage id替換ip作為storage server標識,默認為false use_storage_id = false # 在文件中設置組名、server ID和對應的IP地址 storage_ids_filename = storage_ids.conf # 端口 http.tracker_server_port = 80
我們要使用測試則需要使用到 fdfs_test 命令來完成測試
命令:fdfs_test /etc/fdfs/client.conf upload 上傳的文件名稱
查詢文件 這里存儲到../00/00里
測試刪除
fdfs_delete_file /etc/fdfs/client.conf group1/M00/00/00/dx1E0WArYHCALYE2AAAADEQKaqU633_big.txt
三:分布式文件系統之FastDFS的HTTP訪問
在文件上傳的時候,上傳成功的信息中有提示我們可以通過某個路徑去訪問上傳的文件,但是我們直接訪問這個路徑,卻不可以,那么已經上傳到FastDFS文件系統中的文件,我們如何在瀏覽器中訪問呢?FastDFS提供了一個Nginx擴展模塊,利用該模塊,我們可以通過Nginx訪問已經上傳到FastDFS上的文件
1:安裝Nginx並添加fastDFS模塊
安裝Nginx環境檢查: gcc編譯器是否安裝 檢查是否安裝:yum list installed | grep gcc 執行安裝:yum install gcc -y openssl庫是否安裝 檢查是否安裝:yum list installed | grep openssl 執行安裝:yum install openssl openssl-devel -y pcre庫是否安裝 檢查是否安裝:yum list installed | grep pcre 執行安裝:yum install pcre pcre-devel -y zlib庫是否安裝 檢查是否安裝:yum list installed | grep zlib 執行安裝:yum install zlib zlib-devel -y 全安裝: yum install gcc openssl openssl-devel pcre pcre-devel zlib zlib-devel –y >>解壓:fastdfs-nginx-module-1.22.tar.gz tar -zxvf fastdfs-nginx-module-1.22.tar.gz >>解壓:nginx-1.19.6.tar.gz tar -zxvf nginx-1.19.6.tar.gz >>進入:nginx-1.19.6 cd nginx-1.19.6/ >>安裝前配置 ./configure --prefix=/usr/local/nginx_fdfs --add-module=/root/fastdfs-nginx-module-1.22/src
--prefix:指定准備安裝到哪 --add-module:指定集成的fdfs模塊 >>編譯 && 安裝 make && make install
2:配置Nginx訪問設置
(1):拷貝模塊文件到 /etc/fdfs
我們需要先把擴展模塊 fastdfs-nginx-module-master/src 里的 mod_fastdfs.conf 文件拷貝到 /etc/fdfs/ 目錄下,這樣才可以正常啟動Nginx
命令:cp /root/fastdfs-nginx-module-1.22/src/mod_fastdfs.conf /etc/fdfs
(2):修改拷貝過來的 /etc/fdfs/mod_fastdfs.conf 文件
# 配置存儲運行產生的日志數據等等 文件路徑必須存在 base_path=/opt/fastdfs/nginx_mod # 設置tracker服務地址 tracker_server=119.29.68.209:22122 # 設置文件url中是否有group名 url_have_group_name = true # 文件數據存儲路徑 store_path0=/opt/fastdfs/storage/files

# 連接超時時間(秒)。 # 默認值為30s connect_timeout=2 # 網絡接收和發送超時(秒)。 # 默認值為30s network_timeout=30 # 日志存儲路徑 base_path=/tmp # 從跟蹤器服務器加載FastDFS參數。 # 從V1.12開始。 # 默認值為False load_fdfs_parameters_from_tracker=true # 存儲同步文件最大延遲秒數。 # 與tracker.conf相同。 # 僅當load_fdfs_Parameters_from_tracker為FALSE時有效。 # 從V1.12開始。 # 默認值為86400秒(一天) storage_sync_file_max_delay = 86400 # 如果使用存儲ID而不是IP地址。 # 與tracker.conf相同。 # 僅當load_fdfs_Parameters_from_tracker為FALSE時有效。 # 默認值為False。 # 從V1.13開始 use_storage_id = false # 指定存儲ID文件名,可以使用相對路徑或絕對路徑。 # 與tracker.conf相同。 # 僅當load_fdfs_Parameters_from_tracker為FALSE時有效。 # 從V1.13開始 storage_ids_filename = storage_ids.conf # tracker 服務列表 tracker_server=tracker:22122 # storage server端口號 storage_server_port=23000 # 本地存儲服務器的組名 group_name=group1 # 文件url中是否有group名 url_have_group_name = false # 存儲路徑個數,需要和store_path個數匹配 store_path_count=1 # store_path#,以0為基數,如果store_path0不存在,則其值為base_path。 # 路徑必須存在。 # 必須與storage.conf相同 store_path0=/home/yuqing/fastdfs #store_path1=/home/yuqing/fastdfs1 # 日志級別: ### emerg for emergency ### alert ### crit for critical ### error ### warn for warning ### notice ### info ### debug log_level=info # 設置日志文件名,如/usr/local/apache2/logs/mod_fast dfs.log。 # Empty表示輸出到stderr(apache和nginx error_log文件) log_filename= # 本地文件系統中不存在文件時的響應方式。 ## proxy:從其他存儲服務器獲取內容,然后發送給客戶端。 ## redirect:重定向到原存儲服務器(HTTP Header為Location) response_mode=proxy # 網卡別名前綴,如Linux中的eth,可以通過ifconfig-a查看。 # 多個別名以逗號分隔。空值表示按操作系統類型自動設置。 # 該參數用於獲取本地主機的所有IP地址。 # 默認值為空 if_alias_prefix= # IF支持FLV。 # 默認值為False。 # 從v1.15開始 flv_support = true # FLV文件擴展名。 # 默認值為flv。 # 從v1.15開始 flv_extension = flv # 設置群數。 # 設置為無零以支持此存儲服務器上的多組。 # 僅針對單個組設置為0。 # 將設置部分分組為[group1]、[group2]、...、[groupn]。 # 默認值為0。 # 從v1.14開始 group_count = 0 # group settings for group #1 # since v1.14 # when support multi-group on this storage server, uncomment following section [group1] # 組名稱# group_name=group1 # 組端口 storage_server_port=23000 # 存儲路徑個數,需要和store_path個數匹配 store_path_count=2 store_path0=/home/yuqing/fastdfs store_path1=/home/yuqing/fastdfs1 # group settings for group #2 # since v1.14 # when support multi-group, uncomment following section as neccessary [group2] group_name=group2 storage_server_port=23000 store_path_count=1 store_path0=/home/yuqing/fastdfs
(3):修改Nginx配置文件
完成上面,我們就得開始配置我們的Nginx配置了,這個配置按照之前的安裝是在 /usr/local/nginx_fdfs/conf/nginx.conf
命令:vim /usr/local/nginx_fdfs/conf/nginx.conf
#攔截請求路徑中包含 /group[1-9]/M[0-9][0-9] 的請求,用 fastdfs的Nginx 模塊進行轉發 location ~ /group[1-9]/M[0-9][0-9] { ngx_fastdfs_module; } #注:ngx_fastdfs_module:這個指令不是Nginx本身提供的,是擴展模塊提供的,根據這個指令找 # 到FastDFS提供的Nginx模塊配置文件,然后找到Tracker,最終找到Stroager
(4):運行Nginx服務
切換到Nginx sbin目錄下:cd /usr/local/nginx_fdfs/sbin/ 執行nginx目錄:./nginx 查詢是否啟動:ps -ef | grep nginx
(5):測試,上傳一個文件並在本地瀏覽器訪問
我們隨便上傳一個文件后,上傳成功后會給我們返回一個帶http的具體鏈接,我們直接在本地瀏覽器就可以訪問(開啟80端口)
# 上傳文件測試 fdfs_test /etc/fdfs/client.conf upload abc.txt # 返回獲取的http地址准備本地訪問 http://119.29.68.209/group1/M00/00/00/dx1E0WArksiARSeLAAAADEQKaqU125.txt
四:FastDFS在Java項目中開發
在真實開發中我們肯定不會使用如 fdfs_test 命令來上傳文件,通常使用java代碼來編寫指定的上傳代碼,但是我們想使用得要一個jar包,就是我們最初下載的 fastdfs-client-java-1.28.tar.gz ,由於是源碼,我們使用 maven 的 mvn 命令編譯一下即可
1:編譯源碼來生成jar包
安裝過后就會出現到你的maven倉庫了..\org\csource\fastdfs-client-java
2:代碼編寫
我們以創建一個簡單的maven項目為例

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>demo_001</artifactId> <version>1.0-SNAPSHOT</version> <!--maven編譯版本--> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <!--導入坐標--> <dependencies> <!--導入FastDFS客戶端jar包--> <dependency> <groupId>org.csource</groupId> <artifactId>fastdfs-client-java</artifactId> <version>1.28-SNAPSHOT</version> </dependency> </dependencies> </project>
完成了 pom.xml 文件的編寫,我們就去resource下創建一個 fastdfs.conf 的配置文件指定 tracker地址
tracker_server = 119.29.68.209:22122

public class Test { public static void main(String[] args) { //上傳 //upload(); //下載 //download(); //刪除 delete(); } //上傳方法 //注意22122 23000端口的開放 public static void upload() { try { //加載配置文件 ClientGlobal.init("fastdfs.conf"); //創建 TrackerClient跟蹤器客戶端 TrackerClient trackerClient = new TrackerClient(); //通過 TrackerClient跟蹤器客戶端 獲取 TrackerServer跟蹤器服務端 TrackerServer trackerServer = trackerClient.getTrackerServer(); //通過 TrackerClient跟蹤器客戶端 獲取 StorageServer存儲服務器服務端 StorageServer storeStorage = trackerClient.getStoreStorage(trackerServer); //創建存儲服務器客戶端 StorageClient storageClient = new StorageClient(trackerServer, storeStorage); //開始上傳 // 第一個參數文件路徑,也可以是二進制數組 // 第二個參數是文件類型 String[] strings = storageClient.upload_file("h:\\1.jpg", "jpg", null); for (String str : strings) { System.out.println(str); //打印: // group1 // M00/00/00/dx1E0WArsfeAWVTvAAEoDtcZimw368.jpg } //關閉資源 storageClient.close(); } catch (IOException | MyException e) { e.printStackTrace(); } } //下載 public static void download() { try { //加載配置文件 ClientGlobal.init("fastdfs.conf"); //創建 TrackerClient跟蹤器客戶端 TrackerClient trackerClient = new TrackerClient(); //通過 TrackerClient跟蹤器客戶端 獲取 TrackerServer跟蹤器服務端 TrackerServer trackerServer = trackerClient.getTrackerServer(); //通過 TrackerClient跟蹤器客戶端 獲取 StorageServer存儲服務器服務端 StorageServer storeStorage = trackerClient.getStoreStorage(trackerServer); //創建存儲服務器客戶端 StorageClient storageClient = new StorageClient(trackerServer, storeStorage); //開始下載 byte[] bytes = storageClient.download_file("group1", "M00/00/00/dx1E0WArsfeAWVTvAAEoDtcZimw368.jpg"); //寫出文件 new FileOutputStream("H:\\downloadfile.jpg").write(bytes); //關閉資源 storageClient.close(); } catch (IOException | MyException e) { e.printStackTrace(); } } //刪除 public static void delete() { try { //加載配置文件 ClientGlobal.init("fastdfs.conf"); //創建 TrackerClient跟蹤器客戶端 TrackerClient trackerClient = new TrackerClient(); //通過 TrackerClient跟蹤器客戶端 獲取 TrackerServer跟蹤器服務端 TrackerServer trackerServer = trackerClient.getTrackerServer(); //通過 TrackerClient跟蹤器客戶端 獲取 StorageServer存儲服務器服務端 StorageServer storeStorage = trackerClient.getStoreStorage(trackerServer); //創建存儲服務器客戶端 StorageClient storageClient = new StorageClient(trackerServer, storeStorage); //開始刪除 int result = storageClient.delete_file("group1", "M00/00/00/dx1E0WArsfeAWVTvAAEoDtcZimw368.jpg"); System.out.println(result == 0 ? "刪除成功" : "刪除失敗"); //0成功,返回其它數字都是失敗 //關閉資源 storageClient.close(); } catch (IOException | MyException e) { e.printStackTrace(); } } }
.