【大型网站技术实践】初级篇:海量图片的分布式存储设计与实现
說明:本文是我閱讀計算機工程期刊《海量圖片的分布式存儲及負載均衡研究》一文的學習筆記和具體實踐,原文地址在本文底部。
一、研究背景:性能與資金,二者可兼得乎?
1.1 那么問題來了?
隨著互聯(lián)網(wǎng)的發(fā)展,許多大中型的網(wǎng)站都保存了大量的圖片資源,用戶在訪問這些圖片資源異常豐富的網(wǎng)站(如淘寶、京東等電子商務(wù)網(wǎng)站)時,網(wǎng)頁中的圖片信息占據(jù)了頁面數(shù)據(jù)流量的很大部分,那么問題也來了:
(1)由于受客戶端瀏覽器限制,無法從一臺服務(wù)器上同時下載頁面中所有圖片信息;
PS:當一個網(wǎng)頁被瀏覽時,Web服務(wù)器與瀏覽器建立連接,每個連接表示一個并發(fā)。當頁面包含多個圖片時,Web服務(wù)器與瀏覽器會產(chǎn)生多個連接,同時發(fā)送文字和圖片以提高瀏覽速度。因此,頁面中圖片越多Web服務(wù)器受到的壓力也就越大。同時由于受到瀏覽器本身的并發(fā)連接數(shù)限制(2個~6個并發(fā)),意味著頁面上有多于并發(fā)連接數(shù)限制的圖片時,也不能并行地把所有圖片同時下載和顯示。
(2)由于圖片保存在物理服務(wù)器上,訪問圖片需要頻繁進行I/O操作:因此當并發(fā)用戶數(shù)越來越多時,I/O操作就會成為整個系統(tǒng)的性能瓶頸;
(3)由于受操作系統(tǒng)的限制,一個目錄中能存放的圖片文件數(shù)量也是有限的:隨著圖片資源不斷增加,如何有效管理和維護圖片也是一個難題;
1.2 山東濟南找藍翔?
(1)對于少數(shù)大型網(wǎng)站系統(tǒng),由于自身具有雄厚的資金和人力資源,可采用NFS、CDN、Lighttpd、反向代理、負載均衡等技術(shù)提高用戶訪問速度;但是,這些技術(shù)需要龐大的資金來支持。
(2)對于多數(shù)中小型網(wǎng)站系統(tǒng),有木有一種方案適用于中等規(guī)模商務(wù)網(wǎng)站的海量圖片數(shù)據(jù)分布式動態(tài)存儲及負載均衡的解決方案?該方案可否只需增加很少的硬件成本,即可提升網(wǎng)站的訪問速度,并且可以根據(jù)需要動態(tài)調(diào)整圖片服務(wù)器的數(shù)量及圖片的存儲目錄,確保系統(tǒng)具有可擴展性和伸縮性。
SUMMARY:需求永遠是那么美好,使用最少的money干盡量多的事情!正在我們決定放棄開發(fā)崗位去藍翔學挖掘機技術(shù)的時候,我們突然發(fā)現(xiàn)有那么多的技術(shù)先驅(qū)已經(jīng)給我們指明了道路。
二、架構(gòu)設(shè)計:構(gòu)建圖片服務(wù)器集群
對于小型網(wǎng)站,由于數(shù)據(jù)規(guī)模小,可以把網(wǎng)站所有頁面和圖片統(tǒng)一存放在一個主目錄下,這樣的網(wǎng)站對系統(tǒng)架構(gòu)、性能要求都很簡單。但大中型網(wǎng)站都保存有海量級的圖片文件,所采用的技術(shù)更是涉及廣泛,從硬件到軟件、編程語言、數(shù)據(jù)庫、Web服務(wù)器、防火墻等各個領(lǐng)域都有較高要求。因此,有必要設(shè)立單獨的圖片服務(wù)器來專門存放圖片,把圖片數(shù)據(jù)的流量從Web服務(wù)器上分離開,這樣的架構(gòu)可以有效緩解Web服務(wù)器的I/O性能瓶頸,提升用戶的訪問速度。
2.1 系統(tǒng)設(shè)計目標
基于以上的考慮,我們希望的設(shè)計目標是:
(1)圖片能進行分布式存儲;
(2)圖片服務(wù)器能實現(xiàn)負載均衡;
(3)能根據(jù)用戶訪問量及網(wǎng)站圖片數(shù)據(jù)量的增加能動態(tài)添加圖片服務(wù)器節(jié)點;
(4)圖片服務(wù)器節(jié)點的動態(tài)調(diào)整對網(wǎng)站用戶而言是透明的,并且不會中斷系統(tǒng)的正常運行;
其中,(1)和(2)是針對系統(tǒng)的高可用和伸縮性,而(3)和(4)則是針對系統(tǒng)的高可用和可擴展而言的。
2.2 系統(tǒng)架構(gòu)設(shè)計
系統(tǒng)整體架構(gòu)如上圖所示:包括客戶端、Web服務(wù)器、數(shù)據(jù)庫服務(wù)器、圖片服務(wù)器集群4個部分。
(1)Web服務(wù)器部署網(wǎng)站的Web頁面,用于響應(yīng)客戶端用戶的請求。當用戶瀏覽網(wǎng)頁時,Web服務(wù)器響應(yīng)請求并訪問數(shù)據(jù)庫服務(wù)器,獲得網(wǎng)頁中所有圖片的URL路徑,然后生成頁面并返回給客戶端;
(2)客戶端接收該頁面并根據(jù)頁面中的圖片URL路徑自動從不同的圖片服務(wù)器下載并顯示相應(yīng)圖片。
(3)數(shù)據(jù)庫服務(wù)器用于記錄所有圖片的編號以及圖片的存放位置等信息,同時需要記錄所有圖片服務(wù)器的配置及當前狀態(tài)信息。
(4)圖片服務(wù)器集群用于存放網(wǎng)站的所有圖片信息,該集群的服務(wù)器數(shù)量可以根據(jù)需要動態(tài)增加或刪減。
三、系統(tǒng)實現(xiàn):一種簡單且價廉可用的方案
3.1 數(shù)據(jù)庫設(shè)計與實現(xiàn):兩張簡單的表
Web服務(wù)器需要及時掌握所有圖片服務(wù)器的狀態(tài)和信息才能動態(tài)決定把圖片保存到哪一臺圖片服務(wù)器。因此,需要把所有的圖片服務(wù)器的狀態(tài)信息全部紀錄到數(shù)據(jù)庫服務(wù)器中,記錄圖片服務(wù)器信息和狀態(tài)的表格式如下圖所示:可以清楚地看出,圖片服務(wù)器信息表中記錄了圖片服務(wù)器的ID、名稱、URL、最大存儲數(shù)量、當前已存數(shù)量以及服務(wù)器的狀態(tài)(True:可用,False:不可用),每個圖片服務(wù)器下會有多個圖片信息記錄,因此它們是一對多的關(guān)系。
(1)圖片服務(wù)器狀態(tài)信息表建表語句:
?View Code(2)圖片記錄信息表建表語句:
?View Code3.2 文件上傳與瀏覽系統(tǒng)實現(xiàn):一個ASP.Net MVC應(yīng)用程序
這里我們使用一個ASP.NET MVC應(yīng)用程序部署在Web服務(wù)器上,這個應(yīng)用程序作為Web網(wǎng)站向客戶提供上傳和瀏覽的服務(wù)。因此,它最重要的功能就是:
一、接收用戶上傳的文件,并轉(zhuǎn)交給圖片服務(wù)器的相關(guān)處理程序進行處理和保存;
二、取得所有圖片服務(wù)器中保存的有效圖片路徑,返回給客戶端瀏覽器,再由客戶端瀏覽器對圖片路徑向圖片服務(wù)器集群進行請求;
3.2.1 設(shè)計Controller
?View Code(1)圖片上傳的過程比較復(fù)雜,首先Web服務(wù)器接收客戶端的訪問請求并訪問數(shù)據(jù)庫,在Web端需要取得所有可用的圖片服務(wù)器的集合,這里使用到了一個GetAllUseableServers方法,它的實現(xiàn)如下:可以看出,我們需要判斷FlgUsable標志為true以及CurPicAmount當前存儲量小于MaxPicAmount最大存儲量這兩個條件。如果有宕機或不可用的情況,需要管理員將那一行的FlgUsable設(shè)置為false。
public List<ImageServerInfo> GetAllUseableServers(){List<ImageServerInfo> serverList = db.ImageServerInfo.Where<ImageServerInfo>(s => s.FlgUsable == true&& s.CurPicAmount < s.MaxPicAmount).ToList();return serverList;}(2)這里用到了一個GetServerIndex的方法,它的實現(xiàn)如下:從圖片服務(wù)器狀態(tài)信息表篩選出可用的圖片服務(wù)器集合記作C,并獲取集合的總記錄數(shù)N。然后用隨機函數(shù)產(chǎn)生一個隨機數(shù)R1,用R1與N進行取余運算記作I=R1%N。則C[I]即為要保存圖片的圖片服務(wù)器。這個方法基本保證了我們的圖片服務(wù)器的負載是一個比較均衡的比例。(當然,我們可以設(shè)計一個更加高效的,類似于一致性哈希算法的哈希函數(shù))
#region 01.獲取服務(wù)器索引號/// <summary>/// 01.獲取服務(wù)器索引號/// </summary>/// <param name="serverCount">服務(wù)器數(shù)量</param>/// <returns>索引號</returns>public static int GetServerIndex(int serverCount){Random rand = new Random();int randomNumber = rand.Next();int serverIndex = randomNumber % serverCount;return serverIndex;} #endregion(3)最后,Web端程序借助了WebClient將服務(wù)器ID、文件擴展名以及圖片的字節(jié)流轉(zhuǎn)交給了具體的圖片服務(wù)器處理程序:Web端程序的工作就到此結(jié)束,但是這里木有采用異步,因此需要等待圖片服務(wù)器的工作結(jié)束。
WebClient client = new WebClient();client.UploadData(serverFullUrl, CommonHelper.StearmToBytes(file.InputStream));PS:由于B/S架構(gòu)本身技術(shù)限制,圖片無法通過Web服務(wù)器直接上傳到不同的圖片服務(wù)器中。因此,這里需要借助類似于WebClient、HttpWebRequest等類向具體的圖片服務(wù)器發(fā)送Http請求,或者是通過在圖片服務(wù)器上部署Web Service,以便Web服務(wù)器通過調(diào)用該服務(wù)執(zhí)行圖片的保存操作。
3.2.2 設(shè)計View
(1)上傳頁面:
?View Code在form標簽中不要忘了:enctype="multipart/form-data"
(2)瀏覽頁面:
?View Code這里主要通過對不同的圖片服務(wù)器發(fā)送請求獲取圖片,從而降低Web服務(wù)器的I/O性能瓶頸,加快整個系統(tǒng)的響應(yīng)時間。
3.3 圖片服務(wù)器文件接收系統(tǒng)實現(xiàn):一個ASP.Net一般處理程序
?View Code(1)這是一個簡單的一般處理程序,它首先接收要保存的圖片擴展名以及服務(wù)器ID,根據(jù)規(guī)則生成具體的保存路徑,然后通過I/O流將圖片保存到該服務(wù)器的磁盤上;
(2)最后將更改數(shù)據(jù)庫信息記錄,由于要同時對兩張表進行修改,這里我們需要對這個方法進行一個簡單的封裝,使之成為一個事務(wù)?,F(xiàn)在我們來看看這個Add方法的實現(xiàn):
public ImageStatusEnum Add(ImageInfo imageEntity){// 首先是圖片信息表 db.ImageInfo.Add(imageEntity);// 其次是圖片服務(wù)器信息表ImageServerInfo serverEntity = db.ImageServerInfo.FirstOrDefault(s => s.ServerId == imageEntity.ImageServerId);if (serverEntity != null){// 當前服務(wù)器存儲數(shù)量+1serverEntity.CurPicAmount += 1;}// 一起提交到SQL Server數(shù)據(jù)庫中int result = db.SaveChanges();if (result > 0){return ImageStatusEnum.Successful;}else{return ImageStatusEnum.Failure;}}3.4 簡單測試圖片文件的上傳與瀏覽
(1)測試前的準備工作
?、儆捎谖业碾娔X不支持64位的虛擬機,因此原本打算在VMware中部署三臺Windows Server 2008 R2作為Web服務(wù)器和圖片服務(wù)器的打算被撤銷(沒法任性地做實踐,我很不開心啊)。于是,我采用了在一臺電腦上部署多個應(yīng)用,用端口號區(qū)分不同的服務(wù)程序來模擬效果。
?、趯eb應(yīng)用程序和圖片服務(wù)應(yīng)用程序分別編譯發(fā)布,并部署到IIS中,分配不同的端口號:圖片上傳與瀏覽程序8000端口,圖片服務(wù)器的文件處理程序分別占用8010與8020端口;
(2)測試圖片文件上傳與存儲
由于連續(xù)截屏所生成的gif圖片太大,因此這里只選擇了截取其中一次上傳的過程作為展示。在我連續(xù)上傳操作了N次之后,現(xiàn)在我們來看看兩個文件服務(wù)器所在的文件夾中是否有我們上傳的圖片文件(這里主要是看部署的程序所在的文件目錄,其中有一個專門保存圖片的文件目錄Upload)
?、賵D片服務(wù)器A所保存的文件:
?、趫D片服務(wù)器B所保存的文件:
總結(jié):從圖中可以看出,我們一共上傳了13張圖片,其中圖片服務(wù)器A保存了6張,圖片服務(wù)器B保存了7張,兩個服務(wù)器的負載并沒有出現(xiàn)一頭小一頭大,而是一個相對比較均衡的數(shù)量,這得益于我們的隨機函數(shù)。
(3)測試圖片文件瀏覽請求
?、偈欠耧@示了圖片列表:
?、谑欠駨牟煌瑘D片服務(wù)器獲取:
總結(jié):設(shè)立單獨的圖片服務(wù)器來專門存放圖片后,把圖片數(shù)據(jù)的流量從Web服務(wù)器上分離開,這樣可以緩解Web服務(wù)器的I/O性能瓶頸,提高響應(yīng)速度。
(4)在原文的性能測試中,在局域網(wǎng)環(huán)境下對采用圖片服務(wù)器和不采用圖片服務(wù)器2種情況進行了性能測試:測試數(shù)據(jù)有300萬張圖片均勻分布在3臺圖片服務(wù)器上,每臺圖片服務(wù)器建立1 000個子目錄。在5臺客戶端上同時運行壓力測試軟件,分別模擬200個~1 000個并發(fā)用戶的請求。其測試結(jié)果如下圖所示:
從圖中可以看出,采用3臺普通PC機作為圖片服務(wù)器后,整個系統(tǒng)的響應(yīng)時間大大減少,性能得到明顯提升,而且并發(fā)訪問量越大,性能的提升越明顯,而對于整個系統(tǒng)而言增加的硬件成本卻很有限。
參考資料
?朱曉輝、王杰華、石振國、陳蘇蓉,《海量圖片的分布式存儲及負載均衡研究》:http://www.cqvip.com/QK/71135X/201107/36101649.html
附件下載
(1)數(shù)據(jù)庫:MyImageServer.mdf
(2)程序代碼:MyImageDFS
來源:http://www.cnblogs.com/edisonchou/p/4137134.html
總結(jié)
以上是生活随笔為你收集整理的【大型网站技术实践】初级篇:海量图片的分布式存储设计与实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 宝蓝色(说一说宝蓝色的简介)
- 下一篇: API接口设计 注意问题