學成在線(第8天)

FastDFS 研究

 什麼是分佈式文件系統

什麼是文件系統

文件系統是負責管理和存儲文件的系統軟件,它是操做系統和硬件驅動之間的橋樑,操做系統經過文件系統
提供的接口去存取文件,用戶經過操做系統訪問磁盤上的文件。以下圖:html

 什麼是分佈式文件系統

爲何會有分佈文件系統呢?
分佈式文件系統是面對互聯網的需求而產生,互聯網時代對海量數據如何存儲?靠簡單的增長硬盤的個數已經知足
不了咱們的要求,由於硬盤傳輸速度有限可是數據在急劇增加,另外咱們還要要作好數據備份、數據安全等。
採用分佈式文件系統能夠將多個地點的文件系統經過網絡鏈接起來,組成一個文件系統網絡,結點之間經過網絡進
行通訊,一臺文件系統的存儲和傳輸能力有限,咱們讓文件在多臺計算機上存儲,經過多臺計算共同傳輸。以下
圖:前端

好處:
一、一臺計算機的文件系統處理能力擴充到多臺計算機同時處理。
二、一臺計算機掛了還有另外副本計算機提供數據。
三、每臺計算機能夠放在不一樣的地域,這樣用戶就能夠就近訪問,提升訪問速度。nginx

 什麼是fastDFS

FastDFS是用c語言編寫的一款開源的分佈式文件系統,它是由淘寶資深架構師餘慶編寫並開源。FastDFS專爲互聯
網量身定製,充分考慮了冗餘備份、負載均衡、線性擴容等機制,並注重高可用、高性能等指標,使用FastDFS很
容易搭建一套高性能的文件服務器集羣提供文件上傳、下載等服務。
爲何要使用fastDFS呢?
上邊介紹的NFS、GFS都是通用的分佈式文件系統,通用的分佈式文件系統的優勢的是開發體驗好,可是系統複雜
性高、性能通常,而專用的分佈式文件系統雖然開發體驗性差,可是系統複雜性低而且性能高。fastDFS很是適合
存儲圖片等那些小文件,fastDFS不對文件進行分塊,因此它就沒有分塊合併的開銷,fastDFS網絡通訊採用
socket,通訊速度很快。c++

fastDSF 架構

FastDFS架構包括 Tracker server和Storageserver。客戶端請求Tracker server進行文件上傳、下載,經過Tracker
server調度最終由Storage server完成文件上傳和下載。數據庫

1)Tracker

Tracker Server做用是負載均衡和調度,經過Tracker server在文件上傳時能夠根據一些策略找到Storage server提
供文件上傳服務。能夠將tracker稱爲追蹤服務器或調度服務器。
FastDFS集羣中的Tracker server能夠有多臺,Tracker server之間是相互平等關係同時提供服務,Tracker server
不存在單點故障。客戶端請求Tracker server採用輪詢方式,若是請求的tracker沒法提供服務則換另外一個tracker。json

2)Storage

Storage Server做用是文件存儲,客戶端上傳的文件最終存儲在Storage服務器上,Storage server沒有實現本身
的文件系統而是使用操做系統的文件系統來管理文件。能夠將storage稱爲存儲服務器。api

Storage集羣採用了分組存儲方式。storage集羣由一個或多個組構成,集羣存儲總容量爲集羣中全部組的存儲容
量之和。一個組由一臺或多臺存儲服務器組成,組內的Storage server之間是平等關係,不一樣組的Storage server
之間不會相互通訊,同組內的Storage server之間會相互鏈接進行文件同步,從而保證同組內每一個storage上的文件
徹底一致的。一個組的存儲容量爲該組內的存儲服務器容量最小的那個,因而可知組內存儲服務器的軟硬件配置最
好是一致的。
採用分組存儲方式的好處是靈活、可控性較強。好比上傳文件時,能夠由客戶端直接指定上傳到的組也能夠由
tracker進行調度選擇。一個分組的存儲服務器訪問壓力較大時,能夠在該組增長存儲服務器來擴充服務能力(縱向
擴容)。當系統容量不足時,能夠增長組來擴充存儲容量(橫向擴容)。瀏覽器

3)Storage狀態收集

Storage server會鏈接集羣中全部的Tracker server,定時向他們報告本身的狀態,包括磁盤剩餘空間、文件同步
情況、文件上傳下載次數等統計信息。安全

文件上傳流程

客戶端上傳文件後存儲服務器將 文件ID 返回給客戶端,此文件ID用於之後訪問該文件的索引信息。文件索引信息
包括:組名,虛擬磁盤路徑,數據兩級目錄,文件名。服務器

  • 組名:文件上傳後所在的 storage組名稱,在文件上傳成功後有 storage服務器返回,須要客戶端自行保存。
  • 虛擬磁盤路徑: storage配置的虛擬路徑,與磁盤選項 store_path* 對應。若是配置了store_path0則是M00,若是配置了store_path1則是M01,以此類推。
  • 數據兩級目錄: storage服務器在每一個虛擬磁盤路徑下建立的兩級目錄,用於存儲數據文件。
  • 文件名:與文件上傳時不一樣。是由存儲服務器根據特定信息生成,文件名包含:源存儲服務器 IP地址、文件建立時間戳、文件大小、隨機數和文件拓展名等信息。

文件下載流程

tracker根據請求的文件路徑即文件ID 來快速定義文件。
好比請求下邊的文件:

1.經過組名tracker可以很快的定位到客戶端須要訪問的存儲服務器組是group1,並選擇合適的存儲服務器提供客
戶端訪問。
2.存儲服務器根據「文件存儲虛擬磁盤路徑」和「數據文件兩級目錄」能夠很快定位到文件所在目錄,並根據文件名找到
客戶端須要訪問的文件。

FastDFS環境搭建

關於FastDfs的搭建過程,我這裏就不寫出來了,我第一次也是專研一下午才弄明白。下面也把搭建好的成品Centos7分享出來,包括nginx的環境搭建。

fastDFS安裝時,./make.sh編譯時出錯---perl:未找到命令

作fastDFS的案例的時候,在搭建分佈式集羣的模塊的時候,使用 ./make.sh 編譯的時候報錯,錯誤以下:

錯誤緣由:在執行make.sh的時候沒有找到相應的命令

解決辦法:安裝相應的命令便可。執行如下命令

yum -y install zlib zlib-devel pcre pcre-devel gcc gcc-c++ openssl openssl-devel libevent libevent-devel perl unzip net-tools wget  

Centos7成品:

連接:https://pan.baidu.com/s/1-yxZ_SHoq5k9BymaosTU-w 
提取碼:89ho

具體搭建過程徹底按照這篇博客完成的

http://www.javashuo.com/article/p-uxmxtatc-mx.html

感興趣的能夠試着作作。

另外,使用我搭建好的Centos7有幾個地方須要注意一下

配置和啓動storage

  1. cd切換目錄到: /etc/fdfs/ 目錄下
  2. 修改storage.conf ;   vi  storage.conf
#配置tracker服務器:IP
tracker_server=192.168.172.20:22122
#若是有多個則配置多個tracker
#tracker_server=192.168.101.4:22122
這裏的storage.conf配置文件要成本身虛擬機的ip地址

    3. vi /etc/fdfs/mod_fastdfs.conf,改爲虛擬機ip地址(同上)

base_path=/home/fastdfs
tracker_server=192.168.172.20:22122 
#tracker_server=192.168.172.20:22122 #(多個tracker配置多行)
url_have_group_name=true        #url中包含group名稱
store_path0=/home/fdfs_storage  #指定文件存儲路徑(上面配置的store路徑)

    4.修改nginx配置文件,改iP地址(同上)

cd /usr/local/nginx/conf/
vi nginx.conf

 

個人Centos7默認配置tracker,storage和nginx默認開機自動啓動了

能夠啓動完成後進入 /home/fdfs_storage/data 目錄下,能夠看到已經啓動了。

 nginx能夠經過ps -ef | grep nginx查看進程,

 上傳圖片測試

拷貝一張圖片1.jpg 到Centos服務器上的 root目錄下,輸入如下指令

/usr/bin/fdfs_test /etc/fdfs/client.conf upload /root/1.jpg

 紅色既是url地址,在瀏覽器上輸入,能夠看到上傳圖片成功!!

 有問題的能夠查看上面一篇博客,詳解。

 上傳圖片開發

需求分析

在不少系統都有上傳圖片/上傳文件的需求,好比:上傳課程圖片、上傳課程資料、上傳用戶頭像等,爲了提供系
統的可重用性專門設立文件系統服務承擔圖片/文件的管理,文件系統服務實現對文件的上傳、刪除、查詢等功能
進行管理。
各各子系統再也不開發上傳文件的請求,各各子系統經過文件系統服務進行文件的上傳、刪除等操做。文件系統服務
最終會將文件存儲到fastDSF文件系統中。
下圖是各各子系統與文件系統服務之間的關係:

 

 下圖是課程管理中上傳圖片處理流程:

 

執行流程以下:
一、管理員進入教學管理前端,點擊上傳圖片
二、圖片上傳至文件系統服務,文件系統請求fastDFS上傳文件
三、文件系統將文件入庫,存儲到文件系統服務數據庫中。
四、文件系統服務向前端返回文件上傳結果,若是成功則包括文件的Url路徑。
五、課程管理前端請求課程管理進行保存課程圖片信息到課程數據庫。
六、課程管理服務將課程圖片保存在課程數據庫。

Api接口

在api工程下建立com.xuecheng.api.filesystem包,

public interface FileSystemControllerApi {
  
    /**
     * 上傳文件
     * @param multipartFile 文件
     * @param filetag 文件標籤
     * @param businesskey 業務key
     * @param metedata 元信息,json格式
     * @return
     */
    public UploadFileResult upload(MultipartFile multipartFile,
                    String filetag,
                    String businesskey,
                    String metadata);
} 

Dao

將文件信息存入數據庫,主要存儲文件系統中的文件路徑。

public interface FileSystemRepository extends MongoRepository<FileSystem,String> {
}

Service

@Service
public class FileSystemService {
    private static final Logger LOGGER = LoggerFactory.getLogger(FileSystemService.class);
    @Value("${xuecheng.fastdfs.tracker_servers}")
    String tracker_servers;
    @Value("${xuecheng.fastdfs.connect_timeout_in_seconds}")
    int connect_timeout_in_seconds;
    @Value("${xuecheng.fastdfs.network_timeout_in_seconds}")
    int network_timeout_in_seconds;
    @Value("${xuecheng.fastdfs.charset}")
    String charset;
    @Autowired
    FileSystemRepository fileSystemRepository;
    //加載fdfs的配置
    private void initFdfsConfig(){
        try {
            ClientGlobal.initByTrackers(tracker_servers);
            ClientGlobal.setG_connect_timeout(connect_timeout_in_seconds);
            ClientGlobal.setG_network_timeout(network_timeout_in_seconds);
            ClientGlobal.setG_charset(charset);
        } catch (Exception e) {
            e.printStackTrace();
            //初始化文件系統出錯
            ExceptionCast.cast(FileSystemCode.FS_INITFDFSERROR);
        }
    }
    //上傳文件
    public UploadFileResult upload(MultipartFile file,
                                   String filetag,
                                   String businesskey,
                                   String metadata){
        if(file == null){
            ExceptionCast.cast(FileSystemCode.FS_UPLOADFILE_FILEISNULL);
        }
        //上傳文件到fdfs
北京市昌平區建材城西路金燕龍辦公樓一層 電話:400-618-9090
        String fileId = fdfs_upload(file);
        //建立文件信息對象
        FileSystem fileSystem = new FileSystem();
        //文件id
        fileSystem.setFileId(fileId);
        //文件在文件系統中的路徑
        fileSystem.setFilePath(fileId);
        //業務標識
        fileSystem.setBusinesskey(businesskey);
        //標籤
        fileSystem.setFiletag(filetag);
        //元數據
        if(StringUtils.isNotEmpty(metadata)){
            try {
                Map map = JSON.parseObject(metadata, Map.class);
                fileSystem.setMetadata(map);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //名稱
        fileSystem.setFileName(file.getOriginalFilename());
        //大小
        fileSystem.setFileSize(file.getSize());
        //文件類型
        fileSystem.setFileType(file.getContentType());
        fileSystemRepository.save(fileSystem);
        return new UploadFileResult(CommonCode.SUCCESS,fileSystem);
    }
    //上傳文件到fdfs,返回文件id
    public String fdfs_upload(MultipartFile file) {
        try {
            //加載fdfs的配置
            initFdfsConfig();
            //建立tracker client
            TrackerClient trackerClient = new TrackerClient();
            //獲取trackerServer
            TrackerServer trackerServer = trackerClient.getConnection();
            //獲取storage
            StorageServer storeStorage = trackerClient.getStoreStorage(trackerServer);
            //建立storage client
            StorageClient1 storageClient1 = new StorageClient1(trackerServer,storeStorage);
            //上傳文件
            //文件字節
            byte[] bytes = file.getBytes();
            //文件原始名稱
            String originalFilename = file.getOriginalFilename();
            //文件擴展名
            String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
            //文件id
            String file1 = storageClient1.upload_file1(bytes, extName, null);

            return file1;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
View Code

Controller

@RestController
@RequestMapping("/filesystem")
public class FileSystemController implements FileSystemControllerApi {
    @Autowired
    FileSystemService fileSystemService;
    @Override
    @PostMapping("/upload")
    public UploadFileResult upload(@RequestParam("file") MultipartFile file,
                                   @RequestParam(value = "filetag", required = true) String
filetag,
                                   @RequestParam(value = "businesskey", required = false) String
businesskey,
                                   @RequestParam(value = "metedata", required = false) String
metadata) {
        return fileSystemService.upload(file,filetag,businesskey,metadata);
    }
}
View Code

測試

使用swagger-ui或postman進行測試。
下圖是使用swagger-ui進行測試的界面:

 

 

 

 

 

 

 

 

相關文章
相關標籤/搜索