分散式文件系統FastDFS 技術整理

来源:https://www.cnblogs.com/xiegongzi/archive/2022/06/05/16330724.html
-Advertisement-
Play Games

1、FastDFS 1.1、瞭解基礎概念 1.1.1、什麼是分散式文件系統? 全稱:Distributed File System,即簡稱的DFS 這個東西可以是一個軟體,也可以說是伺服器,和tomcat差不多,即相當於軟體也相當於是伺服器,這個軟體就是用來管理文件的 這個軟體所管理的文件通常不是在 ...


1、FastDFS

1.1、瞭解基礎概念

1.1.1、什麼是分散式文件系統?

  • 全稱:Distributed File System,即簡稱的DFS
  • 這個東西可以是一個軟體,也可以說是伺服器,和tomcat差不多,即相當於軟體也相當於是伺服器,這個軟體就是用來管理文件的
  • 這個軟體所管理的文件通常不是在一個伺服器節點上,而是在多個伺服器節點上
  • 伺服器節點通過網路相連構成一個龐大的文件存儲伺服器集群,這些伺服器都用於存儲文件資源,通過分散式文件系統來管理這些伺服器上的文件


1.1.2、傳統文件系統 和 分散式文件系統對比

傳統文件系統

image

  • 缺點
    • 所有的文件都存放在一臺電腦中,如果這台電腦掛彩了,那麼就會導致整個服務不可用( 文件不能上傳和下載了 )
    • 如果這台電腦磁碟損壞了,那麼會丟失所有的文件
    • 這台電腦的磁碟空間非常有限,很容易到達磁碟的上限,導致無法上傳文件

  • 回顧玩servlet時的文件上傳和下載

    文件上傳

    • 假如前端轟HTML寫法是如下的樣子:
    		  <div id="image">
    			  <label for="">標題圖片:</label>
    			  <input type="file" id="file" name="file" >
    			  <img src="" alt="" width="100px" height="150px">
    		  </div>
    
    
    • JS寫法如下:
    		// 當圖片發生改變時 —— 也就是用戶點擊file框,上傳文件時
    		$("#file").on( 'change' , function () {
    
    			// 創建一個FormData空對象,就相當於是偽造了一個form表單
    			let formData = new FormData();
    
    			// 這個FromData對象就用來裝文件內容
                // 文件的files屬性本質是個數組
    			let files = $("#file").prop("files");
    			formData.append("upFile" , files[0] );
    
    			$.ajax( {
    
    				url: '/ajax/upload.do',
    				type: 'post',
    				data: formData,
    				dataType: 'json',
    
    				cache: false,    // 上傳文件不需要緩存
    				contentType: false,      // 不需要對內容類型進行處理  因為內容是一個FormData對象
    				processData: false,       // 不需要對數據進行處理,因為上面的data是一個FormData對象
    
    				// 後臺返回的格式 :
    				// { "errno":"0" , "data":[ {"alt":"1633528500498.jpg" , "url":"/upload/2021-10-06/1633528500498.jpg"} ] }
    				success: function (info) {
    					info.data.forEach( function (data) {
    
    						// $("#image img").remove();
    						// $("#image").append( ' <img src=" '+data.url+' " alt="" width="100px" height="150px"> ' )
    
    	/*
    	 註掉的這種是:html中沒有img標簽時使用
    	 因為:使用下麵這種方法的情景是 —— 頁面本來就有一個img框( 即:初始頁面上這個file本身有一張圖片 ),所以下麵這種可以做到圖片改變時把圖片的路徑換掉,也就是圖片渲染( 也是數據回填 的思想 )
    	 但是:如果頁面一開始file的位置是不應該有圖片的,是後面用戶選了之後才出現圖片預覽效果,那麼:就使用註釋掉的這種方法:追加
    	*/
    
    						$("#image img").attr("src" , data.url );
    					});
    				}
    			} );
    
    		})
    
    
    • 那麼後端的low代碼如下:
    	import com.alibaba.fastjson.JSON;
    
    	import javax.servlet.ServletException;
    	import javax.servlet.annotation.MultipartConfig;
    	import javax.servlet.annotation.WebServlet;
    	import javax.servlet.http.HttpServlet;
    	import javax.servlet.http.HttpServletRequest;
    	import javax.servlet.http.HttpServletResponse;
    	import javax.servlet.http.Part;
    	import java.io.File;
    	import java.io.IOException;
    	import java.time.LocalDate;
    	import java.util.ArrayList;
    	import java.util.Collection;
    	import java.util.Date;
    	import java.util.HashMap;
    
    
    	// @MultipartConfig 註解就是文件註解,要獲取前端的文件信息,必須加這個註解,不然做的所有事情都是無用功
    	@MultipartConfig
    	@WebServlet("/ajax/upload.do")
    	public class UploadServlet extends HttpServlet {
    
    		@Override
    		protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    			/*
    			*   想要構建的是這麼一個玩意兒
    			*       "errno":0 data:[ { url:"圖片地址“ } , { alt:"圖片說明“ } , { href:"null" } ]
    			*
    			* */
    
    			ArrayList<Object> list = new ArrayList<>();
    
    			Collection<Part> parts = req.getParts();   // 這是獲取前臺上傳的文件
    
    			for (Part part : parts) {
    
    				// 先構建 data:[ { } , { } ]中的[ { } , { } ]
    
    				// 獲取文件的全路徑
                    // 但是:不同瀏覽器的這個全路徑都不一樣,所以需要截取從而自定義文件名
    				String filePath = part.getSubmittedFileName();  
    				// System.out.println(filePath);
    				// 截取文件的尾碼名
    				int subFileName = filePath.lastIndexOf(".");
    				String fileSuffix = filePath.substring(subFileName);
    
    				// 自己給文件重新定義一個名字,並規定存放的地方
    				String timeStr = LocalDate.now().toString();
    
    				// 獲取當前項目的一個指定文件夾名字,用來保存文件 註意:getRealPath這是獲取的當前項目的全路徑,即:從盤符開始的路徑
    				String proPathName = this.getServletContext().getRealPath("/upload/" + timeStr );
    				File file = new File(proPathName);
    				if ( !file.exists() ){
    					file.mkdirs();
    				}
    
    				// 拼接文件尾碼名並保存文件
    				long timeStamp = new Date().getTime();
    				part.write(proPathName + "/" + timeStamp + fileSuffix );
    
    				HashMap<String, String> map = new HashMap<>();
    				map.put( "url" , "/upload/" + timeStr + "/" + timeStamp + fileSuffix );
    				map.put( "alt" , timeStamp + fileSuffix );
    				map.put( "href" , null );
    				list.add(map);
    			}
    
    			// 再構建"errno":0 data:[ { url:"圖片地址“ } , { alt:"圖片說明“ } , { href:"null" } ]
    			HashMap<String, Object> map = new HashMap<>();
    			map.put("errno", "0");
    			map.put("data", list);
    
    			resp.getWriter().print( JSON.toJSONString(map) );
    		}
    	}
    
    

image


文件下載

  • 後端low代碼如下
	import javax.servlet.ServletException;
	import javax.servlet.ServletOutputStream;
	import javax.servlet.annotation.WebServlet;
	import javax.servlet.http.HttpServlet;
	import javax.servlet.http.HttpServletRequest;
	import javax.servlet.http.HttpServletResponse;
	import java.io.FileInputStream;
	import java.io.IOException;
	import java.net.URLEncoder;

	@WebServlet("/downFile")
	public class downFileInClientServlet extends HttpServlet {

		@Override
		protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			doPost(req, resp);
		}

		@Override
		protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

			// 1、獲取讓瀏覽器下載的文件路徑
			String FileRealPath = "D:\\JavaTrainStudy\\servlet\\out\\production\\study06-httpServletResponse\\loginbg.png";

			// 2、告知瀏覽器要下載的文件名是什麼?
			String fileName = FileRealPath.substring( FileRealPath.lastIndexOf("\\") + 1 );

			// 3、讓瀏覽器支持文件下載
			// Content-Disposition這個就是讓瀏覽器支持文件下載
			// URLEncoder.encode( String s , String enc ) 是為了以防文件名是中文名,這樣就設置編碼格式了,讓瀏覽器能夠解析這個中文文件名
			resp.setHeader("Content-Disposition" , "attachment ; filename=" + URLEncoder.encode(fileName , "utf-8"));

			// 4、獲取輸入、輸出流對象 並 把伺服器中的文件輸出到瀏覽器上
			FileInputStream fis = new FileInputStream( FileRealPath );
			ServletOutputStream os = resp.getOutputStream();

			// 創建緩衝區
			int len = 0 ;
			byte[] buffer = new byte[1024];
			while ( ( len = fis.read( buffer ) )  > 0 ){
				os.write( buffer , 0 , len);
			}

			// 5、關閉流管道
			if ( os != null ){
				os.close();
			}
			if ( fis != null ){
				fis.close();
			}

		}
	}

image



分散式文件系統

image

  • 優點
    • 解決了傳統方式的單點故障問題
    • 若某一個節點出現故障,則還有其他的節點可以用來讀取和寫入文件
    • 提供數據備份從而避免磁碟損壞而導致的文件丟失
    • 提供擴容機制,無限增加文件存放的空間上限


1.2、認識FastDFS

補充:常見的分散式文件系統

  • FastDFS、GFS、HDFS、Lustre 、Ceph 、GridFS 、mogileFS、TFS


1.2.1、瞭解FastDFS

  • 官網:https://github.com/happyfish100/fastdfs
  • FastDFS是一個開源的輕量級分散式文件系統,為互聯網應用量身定做,簡單、靈活、高效,採用C語言開發,由阿裡巴巴開發並開源
  • FastDFS對文件進行管理,功能包括:文件存儲、文件同步( 指的是:文件系統 和 數據備份之間的同步 )、文件上傳、文件下載、文件刪除等
  • FastDFS解決了大容量文件存儲的問題
  • FastDFS特別適合以文件為載體的線上服務,如相冊網站、文檔網站、圖片網站、視頻網站等
  • FastDFS充分考慮了冗餘備份、線性擴容等機制,並註重高可用、高性能等指標,使用FastDFS很容易搭建一套高性能的文件伺服器集群提供文件上傳、下載等服務
    • 冗餘備份:指的是文件系統中存的文件 和 數據備份中存的文件完全一致的問題
      • image
    • 線性擴容:文件系統 和 數據備份不斷增加唄( 就是上圖中再加幾份嘛 ),和水平擴容類似


1.2.2、FastDFS的組成結構

  • 由兩大部分構成,一個是客戶端,一個是服務端
    • 客戶端:指我們的程式,比如我們的Java程式去連接FastDFS、操作FastDFS,那我們的Java程式就是一個客戶端。FastDFS提供專有API訪問,目前提供了C、Java和PHP幾種編程語言的API,用來訪問FastDFS文件系統
    • 服務端由兩個部分構成:一個是跟蹤器(tracker),一個是存儲節點(storage)
      • 跟蹤器 tracker:這個玩意兒類似於Erueka / zookeeper註冊中心,起到一個調度的作用。它是在記憶體中記錄集群中存儲節點storage的狀態信息,是前端Client和後端存儲節點storage的樞紐,因為相關信息全部在記憶體中,Tracker server的性能非常高,一個較大的集群(比如上百個group,group指的就是:文件系統 和 數據備份的組合,這二者就是一個group)中有3台就足夠了
      • 存儲節點 storage:用於存儲文件,包括文件和文件屬性(meta data,如:文件名、文件大小、文件尾碼...)都保存到存儲伺服器磁碟上。以及完成文件管理的所有功能:文件存儲、文件同步和提供文件訪問( 上傳、下載、刪除 )等


2、開始玩FastDFS

2.1、安裝FastDFS

  • 註:我的系統是centos 7

  • 安裝需要的依賴環境 gcc、libevent、libevent-devel

yum install gcc libevent libevent-devel -y


  • 安裝公共函數庫libfastcommon 和 fastDFS壓縮包
    • 自行去前面官網中進行下載,當然:官網的wiki中有線上拉取命令

image


  • 解壓公共函數庫libfastcommon
tar -zxvf libfastcommon-1.0.36.tar.gz

  • 進入libfastcommon,執行裡面的make.sh,編譯公共函數
./make.sh

# 當然:可以把命令進行合併 執行如下命令 就是編譯並安裝
./make.sh && ./make.sh install

image

  • 安裝公共函數
./make.sh install

image


  • 解壓fastdfs-5.11.tar.gz壓縮包
tar -zxvf fastdfs-5.11.tar.gz

  • 進入解壓之後的文件,使用make sh進行編譯
./make.sh

# 一樣的可以用組合命令 即:編譯並安裝
./make.sh && ./make.sh install

  • 安裝
./make.sh install


  • 檢查是否安裝成功,進入如下的目錄即可
cd /usr/bin

  • 往後找,出現這些fdfs開頭的文件就表示成功( 這些文件就是fastDFS的相關命令 )

image


  • fastDFS配置文件所在地,進入如下目錄即可
  • 想要讓fastDFS的配置文件生效,那麼就需要放到下麵的這個目錄中
cd /etc/fdfs

image


  • 拷貝兩個配置文件到etc/fdfs中,這兩個配置文件在解壓的fastDFS的conf中,一個叫http.conf,一個叫mime.types
# 供nginx訪問使用
cp http.conf /etc/fdfs

# 供nginx訪問使用
cp mime.types /etc/fdfs

image



2.2、啟動FastDFS

  • 這個玩意兒不可以直接啟動,因為預設的配置文件中有一些關於文件目錄的配置是不存在的,因此:只要直接啟動就會報錯

2.2.1、修改配置文件

  • 要修改的文件就兩個

image

  • 以防萬一,因此:將上面的文件拷貝一份
/etc/fdfs

mv storage.conf.sample ./storage.conf

mv tracker.conf.sample ./tracker.conf

image


2.2..1.1、修改tracker.conf

  • 在這個配置文件中有一個base_path配置,指向的是fastDFS作者餘慶的地址,而我們自己的linux中並沒有這個目錄,因此:做修改
vim tracker.conf

# 搜索此配置
/base_path

# 改成的值,也可以自定義自己的目錄( 註意:需要保證這個目錄必須存在,沒存在那就需要創建 )
base_path=/opt/fastdfs/tracker

  • 註意:需要保證這個目錄必須存在,沒存在那就需要創建

2.2.1.2、修改storage.conf

  • 需要改的內容如下
# storage存儲數據目錄
base_path=/opt/fastdfs/storage

# 真正存放文件的目錄
store_path0=/opt/fastdfs/storage/files

# 註冊當前存儲節點的跟蹤器地址
tracker_server=伺服器ip:22122
	
  • 註意:要是前面的那三個目錄沒有的話,記得創建,若指向的是已經創建好的目錄,那就不用創建了
mkdir -p /opt/fastdfs/tracker

mkdir -p /opt/fastdfs/storage

mkdir -p /opt/fastdfs/storage/files


2.2.2、開啟fastDFS

  • 在任意目錄下,執行如下的命令即可
# 啟動tracker 要想看fdfs_trackerd的命令用法,那直接輸入fdfs_trackerd就可以彈出其用法了
# 如:要關閉tracker,則命令為:fdfs_trackerd /etc/fdfs/tracker.conf stop
# 開啟 | 重啟就是把stop改成start | restart即可
fdfs_trackerd /etc/fdfs/tracker.conf

# 啟動storage
fdfs_storaged /etc/fdfs/storage.conf



  • 查看是否啟動成功
ps -ef | grep fdfs

  • 如下圖表示啟動成功

image


  • 但是上面的啟動會有坑兒,所以需要確認一把
# 查看日誌文件是否有報ERROR
cat /opt/fastdfs/storage/logs/storage.log


  • 若是發現日誌中報的是如下信息
ERROR - file: storage_ip_changed_dealer.c, line: 180, connect to tracker server 伺服器ip:22122 fail, errno: 110, error info: Connection timed out

即:鏈接超時

  • 這種情況一般都是22122埠沒開放
# 開放22122埠
firewall-cmd --zone=public --add-port=22122/tcp --permanent

# 重啟防火牆
systemctl restart firewalld.service

# 當然:要是雲伺服器的話,直接在web管理界面中添加規則( 開放22122埠 ) 即可



2.2.3、查看預設創建的文件數

  • 進入如下的目錄
cd /opt/fastdfs/storage/files/data

image

  • 這裡面有256個文件夾,而每一個文件夾裡面又有256個文件夾,即256 * 256個文件夾,總的文件夾數目為6萬多個

    • 這256 * 256個文件夾的作用:解決的就是如下的問題

    image

    • 而fastDFS就是使用那256 * 256個文件夾,把文件分別放入哪些文件夾中,這樣就讓搜索變得方便了


2.2.4、測試FastDFS

2.2.4.1、測試上傳文件

  • 要想進行測試的話,需要修改一個配置文件,因為這個配置文件中的配置信息是作者餘慶的

image

  • 要修改的內容如下:
# 註意:這個目錄也要保證存在,不存在就是創建 mkdir -p /opt/fastdfs/client
base_path=/opt/fastdfs/client

tracker_server=自己伺服器ip:22122


  • 搞一個用來測試上傳的文件

image

  • 執行文件上傳命令

    • 可以使用如下命令看一下測試文件上傳命令是怎麼寫的

      • fdfs_test
        
        

image

  • 提取出測試命令語法
fdfs_test <config_file> <operation>
	operation: upload, download, getmeta, setmeta, delete and query_servers
# <> 表示必填

# 因此:在測試中,文件上傳的指令為:
fdfs_test /etc/fdfs/client.conf upload /root/hello-fastdfs.txt


image

  • 註意:防火牆的問題啊,要是報:connect to xxx.xx.xx.xx:23000 fail, errno: 113, error info: No route to host,這就是防火牆沒開放23000埠,打開就可以了
# 開放23000埠
firewall-cmd --zone=public --add-port=23000/tcp --permanent

# 刷新防火牆
systemctl restart firewalld.service


  • 上面成功之後有一堆信息,很重要
This is FastDFS client test program v5.11

Copyright (C) 2008, Happy Fish / YuQing

FastDFS may be copied only under the terms of the GNU General
Public License V3, which may be found in the FastDFS source kit.

# 這個是說訪問fastdfs的主頁網址 - 目前還不能訪問,需要後面弄
Please visit the FastDFS Home Page http://www.csource.org/ 
for more detail.

# 這是配置的client.conf中的信息
[2022-06-01 10:17:07] DEBUG - base_path=/opt/fastdfs/client, connect_timeout=30, network_timeout=60, tracker_server_count=1, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0

tracker_query_storage_store_list_without_group: 
	server 1. group_name=, ip_addr=162.14.66.60, port=23000

group_name=group1, ip_addr=162.14.66.60, port=23000
storage_upload_by_filename
# 重要的信息在這裡group_name、remote_filename
# group_name就是組名,在前面配置中見過它,就是說的文件系統 和 數據備份這二者的組合名
# remote_filename 遠程文件名 這是關鍵中的關鍵,告知你:文件保存到那裡去了
group_name=group1, remote_filename=M00/00/00/CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt
source ip address: 10.0.0.16
file timestamp=2022-06-01 10:17:07
file size=641
file crc32=1141168436
# 下麵這個URL地址很重要,就是去瀏覽器訪問上傳的這個文件資源的地址,但是:目前還不可以訪問,因為沒有配置Nginx
example file url: http://162.14.66.60/group1/M00/00/00/CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt
storage_upload_slave_by_filename
group_name=group1, remote_filename=M00/00/00/CgAAEGKWzCOACGE1AAACgUQE2TQ590_big.txt
source ip address: 10.0.0.16
file timestamp=2022-06-01 10:17:07
file size=641
file crc32=1141168436
example file url: http://162.14.66.60/group1/M00/00/00/CgAAEGKWzCOACGE1AAACgUQE2TQ590_big.txt

  • 單獨說明:remote_filename
remote_filename=M00/00/00/

M00 指的是:/opt/fastdfs/storage/files/data			就是前面去看預設創建文件數( 256 * 256 )的位置,跟前面的配置有關啊

00/00/ 指的就是:/opt/fastdfs/storage/files/data目錄下的00子目錄,這裡面的00目錄

CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt  指的是:保存的文件名  fastdfs會重新生成文件名,以防的就是同名文件,造成附件覆蓋的問題

image

image

  • 上圖中幾個文件解讀
# _big 就是數據備份文件
# _m 就是meta data文件,即:文件屬性文件( 文件名、文件尾碼、文件大小..... )
-rw-r--r-- 1 root root 641 Jun  1 10:17 CgAAEGKWzCOACGE1AAACgUQE2TQ590_big.txt
-rw-r--r-- 1 root root  49 Jun  1 10:17 CgAAEGKWzCOACGE1AAACgUQE2TQ590_big.txt-m

# 這兩個就是文件系統中的文件
-rw-r--r-- 1 root root 641 Jun  1 10:17 CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt
-rw-r--r-- 1 root root  49 Jun  1 10:17 CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt-m


# CgAAEGKWzCOACGE1AAACgUQE2TQ590_big.txt 和 文件系統中的CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt存的內容是一樣的

# CgAAEGKWzCOACGE1AAACgUQE2TQ590_big.txt-m 和 CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt-m這兩個備份文件也是相應的


image



2.2.4.2、測試文件下載和刪除
  • 前面已經見過對應的語法了
fdfs_test <config_file> <operation>
	operation: upload, download, getmeta, setmeta, delete and query_servers
# <> 表示必填

  • 變一下就可以了
# 變成下載的命令,然後使用此命令查看完整命令即可
fdfs_test /etc/fdfs/client.conf download


# 根據執行上面的命令,得到文件下載的語法
fdfs_test <config_file> download <group_name> <remote_filename>

# 那麼想要下載剛剛上傳的文件,執行如下的命令即可
fdfs_test /etc/fdfs/client.conf download group1 M00/00/00/CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt
# 其中:group 和 remote_filename都在前面上傳時見過了
# 註:這個下載是下載到當前所在目錄的位置


# 同理:就可以得到文件刪除的命令了
fdfs_test /etc/fdfs/client.conf delete group1 M00/00/00/CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt

  • 以上這些fdfs_test只會在測試時使用,其他地方基本上都不用的


2.3、安裝Nginx

  • 上傳fastdfs-niginx擴展模塊 並 解壓 - 使用官網中wiki說明的命令拉取也行

  • 安裝nginx,要是有的話就跳過

image

  • 記住兩個目錄
# nginx安裝目錄
/usr/local/nginx_fdfs

# fastdfs-nginx模塊的src目錄
/usr/local/fastdfs-nginx-module-master/src

image

  • 進入nginx安裝目錄,進行模塊添加配置
# 進入nginx安裝目錄
cd nginx_fdfs

# 執行模塊配置 
# prefix 就是前面讓記住的nginx安裝目錄	add-module就是fastdfs-nginx模塊的src目錄
./configure --prefix=/usr/local/nginx_fdfs --add-module=/usr/local/fastdfs-nginx-module-master/src


  • 編譯並安裝
# 在安裝的nginx目錄下載執行下述命令
make & make install

image

  • 註釋事項:Nginx的安裝需要Linux安裝相關的幾個庫,否則編譯會出現錯誤,有這幾個的話就不安裝了
yum install gcc openssl openssl-devel pcre pcre-devel zlib zlib-devel –y



2.3.1、修改需要的配置文件

  • 將fastdfs-nginx擴展模塊中的mod_fastdfs.conf文件複製到/etc/fdfs
cp /usr/local/fastdfs-nginx-module-master/src/mod_fastdfs.conf /etc/fdfs

image

  • 修改/etc/fdfs/mod_fastdfs.conf
vim mod_fastdfs.conf

# 修改內容如下:
# 這個目錄要保證存在,不存在就要配置好了創建它 mkdir -p /opt/fastdfs/nginx_mod
base_path=/opt/fastdfs/nginx_mod

tracker_server=自己伺服器ip:22122

# 訪問地址是否帶上組名
url_have_group_name = true

store_path0=/opt/fastdfs/storage/files

  • 上面base_path目錄要是不存在記得創建

image

  • 進入nginx_fdfs的安裝目錄中,去nginx.conf中配置fastdfs-nginx的擴展模塊
# 編輯nginx.conf文件
vim /usr/local/nginx_fdfs/conf/nginx.conf

# 配置內容
location ~ /group[1-9]/M0[0-9] {	
     ngx_fastdfs_module;  
}


# 解讀:ngx_fastdfs_module
# 	這個指令不是Nginx本身提供的,是擴展模塊提供的,根據這個指令找到FastDFS提供的Nginx模塊配置文件,然後找到Tracker,最終找到Stroager

image

  • 啟動nginx
/usr/local/nginx_fdfs/sbin/nginx -c /usr/local/nginx_fdfs/conf/nginx.conf  -t

/usr/local/nginx_fdfs/sbin/nginx -c /usr/local/nginx_fdfs/conf/nginx.conf

# 保險起見,查看nginx是否啟動成功
ps -ef | grep nginx

image

image

  • 註意:這裡很容易出現啟動不起來,如果下麵這個進程沒有啟動起來
nobody    3895  3894  0 15:45 ?        00:00:00 nginx: worker process

  • 那麼:就去查看日誌文件
cd /usr/local/nginx_fdfs/logs


# 還有一份日誌中也可能出現錯誤信息
cd /opt/fastdfs/nginx_mod

image

image



2.4、Java操作FastDFS

2.3.2、擴展模塊執行流程

  • 下麵這個流程很重要,涉及到另外更深入的知識( 如:集群部署FastDFS,本篇博客沒有說明集群部署,哪些就是固定命令和流程,百度複製粘貼修改即可 )

image



2.4.1、文件上傳

  • resources目錄下創建fastdfs.conf文件,並編寫如下內容:
tracker_server=伺服器ip:22122

  • 編寫文件上傳代碼
package com.zixieqing;

import org.csource.common.MyException;
import org.csource.fastdfs.*;

import java.io.IOException;

/**
 * @author : ZiXieQing
 * @version : V1.0.0
 * @className : UploadFile
 * @description : 該類功能 FastDFS文件上傳
 * @packageName : com.zixieqing
 */

public class UploadFile {

    public static void main(String[] args) {

        TrackerServer trackerServer = null;
        StorageServer storageServer = null;
        try {
            // 1、初始化配置文件
            ClientGlobal.init("fastdfs.conf");

            // 2、創建tracker客戶端
            TrackerClient trackerClient = new TrackerClient();
            // 3、獲取trackerServer
            trackerServer = trackerClient.getConnection();
            // 4、獲取storageServer
            storageServer = trackerClient.getStoreStorage(trackerServer);

            // 5、創建storage客戶端 - 這個對象就是用來上傳文件、下載文件、刪除文件的
            StorageClient storageClient = new StorageClient(trackerServer, storageServer);

            // 6、上傳文件
            /*
                這裡有兩個API需要瞭解
                    String[] upload_file(byte[] file_buff, int offset, int length, String file_ext_name, NameValuePair[] meta_list)
                    這個API常用來web中上傳文件的
                        參數1 file_buff、文件位元組
                        offset、length、從文件的那個位置開始上傳,截止位置
                        參數4 file_ext_name、文件尾碼
                        參數5 meta_list、文件的屬性文件

                    String[] upload_file(String local_filename, String file_ext_name, NameValuePair[] meta_list)
                    這個API是上傳本地文件的
                        參數1 local_filename、本地文件的絕對路徑
                        參數2 file_ext_name、文件尾碼名
                        參數3 meta_list、文件的屬性文件,linux1中的哪個meta data,一般都不傳

                上述這兩個API,註意返回值,這個String[] 很重要,就是涉及到linux中的那個組名group 和 遠程文件名remote_filename,這個group和remote_fileName一般是存在資料庫中的
             */
            String[] result = storageClient.upload_file("C:\\Users\\ZiXieQing\\Desktop\\圖庫\\19.jpg", "jpg", null);

            // 7、驗證一下
            for (String data : result) {
                System.out.println("data = " + data);
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (MyException e) {
            throw new RuntimeException(e);
        } finally {
            // 8、釋放資源
            if (storageServer != null) {
                try {
                    storageServer.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (trackerServer != null) {
                try {
                    trackerServer.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

image

  • 瀏覽器訪問

image



2.4.2、文件下載

  • 把前面的文件上傳代碼改一下即可,換成另一個API而已
package com.zixieqing;

import org.csource.common.MyException;
import org.csource.fastdfs.*;

import java.io.IOException;

/**
 * @author : ZiXieQing
 * @version : V1.0.0
 * @className : DownloadFile
 * @description : 該類功能 fastDFS文件下載
 * @packageName : com.zixieqing
 */

public class DownloadFile {

    public static void main(String[] args) {

        TrackerServer trackerServer = null;
        StorageServer storageServer = null;
        try {
            // 1、初始化配置文件
            ClientGlobal.init("fastdfs.conf");

            // 2、獲取tracker客戶端
            TrackerClient trackerClient = new TrackerClient();
            // 3、獲取trackerServer
            trackerServer = trackerClient.getConnection();
            // 4、獲取storageServer
            storageServer = trackerClient.getStoreStorage(trackerServer);

            // 5、創建storage客戶端
            StorageClient storageClient = new StorageClient(trackerServer, storageServer);

            // 6、下載文件
            /*
                這裡需要知道兩個API
                     byte[] download_file(String group_name, String remote_filename)
                     這個API常用於web操作

                    int download_file(String group_name, String remote_filename, String local_filename)
                    這個API是把文件下載到本地磁碟中
                    這個API的返回值結果很重要
             */
            String group = "group1";
            String remoteFileName = "M00/00/00/CgAAEGKYRg-AAIrWAAD8cA4U6dY771.jpg";
            // 存入本地磁碟路徑+存入磁碟的文件名
            String localFileName = "d:/靚妹.jpg";
            // 只有返回值是0才表示下載成功,否則只要是其他數字都是下載失敗( 其他數字有可能是組名錯了,遠程文件名錯了........
            int result = storageClient.download_file(group, remoteFileName, localFileName);

            // 7、驗證
            System.out.println("result = " + result);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (MyException e) {
            throw new RuntimeException(e);
        } finally {
            // 8、釋放資源
            if (storageServer != null) {
                try {
                    storageServer.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (trackerServer != null) {
                try {
                    trackerServer.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }

    }
}

image

image



2.4.3、文件刪除

package com.zixieqing;

import org.csource.common.MyException;
import org.csource.fastdfs.*;

import java.io.IOException;

/**
 * @author : ZiXieQing
 * @version : V1.0.0
 * @className : DeleteFile
 * @description : 該類功能 FastDFS刪除文件
 * @packageName : com.zixieqing
 */

public class DeleteFile {

    public static void main(String[] args) {

        TrackerServer trackerServer = null;
        StorageServer storageServer = null;
        try {
            // 1、初始化配置文件
            ClientGlobal.init("fastdfs.conf");

            // 2、獲取tracker客戶端
            TrackerClient trackerClient = new TrackerClient();
            // 3、獲取trackerServer
            trackerServer = trackerClient.getConnection();
            // 4、獲取storageServer
            storageServer = trackerClient.getStoreStorage(trackerServer);
            // 5、獲取storage客戶端
            StorageClient storageClient = new StorageClient(trackerServer, storageServer);

            // 6、執行文件刪除
            /*
                int delete_file(String group_name, String remote_filename)
                參數1 group_name、組名
                參數2 remote_filename、遠程文件名
             */
            // 一樣的,返回值是0就表示成功,其他都是刪除失敗
            int result = storageClient.delete_file("group", "M00/00/00/CgAAEGKYRg-AAIrWAAD8cA4U6dY771.jpg");

            // 7、驗證一下
            System.out.println("result = " + result);

        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (MyException e) {
            throw new RuntimeException(e);
        }finally {
            // 8、釋放資源
            if (storageServer != null) {
                try {
                    storageServer.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (trackerServer != null) {
                try {
                    trackerServer.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 哈工大軟體構造Lab2中Assert的使用總結,可供後來學子借鑒學習 ...
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
  • 這是一個類似於記事本的文字處理器。與正常的記事本不同的是,它會將文本文檔進行加密,確保無法被常規的程式打開。 由於本人是一位業餘編程愛好者,對於“python之禪”之類的規則比較不以為然,因此本程式代碼也許有些許凌亂(當然不利於後期修改)。 這篇文章我早已發佈過,但當時只給出了代碼,並加了一些註釋。 ...
  • 最近在看 C++ 類繼承中的欄位記憶體佈局,我就很好奇 C# 中的繼承鏈那些 private 欄位都哪裡去了? 在記憶體中是如何佈局的,畢竟在子類中是無法訪問的。 一:舉例說明 為了方便講述,先上一個例子: internal class Program { static void Main(string ...
  • du Linux du (英文全拼:disk usage)命令用於顯示目錄或文件的大小。 du 會顯示指定的目錄或文件所占用的磁碟空間。 du命令作用是估計文件系統的磁碟已使用量,常用於查看文件或目錄所占磁碟容量。 du命令與df命令不同,df命令是統計磁碟使用情況,詳見linux命令詳解之df命令 ...
  • 英文原文:https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cgroups.html 1 控制組 1.1 什麼是控制組? 控制組(Control Group)提供一種機制,把一組任務(task)及其子任務整合/分割成具有特殊行為 ...
  • 一、存儲過程簡介 • 存儲過程(Stored Procedure)是一組為了完成特定功能的PL/SQL語句塊,經編譯後存儲在資料庫中。 • 存儲過程經編譯和SQL優化後存儲在資料庫伺服器中,使用時只要調用即可。 • 存儲過程是資料庫中的一個重要對象,任何一個設計良好的資料庫應用程式都應該用到存儲過程 ...
  • 一、概念 • REF游標和游標變數用於處理運行時動態執行的SQL查詢的結果集。 • 創建游標變數有兩個步驟: • 聲明REF游標類型 • 聲明REF游標類型的游標變數 • 聲明REF游標的語法: type 游標類型名 is ref cursor [return 返回值類型] 二、區別 • 靜態游標和 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...