網站文件系統發展
1、單機時代的圖片服務器架構
初創時期由于時間緊迫,開發人員水平也很有限等原因。所以通常就直接在website文件所在的目錄下,建立1個upload子目錄,用于保存用戶上傳的圖片文件。如果按業務再細分,可以在upload目錄下再建立不同的子目錄來區分。例如:upload\QA,upload\Face等
優點:實現起來最簡單,無需任何復雜技術,就能成功將用戶上傳的文件寫入指定目錄。保存數據庫記錄和訪問起來倒是也很方便。
缺點:上傳方式混亂,嚴重不利于網站的擴展。
2、單獨立文件服務器
隨著公司的業務不斷的發展,將服務和文件放在同一服務器下面的弊端越來越明顯;這個時候就該上線獨立的圖片服務器系統;通過ftp或者ssh工具將文件上傳到圖片服務器的某個目錄下面,在通過ngnix或者apache服務器來做圖片的訪問,給圖片服務器配置獨立的子域名,例如 img.xx.com。在業務處理文件時通過ftp或者ssh將文件上傳到文件服務器,返回給程序一個獨立域名的圖片url地址,網站正常訪問的時候就通過這個URL地址來訪問文件。
優點:圖片訪問是很消耗服務器資源的(因為會涉及到操作系統的上下文切換和磁盤I/O操作)。分離出來后,Web/App服務器可以更專注發揮動態處理的能力;獨立存儲,更方便做擴容、容災和數據遷移;方便做圖片訪問請求的負載均衡,方便應用各種緩存策略(HTTP Header、Proxy Cache等),也更加方便遷移到CDN。
缺點:單機存在性能瓶頸,容災、垂直擴展性稍差
3、分布式文件系統
業務繼續發展,單獨單臺的服務器存儲和響應也很快到達了瓶頸,新的業務要求,文件訪問高響應性,高可用性來響應業務對系統的要求。分布式文件系統,一般分為三塊內容來配合,服務的存儲、訪問的仲裁系統,文件存儲系統,文件的容災系統來構成,總裁系統相當于文件服務器的大腦,根據一定的算法來決定文件存儲的位置,文件存儲系統負責報錯文件,容災系統負責文件系統和自己的相互備份。
優點:擴展能力: 毫無疑問,擴展能力是一個分布式文件系統最重要的特點;高可用性: 在分布式文件系統中,高可用性包含兩層,一是整個文件系統的可用性,二是數據的完整和一致性;彈性存儲: 可以根據業務需要靈活地增加或縮減數據存儲以及增刪存儲池中的資源,而不需要中斷系統運行
缺點:系統復雜度稍高,需要更多服務器
分布式文件系統fastDFS
1、什么是FastDFS
FastDFS是一個開源的輕量級分布式文件系統。它解決了大數據量存儲和負載均衡等問題。特別適合以中小文件(建議范圍:4KB < file_size <500MB)為載體的在線服務,如相冊網站、視頻網站等等。在UC基于FastDFS開發向用戶提供了:網盤,社區,廣告和應用下載等業務的存儲服務。
2、FastDFS架構和原理
FastDFS服務端有三個角色:跟蹤服務器(tracker server)、存儲服務器(storage server)和客戶端(client)。
tracker server:跟蹤服務器,主要做調度工作,起負載均衡的作用。在內存中記錄集群中所有存儲組和存儲服務器的狀態信息,是客戶端和數據服務器交互的樞紐。相比GFS中的master更為精簡,不記錄文件索引信息,占用的內存量很少。
storage server:存儲服務器(又稱:存儲節點或數據服務器),文件和文件屬性(meta data)都保存到存儲服務器上。Storage server直接利用OS的文件系統調用管理文件。
client:客戶端,作為業務請求的發起方,通過專有接口,使用TCP/IP協議與跟蹤器服務器或存儲節點進行數據交互。
Tracker相當于FastDFS的大腦,不論是上傳還是下載都是通過tracker來分配資源;客戶端一般可以使用ngnix等靜態服務器來調用或者做一部分的緩存;存儲服務器內部分為卷(或者叫做組),卷于卷之間是平行的關系,可以根據資源的時候情況隨時增加,卷內服務器文件相互同步備份,以達到容災的目的
上傳機制:
首先客戶端請求Tracker服務獲取到存儲服務器的ip地址和端口,然后客戶端根據返回的IP地址和端口號請求上傳文件,存儲服務器接收到請求后,生產文件file_id并且將文件內容寫入磁盤返回給客戶端file_id和路徑信息、文件名,客戶端保存相關信息上傳完畢
下載機制:
客戶端帶上文件名信息請求Tracker服務獲取到存儲服務器的ip地址和端口,然后客戶端根據返回的IP地址和端口號請求下載文件,存儲服務器接收到請求后返回文件給客戶端。
3、如何搭建fastDFS
請參考以下文章:
地址:http://www.linux178.com/storage/fastdfs-nginx-cache.html
4、使用java調用fastDFS
以下代碼是一個spring mvc中一個完整的上傳請求
@RequestMapping(value = "/upload", method = RequestMethod.POST) @ResponseBody public Object upload(@RequestParam MultipartFile file) { UploadResponse res = new UploadResponse(); try { if(file.isEmpty()){ res.setRet_code(UserCodeEnum.ERR_FILE_NULL.getCode()); res.setRet_msg(UserCodeEnum.ERR_FILE_NULL.getDesc()); }else{ logger.info("UserController-upload-request-file=" + file.getOriginalFilename()); String tempFileName = file.getOriginalFilename(); //fastDFS方式 ClassPathResource cpr = new ClassPathResource("fdfs_client.conf"); ClientGlobal.init(cpr.getClassLoader().getResource("fdfs_client.conf").getPath()); byte[] fileBuff = file.getBytes(); String fileId = ""; String fileExtName = tempFileName.substring(tempFileName.lastIndexOf(".")); //建立連接 TrackerClient tracker = new TrackerClient(); TrackerServer trackerServer = tracker.getConnection(); StorageServer storageServer = null; StorageClient1 client = new StorageClient1(trackerServer, storageServer); //設置元信息 NameValuePair[] metaList = new NameValuePair[3]; metaList[0] = new NameValuePair("fileName", tempFileName); metaList[1] = new NameValuePair("fileExtName", fileExtName); metaList[2] = new NameValuePair("fileLength", String.valueOf(file.getSize())); //上傳文件 fileId = client.upload_file1(fileBuff, fileExtName, metaList); res.setHead_img(UserConstants.FILE_IMG_URL+fileId); res.setRet_code(UserCodeEnum.SUCCESS.getCode()); res.setRet_msg(UserCodeEnum.SUCCESS.getDesc()); } logger.info("UserController-upload-response-" + JsonUtils.o2j(res)); } catch (Exception e) { res.setRet_code(UserCodeEnum.ERR_UNKNOWN.getCode()); res.setRet_msg(UserCodeEnum.ERR_UNKNOWN.getDesc()); logger.error("UserController-upload-error", e); } return res; }
fastDFS java客戶端配置文件fdfs_client.conf配置如下:
connect_timeout = 30 network_timeout = 60 charset = ISO8859-1 http.tracker_http_port = 8090 http.anti_steal_token = no http.secret_key = 123456 tracker_server = 192.168.11.***:22122
參考:
http://blog.chinaunix.net/uid-20196318-id-4058561.html
![]() |
不含病毒。www.avast.com |