高併發高流量網站架構

轉自: http://blog.csdn.net/smarttony/article/details/5874485

高併發高流量網站架構


Web2.0的興起,掀起了互聯網新一輪的網絡創業大潮。以用戶爲導向的新網站建設概念,細分了網站功能和用戶羣,不僅成功的造就了一大批新生的網站,也極大的方便了上網的人們。但Web2.0以用戶爲導向的理念,使得新生的網站有了新的特點——高併發,高流量,數據量大,邏輯複雜等,對網站建設也提出了新的要求。

    本文圍繞高併發高流量的網站架構設計問題,主要研究討論了以下內容:

    首先在整個網絡的高度討論了使用鏡像網站,CDN內容分發網絡等技術對負載均衡帶來的便利及各自的優缺點比較。然後在局域網層次對第四層交換技術,包括硬件解決方案F5軟件解決方案LVS,進行了簡單的討論。接下來在單服務器層次,本文着重討論了單臺服務器Socket優化,硬盤級緩存技術,內存級緩存技術,CPUIO平衡技術(即以運算爲主的程序與以數據讀寫爲主的程序搭配部署),讀寫分離技術等。在應用層,本文介紹了一些大型網站常用的技術,以及選擇使用該技術的理由。最後,在架構的高度討論了網站擴容,容錯等問題。

本文以理論與實踐相結合的形式,結合作者實際工作中得到的經驗,具有較廣泛的適用性。

1 引言

1.1 互聯網的發展
最近十年間,互聯網已經從一個單純的用於科研的,用來傳遞靜態文檔的美國內部網絡,發展成了一個應用於各行各業的,傳送着海量多媒體及動態信息的全球網絡。從規模上看,互聯網在主機數、帶寬、上網人數等方面幾乎一直保持着指數增長的趨勢,2006年7月,互聯網上共有主機439,286,364 臺,WWW 站點數量達到 96,854,877個 [1]。全球上網人口在2004 年達到 7 億 2900萬 [2],中國的上網人數在 2006 年 12 月達到了約 1億3700 萬[3]。另一方面,互聯網所傳遞的內容也發生了巨大的變化,早期互聯網以靜態、文本的公共信息爲主要內容,而目前的互聯網則傳遞着大量的動態、多媒體及人性化的信息,人們不僅可以通過 互聯網閱讀到動態生成的信息,而且可以通過它使用電子商務、即時通信、網上游戲等交互性很強的服務。因此,可以說互聯網已經不再僅僅是一個信息共享網絡,而已經成爲了一個無所不在的交互式服務的平臺。

1.2 互聯網網站建設的新趨勢

互聯網不斷擴大的規模,日益增長的用戶羣,以及web2.0[4]的興起,對互聯網網站建設提出了新的要求:

高性能和高可擴展性。2000 年 5 月,訪問量排名世界第一(統計數據來源[5])的Yahoo [6]聲稱其日頁瀏覽數達到 6 億 2500 萬,即每秒約 30,000 次HTTP 請求(按每個頁面瀏覽平均產生 4 次請求計算) 。這樣大規模的訪問量對服務的性能提出了非常高的要求。更爲重要的是,互聯網受衆的廣泛性,使得成功的互聯網服務的訪問量增長潛力和速度非常大,因此服務系統必須具有非常好的可擴展性,以應付將來可能的服務增長。

支持高度併發的訪問。高度併發的訪問對服務的存儲與併發能力提出了很高的要求,當前主流的超標量和超流水線處理器能處理的併發請求數是有限的,因爲隨着併發數的上升,進程調度的開銷會很快上升。互聯網廣域網的本質決定了其訪問的延遲時間較長,因此一個請求完成時間也較長,按從請求產生到頁面下載完成 3 秒計算, Yahoo 在 2000 年 5 月時平均有 90,000 個併發請求。而且對於較複雜的服務,服務器往往要維護用戶會話的信息,例如一個互聯網網站如果每天有 100 萬次用戶會話,每次 20分鐘的話,那平均同時就會有約 14000 個併發會話。

高可用性。互聯網服務的全球性決定了其每天 24 小時都會有用戶訪問,因此任何服務的停止都會對用戶造成影響。而對於電子商務等應用,暫時的服務中止則意味着客戶的永久失去及大量的經濟損失,例如 ebay.com[7]1999 年 6 月的一次 22小時的網站不可訪問,對此網站的 380萬用戶的忠誠度造成巨大影響,使得 Ebay 公司不得不支付了近500萬美元用於補償客戶的損失,而該公司的市值同期下降了 40 億美元[8]。因此,關鍵互聯網應用的可用性要求非常高。

1.3 新浪播客的簡介

以YouTube[9]爲代表的微視頻分享網站近來方興未艾,僅2006年一年,國內就出現近百家仿YouTube的微視頻分享網站[10],試圖複製YouTube的成功模式。此類網站可以說是Web2.0概念下的代表網站,具有Web2.0網站所有典型特徵:高併發,高流量,數據量大,邏輯複雜,用戶分散等等。新浪[11]作爲國內最大的門戶網站,在2005年成功運作新浪博客的基礎上,於2006年底推出了新浪播客服務。新浪播客作爲國內門戶網站中第一個微視頻分享服務的網站,依靠新浪網站及新浪博客的巨大人氣資源,在推出後不到半年的時間內,取得了巨大的成功:同類網站中上傳視頻數量第一、流量增長最快、用戶數最多[12],所有這些成績的取得的背後,是巨大的硬件投入,良好的架構支撐和靈活的應用層軟件設計。


2.1 鏡像網站技術

鏡像網站是指將一個完全相同的站點放到幾個服務器上,分別有自己的URL,這些服務器上的網站互相稱爲鏡像網站[13]。鏡像網站和主站並沒有太大差別,或者可以視爲主站的拷貝。鏡像網站的好處是:如果不能對主站作正常訪問(如服務器故障,網絡故障或者網速太慢等),仍能通過鏡像服務器獲得服務。不便之處是:更新網站內容的時候,需要同時更新多個服務器;需要用戶記憶超過一個網址,或需要用戶選擇訪問多個鏡像網站中的一個,而用戶選擇的,不一定是最優的。在用戶選擇的過程中,缺乏必要的可控性。

在互聯網發展的初期,互聯網上的網站內容很少,而且大都是靜態內容,更新頻率底。但因爲服務器運算能力低,帶寬小,網速慢,熱門網站的訪問壓力還是很大。鏡像網站技術在這種情況下作爲一種有效解決方案,被廣泛採用。隨着互聯網的發展,越來越多的網站使用服務器端腳本動態生成內容,同步更新越來越困難,對可控性要求越來越高,鏡像技術因爲不能滿足這類網站的需要,漸漸的淡出了人們的視線。但有一些大型的軟件下載站,因爲符合鏡像網站的條件——下載的內容是靜態的,更新頻率較低,對帶寬,速度要求又比較高,如國外的SourceForge (http://www.SourceForge.net,著名開源軟件託管網站),Fedora(http://fedoraproject.org,RedHat贊助的Linux發行版),國內的華軍軟件園(http://www.onlinedown.net),天空軟件站(http://www.skycn.com)等,還在使用這項技術(圖1)。


 

在網站建設的過程中,可以根據實際情況,將靜態內容作一些鏡像,以加快訪問速度,提升用戶體驗。

2.2 CDN內容分發網絡

    CDN的全稱是Content Delivery Network,即內容分發網絡。其目的是通過在現有的互聯網中增加一層新的網絡架構,將網站的內容發佈到最接近用戶的網絡“邊緣”,使用戶可以就近取得所需的內容,分散服務器的壓力,解決互聯網擁擠的狀況,提高用戶訪問網站的響應速度。從而解決由於網絡帶寬小、用戶訪問量大、網點分佈不均等原因所造成的用戶訪問網站響應速度慢的問題[14]。

    CDN與鏡像網站技術的不同之處在於網站代替用戶去選擇最優的內容服務器,增強了可控制性。CDN其實是夾在網頁瀏覽者和被訪問的服務器中間的一層鏡像或者說緩存,瀏覽者訪問時點擊的還是服務器原來的URL地址,但是看到的內容其實是對瀏覽者來說最優的一臺鏡像服務器上的頁面緩存內容。這是通過調整服務器的域名解析來實現的。使用CDN技術的域名解析服務器需要維護一個鏡像服務器列表和一份來訪IP到鏡像服務器的對應表。當一個用戶的請求到來的時候,根據用戶的IP,查詢對應表,得到最優的鏡像服務器的IP地址,返回給用戶。這裏的最優,需要綜合考慮服務器的處理能力,帶寬,離訪問者的距離遠近等因素。當某個地方的鏡像網站流量過大,帶寬消耗過快,或者出現服務器,網絡等故障的時候,可以很方便的設置將用戶的訪問轉到另外一個地方(圖2)。這樣就增強了可控制性。

CDN網絡加速技術也有它的侷限性。首先,因爲內容更新的時候,需要同步更新多臺鏡像服務器,所以它也只適用於內容更新不太頻繁,或者對實時性要求不是很高的網站;其次,DNS解析有緩存,當某一個鏡像網站的訪問需要轉移時,主DNS服務器更改了IP解析結果,但各地的DNS服務器緩存更新會滯後一段時間,這段時間內用戶的訪問仍然會指向該服務器,可控制性依然有不足。

目前,國內訪問量較高的大型網站如新浪、網易等的資訊頻道,均使用CDN網絡加速技術(圖3),雖然網站的訪問量巨大,但無論在什麼地方訪問,速度都會很快。但論壇,郵箱等更新頻繁,實時性要求高的頻道,則不適合使用這種技術。

ChinaCache的服務節點全球超過130個,

其中中國節點超過80個,

覆蓋全國主要6大網絡的主要省份[15]。

2.3 應用層分佈式設計
新浪播客爲了獲得CDN網絡加速的優點,又必須避免CDN的不足,在應用層軟件設計上,採取了一個替代的辦法。新浪播客提供了一個供播放器查詢視頻文件地址的接口。當用戶打開視頻播放頁面的時候,播放器首先連接查詢接口,通過接口獲得視頻文件所在的最優的鏡像服務器地址,然後再到該服務器去下載視頻文件。這樣,用一次額外的查詢獲得了全部的控制性,而這次查詢的通訊流量非常小,幾乎可以忽略不計。CDN中由域名解析獲得的靈活性也保留了下來:由接口程序維護鏡像網站列表及來訪IP到鏡像網站的對應表即可。鏡像網站中不需要鏡像所有的內容,而是隻鏡像更新速度較慢的視頻文件。這是完全可以承受的。

2.4 網絡層架構小結
從整個互聯網絡的高度來看網站架構,努力的方向是明確的:讓用戶就近取得內容,但又要在速度和可控制性之間作一個平衡。對於更新比較頻繁內容,由於難以保持鏡像網站之間的同步,則需要使用其他的輔助技術。


3 交換層架構

3.1 第四層交換簡介
按照OSI[16]七層模型,第四層是傳輸層。傳輸層負責端到端通信,在IP協議棧中是TCP和UDP所在的協議層。TCP和UDP數據包中包含端口號(port number),它們可以唯一區分每個數據包所屬的協議和應用程序。接收端計算機的操作系統根據端口號確定所收到的IP包類型,並把它交給合適的高層程序。IP地址和端口號的組合通常稱作“插口(Socket)”。

第四層交換的一個簡單定義是:它是一種傳輸功能,它決定傳輸不僅僅依據MAC地址(第二層網橋)或源/目標IP地址(第三層路由),而且依據IP地址與TCP/UDP (第四層) 應用端口號的組合(Socket)[17]。第四層交換功能就像是虛擬IP,指向實際的服務器。它傳輸的數據支持多種協議,有HTTP、FTP、NFS、Telnet等。

以HTTP協議爲例,在第四層交換中爲每個服務器組設立一個虛擬IP(Virtue IP,VIP),每組服務器支持某一個或幾個域名。在域名服務器(DNS)中存儲服務器組的VIP,而不是某一臺服務器的真實地址。

當用戶請求頁面時,一個帶有目標服務器組的VIP連接請求發送給第四層交換機。第四層交換機使用某種選擇策略,在組中選取最優的服務器,將數據包中的目標VIP地址用實際服務器的IP地址取代,並將連接請求傳給該服務器。第四層交換一般都實現了會話保持功能,即同一會話的所有的包由第四層交換機進行映射後,在用戶和同一服務器間進行傳輸[18]。

第四層交換按實現分類,分爲硬件實現和軟件實現。

3.2 硬件實現
第四層交換的硬件實現一般都由專業的硬件廠商作爲商業解決方案提供。常見的有Alteon[19],F5[20]等。這些產品非常昂貴,但是能夠提供非常優秀的性能和很靈活的管理能力。Yahoo中國當初接近2000臺服務器使用了三四臺Alteon就搞定了[21]。鑑於條件關係,這裏不展開討論。

3.3 軟件實現
第四層交換也可以通過軟件實現,不過性能比專業硬件稍差,但是滿足一定量的壓力還是可以達到的,而且軟件實現配置起來更靈活。軟件四層交換常用的有Linux上的LVS(Linux Virtual Server),它提供了基於心跳(heart beat)的實時災難應對解決方案,提高了系統的魯棒性,同時提供了靈活的VIP配置和管理功能,可以同時滿足多種應用需求[22]。


服務器優化

4.1 服務器整體性能考慮
對於價值昂貴的服務器來說,怎樣配置才能發揮它的最大功效,又不至於影響正常的服務,這是在設計網站架構的時候必須要考慮的。常見的影響服務器的處理速度的因素有:網絡連接,硬盤讀寫,內存空間,CPU速度。如果服務器的某一個部件滿負荷運轉仍然低於需要,而其他部件仍有能力剩餘,我們將之稱爲性能瓶頸。服務器想要發揮最大的功效,關鍵的是消除瓶頸,讓所有的部件都被充分的利用起來。

4.2 Socket優化
以標準的 GNU/Linux 爲例。GNU/Linux 發行版試圖對各種部署情況都進行優化,這意味着對具體服務器的執行環境來說,標準的發行版可能並不是最優化的[23]。GNU/Linux 提供了很多可調節的內核參數,可以使用這些參數爲服務器進行動態配置,包括影響 Socket 性能的一些重要的選項。這些選項包含在 /proc 虛擬文件系統中。這個文件系統中的每個文件都表示一個或多個參數,它們可以通過 cat 工具進行讀取,或使用 echo 命令進行修改。這裏僅列出一些影響TCP/IP 棧性能的可調節內核參數[24]:

/proc/sys/net/ipv4/tcp_window_scaling “1”(1表示啓用該選項,0表示關閉,下同) 啓用 RFC[25] 1323[26] 定義的 window scaling;要支持超過 64KB 的窗口,必須啓用該值。

/proc/sys/net/ipv4/tcp_sack “1”啓用有選擇的應答(Selective Acknowledgment),通過有選擇地應答亂序接收到的報文來提高性能(這樣可以讓發送者只發送丟失的報文段);對於廣域網通信來說,這個選項應該啓用,但是這也會增加對 CPU 的佔用。

/proc/sys/net/ipv4/tcp_timestamps “1” 以一種比重發超時更精確的方法(參閱 RFC 1323)來啓用對 RTT 的計算;爲了實現更好的性能應該啓用這個選項。

/proc/sys/net/ipv4/tcp_mem “24576 32768 49152” 確定 TCP 棧應該如何反映內存使用;每個值的單位都是內存頁(通常是 4KB)。第一個值是內存使用的下限。第二個值是內存壓力模式開始對緩衝區使用應用壓力的上限。第三個值是內存上限。超過這個上限時可以將報文丟棄,從而減少對內存的使用。

/proc/sys/net/ipv4/tcp_wmem “4096 16384 131072” 爲自動調優定義每個 socket 使用的內存。第一個值是爲 socket 的發送緩衝區分配的最少字節數。第二個值是默認值(該值會被 wmem_default 覆蓋),緩衝區在系統負載不重的情況下可以增長到這個值。第三個值是發送緩衝區空間的最大字節數(該值會被 wmem_max 覆蓋)。

/proc/sys/net/ipv4/tcp_westwood “1” 啓用發送者端的擁塞控制算法,它可以維護對吞吐量的評估,並試圖對帶寬的整體利用情況進行優化;對於 WAN 通信來說應該啓用這個選項。

與其他調優努力一樣,最好的方法實際上就是不斷進行實驗。具體應用程序的行爲、處理器的速度以及可用內存的多少都會影響到這些參數對性能作用的效果。在某些情況中,一些認爲有益的操作可能恰恰是有害的(反之亦然)。因此,需要逐一試驗各個選項,然後檢查每個選項的結果,最後得出最適合具體機器的一套參數。

如果重啓了 GNU/Linux 系統,設置的內核參數都會恢復成默認值。爲了將所設置的值作爲這些參數的默認值,可以使用 /etc/rc.local 文件,在系統每次啓動時自動將這些參數配置成所需要的值。

在檢測每個選項的更改帶來的效果的時候,GNU/Linux上有一些非常強大的工具可以使用:

ping 這是用於檢查主機的可用性的最常用的工具,也可以用於計算網絡帶寬延時。

traceroute 打印連接到特定網絡主機所經過的一系列路由器網關的路徑(路由),從而確定每個 hop 之間的延時。

netstat 確定有關網絡子系統、協議和連接的各種統計信息。

tcpdump 顯示一個或多個連接的協議級的報文跟蹤信息,其中包括時間信息,可以使用這些信息來研究不同協議的報文時間。

Ethereal 以一個易於使用的圖形化界面提供 tcpump (報文跟蹤)的信息,支持報文過濾功能。

iperf 測量 TCP 和 UDP 的網絡性能;測量最大帶寬,並彙報延時和數據報的丟失情況。

4.3 硬盤級緩存
硬盤級別的緩存是指將需要動態生成的內容暫時緩存在硬盤上,在一個可接受的延遲時間範圍內,同樣的請求不再動態生成,以達到節約系統資源,提高網站承受能力的目的。Linux環境下硬盤級緩存一般使用Squid[27]。

Squid是一個高性能的代理緩存服務器。和一般的代理緩存軟件不同,Squid用一個單獨的、非模塊化的、I/O驅動的進程來處理所有的客戶端請求。它接受來自客戶端對目標對象的請求並適當地處理這些請求。比如說,用戶通過瀏覽器想下載(即瀏覽)一個web頁面,瀏覽器請求Squid爲它取得這個頁面。Squid隨之連接到頁面所在的原始服務器並向服務器發出取得該頁面的請求。取得頁面後,Squid再將頁面返回給用戶端瀏覽器,並且同時在Squid本地緩存目錄裏保存一份副本。當下一次有用戶需要同一頁面時,Squid可以簡單地從緩存中讀取它的副本,直接返回給用戶,而不用再次請求原始服務器。當前的Squid可以處理HTTP, FTP, GOPHER, SSL和WAIS等協議。

Squid默認通過檢測HTTP協議頭的Expires和 Cache-Control字段來決定緩存的時間。在實際應用中,可以顯式的在服務器端腳本中輸出HTTP頭,也可以通過配置apache的 mod_expires模塊,讓apache自動的給每一個網頁加上過期時間。對於靜態內容,如圖片,視頻文件,供下載的軟件等,還可以針對文件類型(擴展名),用 Squid 的 refresh_pattern 來指定緩存時間。

Squid 運行的時候,默認會在硬盤上建兩層hash目錄,用來存儲緩存的Object。它還會在內存中建立一個Hash Table,用來記錄硬盤中Object分佈的情況。如果Squid配置成爲一個Squid集羣中的一個的話,它還會建立一個 Digest Table(摘要表),用來存儲其它 Squid 上的Object摘要。當用戶端想要的資料本地硬盤上沒有時,可以很快的知道應該去集羣中的哪一臺機器獲得。在硬盤空間快要達到配置限額的時候,可以配置使用某種策略(默認使用LRU:Least Recently Used-最近最少用)刪除一些Object,從而騰出空間[28][29]。

集羣中的Squid Server 之間可以有兩種關係:第一種關係是:Child 和 Parent。當 Child Squid Server 沒有資料時,會直接向 Parent Squid Server 要資料,然後一直等,直到 Parent 給它資料爲止。 第二種關係是:Sibling 和 Sibling。當 Squid Server 沒有資料時,會先向 Sibling 的 Squid Server 要資料,如果 Sibling 沒資料,就跳過它向 Parent 要或直接上原始網站去拿。

默認配置的Squid,沒有經過任何優化的時候,一般可以達到 50% 的命中率[30](圖4)。如果需要,還可以通過參數優化,拆分業務,優化文件系統等辦法,使得Squid達到 90% 以上的緩存命中率。 Squid處理TCP連接消耗的服務器資源比真正的HTTP服務器要小的多,當Squid分擔了大部分連接,網站的承壓能力就大大增強了。

藍線表示Squid的流量,綠色部分表示Apache流量

4.4 內存級緩存
內存級別的緩存是指將需要動態生成的內容暫時緩存在內存裏,在一個可接受的延遲時間範圍內,同樣的請求不再動態生成,而是直接從內存中讀取。Linux環境下內存級緩存Memcached[31]是一個不錯的選擇。

Memcached是danga.com(運營Live Journal[32]的技術團隊)開發的一套非常優秀的分佈式內存對象緩存系統,用於在動態系統中減少數據庫負載,提升性能。和 Squid 的前端緩存加速不同,它是通過基於內存的對象緩存來減少數據庫查詢的方式改善網站的性能,而其中最吸引人的一個特性就是支持分佈式部署;也就是說可以在一羣機器上建立一堆 Memcached 服務,每個服務可以根據具體服務器的硬件配置使用不同大小的內存塊,這樣,理論上可以建立一個無限大的基於內存的緩存系統。

Memcached 是以守護程序方式運行於一個或多個服務器中,隨時接受客戶端的連接操作,客戶端可以由各種語言編寫,目前已知的客戶端 API 包括 Perl/PHP/Python/Ruby/Java/C#/C 等等[附錄1]。客戶端首先與 Memcached 服務建立連接,然後存取對象。每個被存取的對象都有一個唯一的標識符 key,存取操作均通過這個 key 進行,保存的時候還可以設置有效期。保存在 Memcached 中的對象實際上是放置在內存中的,而不是在硬盤上。Memcached 進程運行之後,會預申請一塊較大的內存空間,自己進行管理,用完之後再申請一塊,而不是每次需要的時候去向操作系統申請。Memcached將對象保存在一個巨大的Hash表中,它還使用NewHash算法來管理Hash表,從而獲得進一步的性能提升。所以當分配給Memcached的內存足夠大的時候,Memcached的時間消耗基本上只是網絡Socket連接了[33]。

Memcached也有它的不足。首先它的數據是保存在內存當中的,一旦服務進程重啓(進程意外被關掉,機器重啓等),數據會全部丟失。其次Memcached以root權限運行,而且Memcached本身沒有任何權限管理和認證功能,安全性不足。第一條是Memcached作爲內存緩存服務使用無法避免的,當然,如果內存中的數據需要保存,可以採取更改Memcached的源代碼,增加定期寫入硬盤的功能。對於第二條,我們可以將Memcached服務綁定在內網IP上,通過Linux防火牆進行防護。

4.5 CPU與IO均衡
在一個網站提供的所有功能中,有的功能可能需要消耗大量的服務器端IO資源,像下載,視頻播放等,而有的功能則可能需要消耗大量的服務器CPU資源,像視頻格式轉換,LOG統計等。在一個服務器集羣中,當我們發現某些機器上CPU和IO的利用率相差很大的時候,例如CPU負載很高而IO負責很低,我們可以考慮將該服務器上的某些耗CPU資源的進程換成耗IO的進程,以達到均衡的目的。均衡每一臺機器的CPU和IO消耗,不僅可以獲得更充分的服務器資源利用,而且還能夠支持暫時的過載,遇到突發事件,訪問流量劇增的時候, 實現得體的性能下降(Graceful performance degradation)[34],而不是立即崩潰。

4.6 讀寫分離
如果網站的硬盤讀寫性能是整個網站性能提升的一個瓶頸的話,可以考慮將硬盤的讀,寫功能分開,分別進行優化。在專門用來寫的硬盤上,我們可以在Linux 下使用軟件RAID-0(磁盤冗餘陣列0級)[35]。RAID-0在獲得硬盤IO提升的同時,也會增加整個文件系統的故障率——它等於RAID中所有驅動器的故障率之和。如果需要保持或提高硬盤的容錯能力,就需要實現軟件RAID-1,4或5,它們能在某一個(甚至幾個)磁盤驅動器故障之後仍然保持整個文件系統的正常運行[36],但文件讀寫效率不如RAID-0。而專門用來讀的硬盤,則不用如此麻煩,可以使用普通的服務器硬盤,以降低開銷。

一般的文件系統,會綜合考慮各種大小和格式的文件的讀,寫效率,因而對特定的文件讀或寫的效率不是最優。如果有必要,可以通過選擇文件系統,以及修改文件系統的配置參數來達到對特定文件的讀或寫的效率最大化。比如說,如果文件系統中需要存儲大量的小文件,則可以使用 ReiserFS[37]來替代Linux操作系統默認的ext3系統,因爲ReiserFS是基於平衡樹的文件系統結構,尤其對於大量文件的巨型文件系統,搜索速度要比使用局部的二分查找法的ext3快。 ReiserFS裏的目錄是完全動態分配的,因此不存在ext3中常見的無法回收巨型目錄佔用的磁盤空間的情況。ReiserFS裏小文件(< 4K)可以直接存儲進樹,小文件讀取和寫入的速度更快,樹內節點是按字節對齊的,多個小文件可共享同一個硬盤塊,節約大量空間。ext3使用固定大小的塊分配策略,也就是說,不到4K的小文件也要佔據4K的空間,導致的空間浪費比較嚴重[38]。但ReiserFS對很多Linux內核支持的不是很好,包括2.4.3、2.4.9 甚至相對較新的 2.4.16,如果網站想要使用它,就必須要安裝與它配合的較好的2.4.18內核——一般管理員都不是很樂意使用太新的內核,因爲在它上面運行的軟件,都還沒有經過大量的實踐測試,也許有一些小的bug還沒有被發現,但對於服務器來說,再小的bug也是不能接受的。ReiserFS還是一個較爲年輕的,發展迅速的文件系統,它相對於ext3來說有一個很大的缺陷就是,每次ReiserFS文件系統升級的時候,必須完全重新格式化整個磁盤分區。所以在選擇使用的時候,需要權衡取捨[39]。


5 應用程序層優化

5.1 網站服務器程序的選擇
經統計[40],當前互聯網上有超過50%的網站主機使用Apache[41]服務器程序。 Apache是開源界的首選Web服務器,因爲它的強大和可靠,而且適用於絕大部分的應用場合。但是它的強大有時候卻顯得笨重,配置文件複雜得讓人望而生畏,高併發情況下效率不太高。而輕量級的Web服務器Lighttpd[42]卻是後起之秀,基於單進程多路複用技術,其靜態文件的響應能力遠高於 Apache。 Lighttpd對PHP的支持也很好,還可以通過Fastcgi方式支持其他的語言,比如Python等。雖然Lighttpd是輕量級的服務器,功能上不能跟Apache比,某些複雜應用無法勝任,但即使是大部分內容動態生成的網站,仍免不了會有一些靜態元素,比如圖片、JS腳本、CSS等等,可以考慮將Lighttpd放在Squid的前面,構成 Lighttpd->Squid->Apache的一條處理鏈,Lighttpd在最前面,專門處理靜態內容的請求,把動態內容請求通過 Proxy模塊轉發給Squid,如果Squid中有該請求的內容且沒有過期,則直接返回給Lighttpd。新請求或者過期的頁面請求交由Apache 中的腳本程序來處理。經過Lighttpd和Squid的兩級過濾,Apache需要處理的請求大大減少,減少了Web應用程序的壓力。同時這樣的構架,便於把不同的處理分散到多臺計算機上進行,由Lighttpd在前面統一分發。

在這種架構下,每一級都是可以進行單獨優化的,比如Lighttpd可以採用異步IO方式,Squid可以啓用內存來緩存,Apache可以啓用MPM(Multi -Processing Modules,多道處理模塊)等,並且每一級都可以使用多臺機器來均衡負載,伸縮性好。

著名視頻分享網站YouTube就是選擇使用Lighttpd作爲網站的前臺服務器程序。

5.2 數據庫選擇
MySQL[43]是一個快速的、多線程、多用戶和健壯的SQL數據庫服務器,支持關鍵任務、重負載系統的使用,是最受歡迎的開源數據庫管理系統,是Linux下網站開發的首選。它由MySQL AB開發、發佈和提供支持。

MySQL數據庫能爲網站提供:

高性能。MySQL支持海量,快速的數據庫存儲和讀取。還可以通過使用64位處理器來獲取額外的一些性能,因爲MySQL在內部裏很多時候都使用64位的整數處理。

易用性。MySQL的核心是一個小而快速的數據庫。它的快速連接,快速存取和安全可靠的特性使MySQL非常適合在互聯網站上使用。

開放性。MySQL提供多種後臺存儲引擎的選擇,如MyISAM, Heap, InnoDB,Berkeley Db等。缺省格式爲MyISAM。 MyISAM 存儲引擎與磁盤兼容的非常好[44]。

支持企業級應用。MySQL有一個用於記錄數據改變的二進制日誌。因爲它是二進制的,這一日誌能夠快速地將數據的更改從一臺機器複製(replication)到另一臺機器上。即使服務器崩潰,這一二進制日誌也能夠保持完整。這一特性通常被用來搭建數據庫集羣,以支持更大的流量訪問要求[30](圖5)。


 

MySQL也有一些它自身的缺陷,如缺乏圖形界面,缺乏存儲過程, 還不支持觸發器,參照完整性,子查詢和數據表視圖等,但這些功能都在開發者的TO-DO列表當中。這就是開源的力量:你永遠可以期待更好。

國外的Yahoo!,國內的新浪,搜狐等很多大型商業網站都使用MySQL 作爲後臺數據庫。對於一般的網站系統,無論從成本還是性能上考慮,MySQL應該是最佳的選擇。

5.3 服務器端腳本解析器的選擇
目前最常見的服務器端腳本有三種:ASP(Active Server Pages),JSP(Java Server Pages),PHP (Hypertext Preprocessor)[45][46]。

ASP全名Active Server Pages,以及它的升級ASP.NET,是微軟公司出品的一個WEB服務器端的開發環境,利用它可以產生和運行動態的、交互的、高性能的WEB服務應用程序。ASP採用腳本語言VBScript(C#)作爲自己的開發語言。 但因爲只能運行在Windows環境下,這裏我們不討論它。

PHP是一種跨平臺的服務器端的嵌入式腳本語言。它大量地借用C,Java和Perl語言的語法,並耦合PHP自己的特性,使WEB開發者能夠快速地寫出動態生成頁面。它支持目前絕大多數數據庫。PHP也是開源的,它的發行遵從GPL開源協議,你可以從 PHP官方站點(http://www.php.net)自由下載到它的二進制安裝文件及全部的源代碼。如果在Linux平臺上與MySQL搭配使用,PHP是最佳的選擇。

JSP是Sun公司推出的新一代站點開發語言,是Java語言除Java應用程序和Java Applet之外的第三個應用。Jsp可以在Serverlet和JavaBean的支持下,完成功能強大的站點程序。作爲採用Java技術家族的一部分,以及Java 2(企業版體系結構)的一個組成部分,JSP技術擁有Java技術帶來的所有優點,包括優秀的跨平臺性,高度可重用的組件設計,健壯性和安全性等,能夠支持高度複雜的基於Web的應用。

除了這三種常見的腳本之外,在Linux下我們其實還有很多其他的選擇:Python(Google使用),Perl等,如果作爲CGI調用,那麼可選擇範圍就更廣了。使用這些不太常見的腳本語言的好處是,它們對於某些特殊的應用有別的腳本所不具有的優勢;不好的地方是,這些腳本語言在國內使用的人比較少,當碰到技術上的問題的時候,能找到的資料也較少。

5.4 可配置性
在大型網站開發過程中,不管使用什麼技術,網站的可配置性是必須的。在網站的後期運營過程中,肯定會有很多的需求變更。如果每一次的需求變更都會導致修改源代碼,那麼,這個網站的開發可以說是失敗的。

首先,也是最重要的一點,功能和展示必須分開。PHP和JSP都支持模板技術,如PHP的 Smarty,Phplib,JSP的JSTL(JSP Standard Tag Library)等。核心功能使用腳本語言編寫,前臺展示使用帶特殊標籤的HTML,不僅加快了開發速度,而且方便以後的維護和升級[47]。

其次,對於前臺模板,一般還需要將頁面的頭,尾單獨提取出來,頁面的主體部分也按模塊或者功能拆分。對CSS,JS等輔助性的代碼,也建議以單獨的文件形式存放。這樣不僅方便管理,修改,而且還可以在用戶訪問的時候進行緩存,減少網絡流量,減輕服務器壓力。

再次,對於核心功能腳本,必須將與服務器相關的配置內容,如數據庫連接配置,腳本頭文件路徑等,與代碼分離開。尤其當網站使用集羣技術,CDN加速等技術的時候,每一臺服務器上的配置可能都會不一樣。如果不使用配置文件,則需要同時維護幾份不同的代碼,很容易出錯。

最後,應該儘量做到修改配置文件後能實時生效,避免修改配置文件之後需要重啓服務程序的情況。

5.5 封裝和中間層思想
在功能塊層次,如果使用JSP,基於純面嚮對象語言Java的面向對象思想,類似數據庫連接,會話管理等基本功能都已經封裝成類了。如果使用PHP,則需要在腳本代碼中顯式的封裝,將每一個功能塊封裝成一個函數,一個文件或者一個類。

在更高的層次,可以將網站分爲表示層,邏輯層,持久層,分別進行封裝,做到當某一層架構發生變化時,不會影響到其他層。比如新浪播客在一次升級的時候,將持久層的數據庫由原來的集中式改爲分佈式架構,因爲封裝了數據庫連接及所有操作[附錄2],做到了不修改任何上層代碼,平穩的實現了過渡。近來流行的MVC架構,將整個網站拆分成Model(模型/邏輯)、View(視圖/界面)、Controller(控制/流程)三個部分,而且有很多優秀的代碼框架可供選擇使用, 像JSP的Structs,Spring,PHP的php.MVC, Studs 等。使用現成的代碼框架,可以使網站開發事半功倍。


6 擴容、容錯處理

6.1 擴容
一個大型網站,在設計架構的時候,必須考慮到以後可能的容量擴充。新浪播客在設計時充分地考慮了這一點。對於視頻分享類網站來說,視頻存儲空間消耗是巨大的。新浪播客在主存儲服務器上,採用配置文件形式指定每一個存儲盤櫃上存儲的視頻文件的ID範圍。當前臺服務器需要讀取一個視頻的時候,首先通過詢問主存儲服務器上的接口獲得該視頻所在的盤櫃及目錄地址,然後再去該盤櫃讀取實際的視頻文件。這樣如果需要增加存儲用的盤櫃,只需要修改配置文件即可,前臺程序絲毫不受影響。

新浪播客採用MySQL數據庫集羣,在邏輯層封裝了所有的數據庫連接及操作。當數據庫存儲架構發生改變的時候,如增加一臺主庫,將某些數據表獨立成庫,增加讀取數據用的從庫等,都只需要修改封裝了的數據庫操作類,上層代碼不用修改。

新浪播客的前臺頁面服務器使用F5公司的硬件第四層交換機,網通,電信分別導向不同的虛擬IP,每一個虛擬IP後面又有多個服務器提供服務。當訪問流量增大的時候,可以很方便往虛擬IP後面增加服務器,分擔壓力。

6.2 容錯
對於商業性網站來說,可用性是非常重要的。7*24的訪問要求網站具有很強的容錯能力。錯誤包括網絡錯誤,服務器錯誤以及應用程序錯誤。

2006年12月27日臺灣東部外海發生里氏7.6級地震,造成途徑臺灣海峽的多條海底電纜中斷,導致許多國外網站,像MSN, NBA, Yahoo!(英文主站)等國內無法訪問,但也有例外,以Google爲代表的在國內建設有分佈式數據節點的很多網站卻仍然可以訪問。雖然說地震造成斷網是不可抗原因,但如果在這種情況下網站仍然可以訪問,無疑能給網站用戶留下深刻的印象。這件事情給大型商業網站留下的教訓是:網站需要在用戶主要分佈區域保持數據存在,以防止可能的網絡故障。

對於服務器錯誤,一般採取冗餘設計的方法來避免。對於存儲服務器(主要是負責寫入的服務器),可以使用RAID(冗餘磁盤陣列);對於數據庫(主要是負責寫入的主庫),可以採用雙主庫設計[30];對於提供服務的前臺,則可以使用第四層交換的集羣,由多臺服務器同時提供服務,不僅分擔了流量壓力,同時還可以互相作爲備份。

在應用層程序中,也要考慮“用戶友好”的出錯設計。典型例子如HTTP 404 出錯頁面,程序內部錯誤處理,錯誤返回提示等,儘可能的做到人性化。


7 總結及展望

7.1 總結



對於一個高併發高流量的網站來說,任何一個環節的瓶頸都會造成網站性能的下降,影響用戶體驗,進而造成巨大的經濟損失。在全互聯網層面,應該使用分佈式設計,縮短網站與用戶的網絡距離,減少主幹網上的流量,以及防止在網絡意外情況下網站無法訪問的問題。在局域網層面,應該使用服務器集羣,一方面可以支撐更大的訪問量,另一方面也作爲冗餘備份,防止服務器故障導致的網站無法訪問。在單服務器層面,應該配置操作系統,文件系統及應用層軟件,均衡各種資源的消耗,消除系統性能瓶頸,充分發揮服務器的潛能。在應用層,可以通過各種緩存來提升程序的效率,減少服務器資源消耗(圖6)。另外,還需要合理設計應用層程序,爲以後的需求變更,擴容做好準備。

在每一個層次,都需要考慮容錯的問題,嚴格消除單點故障,做到無論應用層程序錯誤,服務器軟件錯誤,服務器硬件錯誤,還是網絡錯誤,都不影響網站服務。

7.2展望
當前Linux環境下有著名的LAMP(Linux+Apache+MySQL+PHP/PERL/PYTHON)網站建設方案,但只是針對一般的中小網站而言。對於高併發高流量的大型商業網站,還沒有一個完整的,性價比高的解決方案。除去服務器,硬盤,帶寬等硬件投資外,還需要花費大量的預算和時間精力在軟件解決方案上。

隨着互聯網的持續發展,Web2.0的興起,在可以預見的未來裏,互聯網的用戶持續增多,提供用戶參與的網站不斷增加,用戶參與的內容日益增長,越來越多的網站的併發量,訪問量會達到一個新的高度,這就會促使越來越多的個人,公司以及研究機構來關注高併發高流量的網站架構問題。就像Web1.0成就了無數中小網站,成就了LAMP一樣,Web2.0註定也會成就一個新的,高效的,成本較低的解決方案。這個方案應該包括透明的第三方CDN網絡加速服務,價格低廉的第四層甚至更高層網絡交換設備,優化了網絡性能的操作系統,優化了讀寫性能,分佈式,高可靠的文件系統,揉合了內存,硬盤等各個級別緩存的HTTP服務器,更爲高效的服務器端腳本解析器,以及封裝了大部分細節的應用層設計框架。

技術的進步永無止境。我們期待互聯網更爲美好的明天。

發佈了39 篇原創文章 · 獲贊 1 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章