網頁右邊,向下滑有目錄索引,可以根據标題跳轉到你想看的内容 |
如果右邊沒有就找找左邊 |
- 通用分布式檔案系統
和傳統的本地檔案系統(ext3,NTFS等)相對應。典型代表Iustre、MooseFS - 優點:表中檔案系統操作方式,對開發者門檻較低
- 缺點:系統複雜性較高,需要支援若幹标準的檔案操作,如:目錄結構、檔案讀寫權限、檔案鎖等。複雜性更高,系統整體性能有所降低,因為要支援POSIX标準(表示可移植作業系統接口,POSIX标準定義了作業系統應該為應用程式提供的接口标準)
- 專用分布式檔案系統
基于google File System的思想,檔案上傳後不能修改。需要使用專有API對檔案進行通路,也可稱作分布式檔案存儲服務。典型代表:MogileFS、FastDFS、TFS。 - 優點:系統複雜性較低,不需要支援若幹标準的檔案操作,如:目錄結構、檔案讀寫權限、檔案鎖等,系統比較簡潔。系統整體性能較高,因為無需支援POSIX标準,可以省去支援POSIX引入的環節,系統更加高效
- 缺點:采用專用API,對開發者門檻較高(直接封裝成工具類)
- 兩個角色
- 名字伺服器(索引伺服器)
- 存儲伺服器
- 架構特點
- 不支援檔案修改功能
- 檔案分塊存儲,需要索引伺服器
- 一個檔案可以存儲多份,一個檔案存儲到哪些存儲伺服器,通常采用動态配置設定的方式
- FastDFS是一個輕量級的開源分布式檔案系統。2008年4月份開始啟動。類似google FS的一個輕量級分布式檔案系統,存C語言實作,支援Linux、FreeBSD、AIX等UNIX系統
- 主要解決了大容量的檔案存儲和高并發通路的問題,檔案存取時實作了負載均衡。實作了軟體方式的磁盤陣列(RAID),可以使用廉價IDE硬碟進行存儲。并且支援存儲伺服器線上擴容。支援相同内容的檔案隻儲存一份,節約磁盤空間。
- FastDFS隻能通過ClientAPI通路,不支援POSIX通路方式。
- FastDFS特别适合大中型網站使用,用來存儲資源檔案(如:圖檔、文檔、音頻、視訊等等)
- FastDFS沒有官網,但是作者happy_fish100餘慶擔任chinaunix中FastDFS闆塊版主。并且會不定期更新闆塊中内容。http://bbs.chinaunix.net
- FastDFS軟體可以在sourceforge中下載下傳https://sourceforge.net/projects/fastdfs/files/(不推薦使用這種下載下傳方式,具體下載下傳請看下面環境搭建内容)
- Client:用戶端。使用java語言編寫的項目屬于用戶端
- Tracker Server:跟蹤伺服器,主要做排程工作,在通路上起均衡負載的作用。在記憶體中記錄叢集中group和storage server的狀态資訊,是連接配接Client和Storage server的樞紐
- Storage Server:存儲伺服器,檔案和檔案屬性(meta data)都儲存到存儲伺服器上,按組group存儲,就是上圖白色的框框,有若幹組,不同組之間不會互相通信
- 架構解讀
- 隻有兩個角色,tracker server和storage server,不需要存儲檔案索引資訊。
- 所有伺服器都是對等的,不存在Master-Slave關系。
- 不同組中storage server之間不會相信通信。
- 由storage server主動向tracker server報告狀态,tracker server之間不會互相通信。
一、環境搭建
- libfastcommon 下載下傳位址: https://github.com/happyfish100/libfastcommon/releases
- libfastcommon是FastDFS官方提供的,libfastcommon包含了FastDFS運作所需要的一些c語言基礎庫
- FastDFS 下載下傳位址 https://github.com/happyfish100/fastdfs/releases
注意:請大家下載下傳6.4以上版本,推薦6.4,因為和nginx做整合時,低版本會發生沖突問題
- 打開Linux,安裝c語言環境,不會Linux請參考文章https://blog.csdn.net/grd_java/article/details/115676099
FastDFS 是C語言開發的應用。安裝必須使用make,cmake和gcc編譯器
//安裝
yum install -y make cmake gcc gcc-c++
- 安裝libfastcommon
- 将兩個包傳過去
- 解壓
- 編譯
- 執行安裝(有固定的預設安裝位置。在/usr/lib64和/usr/include/fastcommon兩個目錄中)
- 建立軟連接配接(因為FastDFS主程式設定的lib目錄是/usr/local/lib是以需要建立軟連接配接,就是快捷方式)
ln -s /usr/lib64/libfastcommon.so /usr/local/lib/libfastcommon.so
ln -s /usr/local/lib64/libfdfsclient.so /usr/local/lib/libfdfsclient.so
- 解壓FastDFS
- 檔案解析
- 配置tracker
- 複制配置檔案(進入/etc/fdfs中,把tracker配置檔案複制一份)
cp tracker.conf.sample tracker.conf
- 建立資料目錄(建立放置tracker資料的目錄)
mkdir -p /usr/local/fastdfs/tracker
- 修改配置檔案(修改tracker.conf設定tracker内容存儲目錄)
- 啟動服務(啟動成功後,配置檔案中指定的目錄出現data目錄和logs目錄)
service fdfs_trackerd start
- 檢視服務運作狀态
service fdfs_trackerd status
- 配置storage(可以和tracker不在同一台伺服器)
- 複制配置檔案(進入/etc/fdfs,把storage配置檔案複制一份)
[root@hadoop105 tracker]# cd /etc/fdfs/
[root@hadoop105 fdfs]# cp storage.conf.sample storage.conf
- 建立目錄(建立兩個,base用于存儲基礎資料和日志,store用于存儲上傳資料)
[root@hadoop105 fdfs]# mkdir -p /user/local/fastdfs/storage/base
[root@hadoop105 fdfs]# mkdir -p /user/local/fastdfs/storage/store
- 修改配置檔案(storage.conf配置檔案用于描述存儲服務的行為,需要進行如下修改)
[root@hadoop105 fdfs]# vim /etc/fdfs/storage.conf
# 基礎路徑,用于儲存storage server基礎資料内容和日志内容的目錄
base_path=/user/local/fastdfs/storage/base
#存儲路徑,用于儲存FastDFS中存儲檔案的目錄,就是要建立256*256個子目錄位
store_path0=/user/local/fastdfs/storage/store
# tracker服務的ip和端口,注意ip寫你自己虛拟機或伺服器ip,22122是tracker的預設端口,可以在上面tracker.conf檔案中配置
tracker_server=192.168.10.105:22122
- 啟動(成功後,指定目錄出現data和logs,path0指定目錄,隻出現data,第一次啟動需要建立256*256子目錄,會比較慢)
[root@hadoop105 fdfs]# service fdfs_storaged start
[root@hadoop105 fdfs]# service fdfs_storaged status
二、檔案上傳
- 用戶端通路Tracker
- Tracker傳回Storage的ip和端口
- 用戶端直接通路Storage,把檔案内容和中繼資料發送過去
- Storage傳回檔案存儲id,包含了組名和檔案名
- 建立maven項目添加依賴
<dependencies>
<!--這個依賴,作者沒有寫,是以很多人提供了很多版本,内容都一樣,如果這個失效,請去maven倉庫換一個fastdfs-client-java-->
<dependency>
<groupId>net.oschina.zcx7878</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
</dependencies>
- 編寫配置檔案
connect_timeout = 10
network_timeout = 30
charset = UTF-8
http.tracker_http_port = 8080
tracker_server = 192.168.10.105:22122
- 工具類
import org.apache.commons.lang3.StringUtils;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import java.io.*;
/**
* FastDFS 分布式檔案系統操作用戶端
*/
public class FastDFSClient {
private static final String CONF_FILENAME=Thread.currentThread().getContextClassLoader().getResource("").getPath()+"fdfs_client.conf";
private static StorageClient storageClient = null;
/**
* 隻加載一次
*/
static{
try {
ClientGlobal.init(CONF_FILENAME);
TrackerClient trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
TrackerServer trackerServer = trackerClient.getConnection();
StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
storageClient = new StorageClient(trackerServer,storageServer);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String[] uploadFile(InputStream inputStream,String fileName){
try {
//檔案的中繼資料
NameValuePair[] meta_list = new NameValuePair[2];
//第一組中繼資料,檔案的原始名稱
meta_list[0] = new NameValuePair("file name",fileName);
//第二組中繼資料
meta_list[1] = new NameValuePair("file length",inputStream.available()+"");
//準備位元組數組
byte[] file_buff = null;
if (inputStream != null){
//檢視檔案長度
int len = inputStream.available();
//建立對應長度的位元組數組
file_buff = new byte[len];
//将輸入流中的位元組内容,讀到位元組數組中
inputStream.read(file_buff);
}
//上傳檔案。參數含義:要上傳的檔案内容(使用位元組數組傳遞),上傳的檔案的類型(擴充名),中繼資料
String[] fileids = storageClient.upload_appender_file(file_buff,getFileExt(fileName),meta_list);
return fileids;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static String[] uploadFile(File file,String fileName){
FileInputStream fis = null;
try {
NameValuePair[] meta_list = null;
fis = new FileInputStream(file);
byte[] file_buff = null;
if(fis != null){
int len = fis.available();
file_buff = new byte[len];
fis.read(file_buff);
}
String[] fileids = storageClient.upload_file(file_buff,getFileExt(fileName),meta_list);
return fileids;
} catch (Exception e) {
e.printStackTrace();
return null;
}finally {
if(fis != null){
try{
fis.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
/**
* 根據組名和遠端檔案名來删除一個檔案
* @param groupName
* @param remoreFileName
* @return
*/
public static int deleteFile(String groupName,String remoreFileName){
try {
int result = storageClient.delete_file(groupName == null ? "group1" : groupName, remoreFileName);
return result;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 修改一個已經存在的檔案
* @param oldGroupName
* @param oldFileName
* @param file
* @param fileName
* @return
*/
public static String[] modifyFile(String oldGroupName,String oldFileName,File file,String fileName){
String[] fileids = null;
try{
//先上傳
fileids = uploadFile(file,fileName);
if(fileids == null){
return null;
}
//再删除
int delResult = deleteFile(oldGroupName,oldFileName);
if(delResult != 0){
return null;
}
}catch (Exception e){
return null;
}
return fileids;
}
/**
* 檔案下載下傳
* @param groupName
* @param remoteFileName
* @return
*/
public static InputStream downloadFile(String groupName,String remoteFileName){
try{
byte[] bytes = storageClient.download_file(groupName, remoteFileName);
InputStream inputStream = new ByteArrayInputStream(bytes);
return inputStream;
}catch (Exception e) {
return null;
}
}
public static NameValuePair[] getMetaDate(String groupName,String remoteFileName){
try{
NameValuePair[] nvp = storageClient.get_metadata(groupName, remoteFileName);
return nvp;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
/**
* 擷取檔案字尾名,不帶點
*/
private static String getFileExt(String fileName){
if(StringUtils.isBlank(fileName)||!fileName.contains(".")){
return "";
}else{
return fileName.substring(fileName.lastIndexOf(".")+1);//不帶最後的點
}
}
}
- 編寫用戶端代碼,上傳一張圖檔測試(上傳後的檔案名,是FastDFS自動生成,和我們代碼設定的檔案名沒啥關系)
import com.yzpnb.utils.FastDFSClient;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.UUID;
public class MyClient {
public static void main(String[] args) {
try{
File file = new File("D:/a.jpg");
InputStream inputStream = new FileInputStream(file);
String fileName = UUID.randomUUID().toString()+ ".jpg";
String[] result = FastDFSClient.uploadFile(inputStream, fileName);
System.out.println(Arrays.toString(result));
}catch (Exception e){
e.printStackTrace();
}
}
}
三、下載下傳
- 編寫代碼并運作
import com.yzpnb.utils.FastDFSClient;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.UUID;
public class MyClient {
public static void main(String[] args) {
try{
//[group1, M00/00/00/wKgKaWENAOWEMeDCAAAAAOFj66Y127.jpg]下載下傳這張圖檔
InputStream is = FastDFSClient.downloadFile("group1", "M00/00/00/wKgKaWENAOWEMeDCAAAAAOFj66Y127.jpg");
FileOutputStream os = new FileOutputStream(new File("D:/b.jpg"));
int index = 0;
while((index = is.read())!=-1){
os.write(index);
}
os.flush();
os.close();
is.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
四、圖檔通路
- FastDFS沒有提供圖檔通路功能
- 是以我們需要使用代理來實作
- nginx提供的代理功能可以實作圖檔通路,但隻支援http請求代理(隻要支援http協定通路的内容,nginx都可以代理),當接受到外部http請求,傳回本地檔案資源給用戶端
- 我們需要借助nginx來實作,外部請求圖檔,把圖檔資訊響應給請求方
- 上傳到虛拟機并安裝:
- fastdfs-nginx-module子產品 :https://github.com/happyfish100/fastdfs-nginx-module
- nginx: http://nginx.org/en/download.html
- 上傳兩個檔案,解壓
- 修改fastdfs-nginx-module配置檔案,在檔案中src目錄下的config檔案,因為配置檔案中指定的是fastDFS核心代碼位置,我們需要指定
- 安裝nginx
- 安裝一些c++之類的運作庫
yum install -y gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel
- 修改配置檔案之前,建立一個目錄(修改配置檔案中好多位置都使用了/var/temp/nginx目錄,我們需要手動建立這個目錄)
- 給nginx權重限
- 進入nginx目錄,添加配置(
你需要修改最後一行,指定路徑到你安裝fastdfs-nginx-module的src路徑
)
./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/local/nginx/nginx.pid \
--lock-path=/var/lock/nginx/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--http-scgi-temp-path=/var/temp/nginx/scgi \
--add-module=/opt/module/fastdfs-nginx-module-master/src
- 編譯并安裝(在nginx目錄下,執行make指令編譯安裝,make install運作)
- 複制fastdfs-nginx-module/src/mod-fastdfs.conf配置檔案到/etc/fdfs目錄,并修改它
connect_timeout=10 # 連接配接逾時時間,機關秒
tracker_server=192.168.10.105:22122# tracker服務結點
url_have_group_name = true# URL是否包含group名稱
store_path0=/usr/loacl/fastdfs/storage/store#storage服務結點的存儲位置,配置與storage結點一緻
- 提供FastDFS需要的HTTP配置檔案(複制FastDFS安裝包中兩個配置檔案http.conf和mine.types到/etc/fdfs目錄中)
- 建立網絡通路存儲服務的軟連接配接(在上傳檔案到FastDFS後,FastDFS會傳回group1/M00/00/00/xxxxx/xx其中group1是卷名,在mod_fastdfs.conf配置檔案中已配置了url_have_group_name,以保證URL解析正确。其中的M00是FastDFS儲存資料時使用的虛拟目錄,需要将這個虛拟目錄定位到真實資料目錄上)
ln -s /usr/local/fastdfs/storage/store/data/ /usr/local/fastdfs/storage/store/data/M00
- 修改nginx配置檔案
- 啟動nginx
到此,已經可以通過http請求擷取資源了,之後會單獨寫一篇文章,使用圖檔通路功能,因為需要寫一個web項目來測試,日後有時間再補充 |