一、FastDFS概述:
FastDFS是一個開源的輕量級分布式文件系統,他對文件進行管理,功能包括:文件存儲、文件同步、文件訪問(文件上傳、下載)等,解決了大容量存儲和負載均衡的問題,高度追求高性能和擴展性。特別適合以文件為載體的在線服務,如相冊萬盞、視頻網站等等。
FastDFS是由純C語言實現,支持Linux,FreeBSD的NUIX系統。類google FS,不是通用的文件系統,只能夠同故宮轉悠API進行訪問,目前提供了C,Java,PHP API。另外,FastDFS可以看作是基於文件的key-Value存儲系統,也可以稱之為 分布式文件存儲服務。
二、FastDFS提供的功能:
1、upload 上傳文件
2、upload_appender:上傳appender文件,后續可已對其進行append操作
3、upload_slave:上傳從文件
4、download 下載文件
5、delete 刪除文件
6、append:在已有文件后追加內容
7、set_metadata:設置文件附加屬性
8、get_metadata:獲取文件附加屬性
三、FastDFS的特點:
1、分組存儲、靈活簡潔
2、對等結構、不存在單點
3、文件ID有FastDFS生成,作為文件訪問憑證。FastDFS不需要傳統的name server
4、和流行的web server無縫連接,FastDFS已提供apache和nginx擴展模塊
5、大、中、小文件均可以很好支持,支持海量小文件存儲
6、支持多塊磁盤,支持但盤數據恢復
7、支持相同文件內容只保存一份,節省存儲空間
8、存儲服務器上可以保存文件附加屬性
9、下載文件支持多線程方式、支持斷點續傳
四、FastDFS架構解讀:
1、只有兩個角色,tracker server和storage server,不需要存儲文件索引信息
2、所有服務器都是對等的,不存在Master-Slave關系
3、存儲服務器采用分組方式,同組內存儲服務器上的文件完全相同
4、不同組的storage server之間不會相互通信
5、不同組的storage server之間不會相互通信
6、有storage server主動向tracker server報告狀態信息,tracker server 之間通常不會相互通信
五、FastDFS如何解決同步延遲問題?
1、storage生成的文件名中,包含源頭storage IP地址和文件創建的時間戳
2、源頭storage定時向tracker報告同步情況,包括向目標服務器同步到的文件時間戳
3、tracker收到storage的同步報告后,找出該組內每台storage被同步到的時間戳(取最小值),作為storage屬性保存到內存中
六、FastDFS擴展模塊要點:
1、使用擴展模塊來解決文件同步延遲問題
2、對每台storage server上部署web server,直接對外提供HTTP服務
3、tracker server上不需要部署web server
4、如果請求文件在當前storage上不存在,通過文件ID反解出源storage,直接請求源storage
5、目前已提供apache和nginx擴展模塊
6、FastDFS擴展模塊不依賴於FastDFS server,可以獨立存在
七、FastDFS擴展模塊特性:
1、僅支持HTTP HEAD和GET
2、支持token方式的防盜鏈(缺省是關閉的)
-ts:生成token的時間(unix時間戳)
-token:32未得token字符串(md5簽名)
3、支持制定保存的缺省文件名,URL參數名為filename
4、支持斷點續傳
FastDFS使用流程介紹:


三、實現流程:
1、配置依賴:因為我們使用的maven來管理工程,所以,我們需要去陪pom文件
<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>com.leech</groupId> <artifactId>fastdfs-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>fastdfs-demo</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.csource</groupId> <artifactId>fastdfs-client-java</artifactId> <version>1.25</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> </dependencies> </project>
2、新建fdfs_client.conf文件,在我們的itoo中,我們建立在(src/main/resources底下)
connect_timeout = 2
network_timeout = 30
charset = UTF-8
http.tracker_http_port = 80
#沒什么用
http.anti_steal_token = no
http.secret_key = FastDFS1234567890
tracker_server = 192.168.17.112:22122
#tracker_server = 192.168.0.119:22122
3、實現文件上傳:
public void save(HttpServletRequest request,HttpServletResponse response){ String videoName=request.getParameter("videoName"); String videoType=request.getParameter("videoType"); String videoDesc=request.getParameter("videoDesc"); String videoPath=request.getParameter("videoPath"); String picturePath=request.getParameter("picturePath"); SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date uploadTime=null; try { uploadTime = formatter.parse(formatter.format(new Date())); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } JacksonJsonUntil jackJsonUtil =new JacksonJsonUntil (); String dataBaseName = "itoo_video"; Video video=new Video(); video.setUserName("why"); video.setUserID("why"); video.setVideoName(videoName); video.setVideoPath(videoPath); video.setVideoType(videoType); video.setVideoDesc(videoDesc); video.setDataBaseName(dataBaseName); video.setPicturePath(picturePath); video.setUploadTime(uploadTime); uploadFileService.save(video); jackJsonUtil.beanToJson(response,video); } /* * 上傳文件 */ @RequestMapping(value={"/upload"}) @ResponseBody public void upload( MultipartFile file, HttpServletRequest request,HttpServletResponse response){ String ext_Name = file.getOriginalFilename().split("\\.")[1]; String videoName=file.getOriginalFilename().split("\\.")[0]; byte[] bytes = null; try { bytes = file.getBytes(); } catch (IOException e) { e.printStackTrace(); } String videoPath=uploadFile(bytes,ext_Name); JacksonJsonUntil jackJsonUtil =new JacksonJsonUntil (); Video video=new Video(); video.setVideoPath(videoPath); video.setVideoName(videoName); jackJsonUtil.beanToJson(response,video); } public String uploadFile(byte[] byteFile, String ext_file) { // 拼接服務區的文件路徑 StringBuffer sbPath = new StringBuffer(); sbPath.append("http://192.168.22.252"); try { // 初始化文件資源 ClientGlobal .init("C:\\Users\\alsr\\Desktop\\ITOO-5.0\\itoo-video-Test\\dmsd-itoo-video-parent\\dmsd-itoo-video-web\\src\\main\\resources\\fdfs_client.conf"); // 鏈接FastDFS服務器,創建tracker和Stroage TrackerClient trackerClient = new TrackerClient(); TrackerServer trackerServer = trackerClient.getConnection(); StorageServer storageServer = null; StorageClient storageClient = new StorageClient(trackerServer, storageServer); //利用字節流上傳文件 String[] strings = storageClient.upload_file(byteFile, ext_file, null); for (String string : strings) { sbPath.append("/" + string); System.out.println(string); } // 全路徑 System.out.println(sbPath); } catch (IOException | MyException e) { e.printStackTrace(); } return sbPath.toString(); }
只要我們能正常接收到一個json類型的字符串(url地址),就證明我們已經上傳成功了,如果不信,可以直接用瀏覽器去驗證一下,看看能不能得到文件展示。
4、FastDFS實現文件下載:
public void testDownload() { try { ClientGlobal.init(conf_filename); TrackerClient tracker = new TrackerClient(); TrackerServer trackerServer = tracker.getConnection(); StorageServer storageServer = null; StorageClient storageClient = new StorageClient(trackerServer, storageServer); byte[] b = storageClient.download_file("group1", "M00/00/00/wKgRcFV_08OAK_KCAAAA5fm_sy874.conf"); System.out.println(b); IOUtils.write(b, new FileOutputStream("D:/"+UUID.randomUUID().toString()+".conf")); } catch (Exception e) { e.printStackTrace(); } }
5、FastDFS獲取將上傳文件信息:
public void testGetFileInfo(){ try { ClientGlobal.init(conf_filename); TrackerClient tracker = new TrackerClient(); TrackerServer trackerServer = tracker.getConnection(); StorageServer storageServer = null; StorageClient storageClient = new StorageClient(trackerServer, storageServer); FileInfo fi = storageClient.get_file_info("group1", "M00/00/00/wKgRcFV_08OAK_KCAAAA5fm_sy874.conf"); System.out.println(fi.getSourceIpAddr()); System.out.println(fi.getFileSize()); System.out.println(fi.getCreateTimestamp()); System.out.println(fi.getCrc32()); } catch (Exception e) { e.printStackTrace(); } }
6、FastDFS獲取文件名稱:
public void testGetFileMate(){ try { ClientGlobal.init(conf_filename); TrackerClient tracker = new TrackerClient(); TrackerServer trackerServer = tracker.getConnection(); StorageServer storageServer = null; StorageClient storageClient = new StorageClient(trackerServer, storageServer); NameValuePair nvps [] = storageClient.get_metadata("group1", "M00/00/00/wKgRcFV_08OAK_KCAAAA5fm_sy874.conf"); for(NameValuePair nvp : nvps){ System.out.println(nvp.getName() + ":" + nvp.getValue()); } } catch (Exception e) { e.printStackTrace(); } }
7、FastDFS實現刪除文件:
public void testDelete(){ try { ClientGlobal.init(conf_filename); TrackerClient tracker = new TrackerClient(); TrackerServer trackerServer = tracker.getConnection(); StorageServer storageServer = null; StorageClient storageClient = new StorageClient(trackerServer,storageServer); int i = storageClient.delete_file("group1", "M00/00/00/wKgRcFV_08OAK_KCAAAA5fm_sy874.conf"); System.out.println( i==0 ? "刪除成功" : "刪除失敗:"+i); } catch (Exception e) { e.printStackTrace(); } }
