|
Web2.0的興起,掀起了互聯(lián)網(wǎng)新一輪的網(wǎng)絡(luò)創(chuàng)業(yè)大潮。以用戶為導向的新網(wǎng)站建設(shè)概念,細分了網(wǎng)站功能和用戶群,不僅成功的造就了一大批新生的網(wǎng)站,也極大的方便了上網(wǎng)的人們。但Web2.0以用戶為導向的理念,使得新生的網(wǎng)站有了新的特點——高并發(fā),高流量,數(shù)據(jù)量大,邏輯復雜等,對網(wǎng)站建設(shè)也提出了新的要求。
本文圍繞高并發(fā)高流量的網(wǎng)站架構(gòu)設(shè)計問題,主要研究討論了以下內(nèi)容: 首先在整個網(wǎng)絡(luò)的高度討論了使用鏡像網(wǎng)站,CDN內(nèi)容分發(fā)網(wǎng)絡(luò)等技術(shù)對負載均衡帶來的便利及各自的優(yōu)缺點比較。然后在局域網(wǎng)層次對第四層交換技術(shù),包括硬件解決方案F5和軟件解決方案LVS,進行了簡單的討論。接下來在單服務器層次,本文著重討論了單臺服務器的Socket優(yōu)化,硬盤級緩存技術(shù),內(nèi)存級緩存技術(shù),CPU與IO平衡技術(shù)(即以運算為主的程序與以數(shù)據(jù)讀寫為主的程序搭配部署),讀寫分離技術(shù)等。在應用層,本文介紹了一些大型網(wǎng)站常用的技術(shù),以及選擇使用該技術(shù)的理由。最后,在架構(gòu)的高度討論了網(wǎng)站擴容,容錯等問題。 本文以理論與實踐相結(jié)合的形式,結(jié)合作者實際工作中得到的經(jīng)驗,具有較廣泛的適用性。 1.2 互聯(lián)網(wǎng)網(wǎng)站建設(shè)的新趨勢 高性能和高可擴展性。2000 年 5 月,訪問量排名世界第一(統(tǒng)計數(shù)據(jù)來源[5])的Yahoo [6]聲稱其日頁瀏覽數(shù)達到 6 億 2500 萬,即每秒約 30,000 次HTTP 請求(按每個頁面瀏覽平均產(chǎn)生 4 次請求計算) 。這樣大規(guī)模的訪問量對服務的性能提出了非常高的要求。更為重要的是, 互聯(lián)網(wǎng)受眾的廣泛性,使得成功的互聯(lián)網(wǎng)服務的訪問量增長潛力和速度非常大,因此服務系統(tǒng)必須具有非常好的可擴展性,以應付將來可能的服務增長。 支持高度并發(fā)的訪問。高度并發(fā)的訪問對服務的存儲與并發(fā)能力提出了很高的要求,當前主流的超標量和超流水線處理器能處理的并發(fā)請求數(shù)是有限的,因為隨著并發(fā)數(shù)的上升,進程調(diào)度的開銷會很快上升?;ヂ?lián)網(wǎng)廣域網(wǎng)的本質(zhì)決定了其訪問的延遲時間較長,因此一個請求完成時間也較長,按從請求產(chǎn)生到頁面下載完成 3 秒計算, Yahoo 在 2000 年 5 月時平均有 90,000 個并發(fā)請求。而且對于較復雜的服務,服務器往往要維護用戶會話的信息,例如一個互聯(lián)網(wǎng)網(wǎng)站如果每天有 100 萬次用戶會話,每次 20分鐘的話,那平均同時就會有約 14000 個并發(fā)會話。 高可用性?;ヂ?lián)網(wǎng)服務的全球性決定了其每天 24 小時都會有用戶訪問,因此任何服務的停止都會對用戶造成影響。而對于電子商務等應用,暫時的服務中止則意味著客戶的永久失去及大量的經(jīng)濟損失,例如ebay.com[7]1999 年 6 月的一次 22小時的網(wǎng)站不可訪問,對此網(wǎng)站的 380萬用戶的忠誠度造成巨大影響,使得 Ebay 公司不得不支付了近500萬美元用于補償客戶的損失,而該公司的市值同期下降了 40 億美元[8]。因此,關(guān)鍵互聯(lián)網(wǎng)應用的可用性要求非常高。 1.3 新浪播客的簡介 2.1 鏡像網(wǎng)站技術(shù) 鏡像網(wǎng)站是指將一個完全相同的站點放到幾個服務器上,分別有自己的URL,這些服務器上的網(wǎng)站互相稱為鏡像網(wǎng)站[13]。鏡像網(wǎng)站和主站并沒有太大差別,或者可以視為主站的拷貝。鏡像網(wǎng)站的好處是:如果不能對主站作正常訪問(如服務器故障,網(wǎng)絡(luò)故障或者網(wǎng)速太慢等),仍能通過鏡像服務器獲得服務。不便之處是:更新網(wǎng)站內(nèi)容的時候,需要同時更新多個服務器;需要用戶記憶超過一個網(wǎng)址,或需要用戶選擇訪問多個鏡像網(wǎng)站中的一個,而用戶選擇的,不一定是最優(yōu)的。在用戶選擇的過程中,缺乏必要的可控性。 在互聯(lián)網(wǎng)發(fā)展的初期,互聯(lián)網(wǎng)上的網(wǎng)站內(nèi)容很少,而且大都是靜態(tài)內(nèi)容,更新頻率底。但因為服務器運算能力低,帶寬小,網(wǎng)速慢,熱門網(wǎng)站的訪問壓力還是很大。鏡像網(wǎng)站技術(shù)在這種情況下作為一種有效解決方案,被廣泛采用。隨著互聯(lián)網(wǎng)的發(fā)展,越來越多的網(wǎng)站使用服務器端腳本動態(tài)生成內(nèi)容,同步更新越來越困難,對可控性要求越來越高,鏡像技術(shù)因為不能滿足這類網(wǎng)站的需要,漸漸的淡出了人們的視線。但有一些大型的軟件下載站,因為符合鏡像網(wǎng)站的條件——下載的內(nèi)容是靜態(tài)的,更新頻率較低,對帶寬,速度要求又比較高,如國外的SourceForge (http://www.SourceForge.net,著名開源軟件托管網(wǎng)站),F(xiàn)edora(http://,RedHat贊助的Linux發(fā)行版),國內(nèi)的華軍軟件園(http://www.onlinedown.net),天空軟件站(http://www.)等,還在使用這項技術(shù)(圖1)。
下圖:SourceForge下載時的鏡像選擇頁面 在網(wǎng)站建設(shè)的過程中,可以根據(jù)實際情況,將靜態(tài)內(nèi)容作一些鏡像,以加快訪問速度,提升用戶體驗。 2.2 CDN內(nèi)容分發(fā)網(wǎng)絡(luò) CDN與鏡像網(wǎng)站技術(shù)的不同之處在于網(wǎng)站代替用戶去選擇最優(yōu)的內(nèi)容服務器,增強了可控制性。CDN其實是夾在網(wǎng)頁瀏覽者和被訪問的服務器中間的一層鏡像或者說緩存,瀏覽者訪問時點擊的還是服務器原來的URL地址,但是看到的內(nèi)容其實是對瀏覽者來說最優(yōu)的一臺鏡像服務器上的頁面緩存內(nèi)容。這是通過調(diào)整服務器的域名解析來實現(xiàn)的。使用CDN技術(shù)的域名解析服務器需要維護一個鏡像服務器列表和一份來訪IP到鏡像服務器的對應表。當一個用戶的請求到來的時候,根據(jù)用戶的IP,查詢對應表,得到最優(yōu)的鏡像服務器的IP地址,返回給用戶。這里的最優(yōu),需要綜合考慮服務器的處理能力,帶寬,離訪問者的距離遠近等因素。當某個地方的鏡像網(wǎng)站流量過大,帶寬消耗過快,或者出現(xiàn)服務器,網(wǎng)絡(luò)等故障的時候,可以很方便的設(shè)置將用戶的訪問轉(zhuǎn)到另外一個地方(圖2)。這樣就增強了可控制性。
CDN網(wǎng)絡(luò)加速技術(shù)也有它的局限性。首先,因為內(nèi)容更新的時候,需要同步更新多臺鏡像服務器,所以它也只適用于內(nèi)容更新不太頻繁,或者對實時性要求不是很高的網(wǎng)站;其次,DNS解析有緩存,當某一個鏡像網(wǎng)站的訪問需要轉(zhuǎn)移時,主DNS服務器更改了IP解析結(jié)果,但各地的DNS服務器緩存更新會滯后一段時間,這段時間內(nèi)用戶的訪問仍然會指向該服務器,可控制性依然有不足。 目前,國內(nèi)訪問量較高的大型網(wǎng)站如新浪、網(wǎng)易等的資訊頻道,均使用CDN網(wǎng)絡(luò)加速技術(shù)(圖3),雖然網(wǎng)站的訪問量巨大,但無論在什么地方訪問,速度都會很快。但論壇,郵箱等更新頻繁,實時性要求高的頻道,則不適合使用這種技術(shù)。
ChinaCache的服務節(jié)點全球超過130個, 其中中國節(jié)點超過80個, 覆蓋全國主要6大網(wǎng)絡(luò)的主要省份[15]。 2.3 應用層分布式設(shè)計 2.4 網(wǎng)絡(luò)層架構(gòu)小結(jié) 3 交換層架構(gòu) 3.1 第四層交換簡介 按照OSI[16]七層模型,第四層是傳輸層。傳輸層負責端到端通信,在IP協(xié)議棧中是TCP和UDP所在的協(xié)議層。TCP和UDP數(shù)據(jù)包中包含端口號(port number),它們可以唯一區(qū)分每個數(shù)據(jù)包所屬的協(xié)議和應用程序。接收端計算機的操作系統(tǒng)根據(jù)端口號確定所收到的IP包類型,并把它交給合適的高層程序。IP地址和端口號的組合通常稱作“插口(Socket)”。 第四層交換的一個簡單定義是:它是一種傳輸功能,它決定傳輸不僅僅依據(jù)MAC地址(第二層網(wǎng)橋)或源/目標IP地址(第三層路由),而且依據(jù)IP地址與TCP/UDP (第四層) 應用端口號的組合(Socket)[17]。第四層交換功能就像是虛擬IP,指向?qū)嶋H的服務器。它傳輸?shù)臄?shù)據(jù)支持多種協(xié)議,有HTTP、FTP、NFS、Telnet等。 以HTTP協(xié)議為例,在第四層交換中為每個服務器組設(shè)立一個虛擬IP(Virtue IP,VIP),每組服務器支持某一個或幾個域名。在域名服務器(DNS)中存儲服務器組的VIP,而不是某一臺服務器的真實地址。 當用戶請求頁面時,一個帶有目標服務器組的VIP連接請求發(fā)送給第四層交換機。第四層交換機使用某種選擇策略,在組中選取最優(yōu)的服務器,將數(shù)據(jù)包中的目標VIP地址用實際服務器的IP地址取代,并將連接請求傳給該服務器。第四層交換一般都實現(xiàn)了會話保持功能,即同一會話的所有的包由第四層交換機進行映射后,在用戶和同一服務器間進行傳輸[18]。 第四層交換按實現(xiàn)分類,分為硬件實現(xiàn)和軟件實現(xiàn)。 3.2 硬件實現(xiàn) 3.3 軟件實現(xiàn) 4 服務器優(yōu)化 4.1 服務器整體性能考慮 對于價值昂貴的服務器來說,怎樣配置才能發(fā)揮它的最大功效,又不至于影響正常的服務,這是在設(shè)計網(wǎng)站架構(gòu)的時候必須要考慮的。常見的影響服務器的處理速度的因素有:網(wǎng)絡(luò)連接,硬盤讀寫,內(nèi)存空間,CPU速度。如果服務器的某一個部件滿負荷運轉(zhuǎn)仍然低于需要,而其他部件仍有能力剩余,我們將之稱為性能瓶頸。服務器想要發(fā)揮最大的功效,關(guān)鍵的是消除瓶頸,讓所有的部件都被充分的利用起來。 4.2 Socket優(yōu)化 /proc/sys/net/ipv4/tcp_window_scaling “1”(1表示啟用該選項,0表示關(guān)閉,下同) 啟用 RFC[25] 1323[26] 定義的 window scaling;要支持超過 64KB 的窗口,必須啟用該值。 /proc/sys/net/ipv4/tcp_sack “1”啟用有選擇的應答(Selective Acknowledgment),通過有選擇地應答亂序接收到的報文來提高性能(這樣可以讓發(fā)送者只發(fā)送丟失的報文段);對于廣域網(wǎng)通信來說,這個選項應該啟用,但是這也會增加對 CPU 的占用。 /proc/sys/net/ipv4/tcp_timestamps “1” 以一種比重發(fā)超時更精確的方法(參閱 RFC 1323)來啟用對 RTT 的計算;為了實現(xiàn)更好的性能應該啟用這個選項。 /proc/sys/net/ipv4/tcp_mem “24576 32768 49152” 確定 TCP 棧應該如何反映內(nèi)存使用;每個值的單位都是內(nèi)存頁(通常是 4KB)。第一個值是內(nèi)存使用的下限。第二個值是內(nèi)存壓力模式開始對緩沖區(qū)使用應用壓力的上限。第三個值是內(nèi)存上限。超過這個上限時可以將報文丟棄,從而減少對內(nèi)存的使用。 /proc/sys/net/ipv4/tcp_wmem “4096 16384 131072” 為自動調(diào)優(yōu)定義每個 socket 使用的內(nèi)存。第一個值是為 socket 的發(fā)送緩沖區(qū)分配的最少字節(jié)數(shù)。第二個值是默認值(該值會被 wmem_default 覆蓋),緩沖區(qū)在系統(tǒng)負載不重的情況下可以增長到這個值。第三個值是發(fā)送緩沖區(qū)空間的最大字節(jié)數(shù)(該值會被 wmem_max 覆蓋)。 /proc/sys/net/ipv4/tcp_westwood “1” 啟用發(fā)送者端的擁塞控制算法,它可以維護對吞吐量的評估,并試圖對帶寬的整體利用情況進行優(yōu)化;對于 WAN 通信來說應該啟用這個選項。 與其他調(diào)優(yōu)努力一樣,最好的方法實際上就是不斷進行實驗。具體應用程序的行為、處理器的速度以及可用內(nèi)存的多少都會影響到這些參數(shù)對性能作用的效果。在某些情況中,一些認為有益的操作可能恰恰是有害的(反之亦然)。因此,需要逐一試驗各個選項,然后檢查每個選項的結(jié)果,最后得出最適合具體機器的一套參數(shù)。 如果重啟了 GNU/Linux 系統(tǒng),設(shè)置的內(nèi)核參數(shù)都會恢復成默認值。為了將所設(shè)置的值作為這些參數(shù)的默認值,可以使用 /etc/rc.local 文件,在系統(tǒng)每次啟動時自動將這些參數(shù)配置成所需要的值。 在檢測每個選項的更改帶來的效果的時候,GNU/Linux上有一些非常強大的工具可以使用: ping 這是用于檢查主機的可用性的最常用的工具,也可以用于計算網(wǎng)絡(luò)帶寬延時。 traceroute 打印連接到特定網(wǎng)絡(luò)主機所經(jīng)過的一系列路由器和網(wǎng)關(guān)的路徑(路由),從而確定每個 hop 之間的延時。 netstat 確定有關(guān)網(wǎng)絡(luò)子系統(tǒng)、協(xié)議和連接的各種統(tǒng)計信息。 tcpdump 顯示一個或多個連接的協(xié)議級的報文跟蹤信息,其中包括時間信息,可以使用這些信息來研究不同協(xié)議的報文時間。 Ethereal 以一個易于使用的圖形化界面提供 tcpump (報文跟蹤)的信息,支持報文過濾功能。 iperf 測量 TCP 和 UDP 的網(wǎng)絡(luò)性能;測量最大帶寬,并匯報延時和數(shù)據(jù)報的丟失情況。 4.3 硬盤級緩存 Squid是一個高性能的代理緩存服務器。和一般的代理緩存軟件不同,Squid用一個單獨的、非模塊化的、I/O驅(qū)動的進程來處理所有的客戶端請求。它接受來自客戶端對目標對象的請求并適當?shù)靥幚磉@些請求。比如說,用戶通過瀏覽器想下載(即瀏覽)一個web頁面,瀏覽器請求Squid為它取得這個頁面。Squid隨之連接到頁面所在的原始服務器并向服務器發(fā)出取得該頁面的請求。取得頁面后,Squid再將頁面返回給用戶端瀏覽器,并且同時在Squid本地緩存目錄里保存一份副本。當下一次有用戶需要同一頁面時,Squid可以簡單地從緩存中讀取它的副本,直接返回給用戶,而不用再次請求原始服務器。當前的Squid可以處理HTTP, FTP, GOPHER, SSL和WAIS等協(xié)議。 Squid默認通過檢測HTTP協(xié)議頭的Expires和 Cache-Control字段來決定緩存的時間。在實際應用中,可以顯式的在服務器端腳本中輸出HTTP頭,也可以通過配置apache的mod_expires模塊,讓apache自動的給每一個網(wǎng)頁加上過期時間。對于靜態(tài)內(nèi)容,如圖片,視頻文件,供下載的軟件等,還可以針對文件類型(擴展名),用 Squid 的 refresh_pattern 來指定緩存時間。 Squid 運行的時候,默認會在硬盤上建兩層hash目錄,用來存儲緩存的Object。它還會在內(nèi)存中建立一個Hash Table,用來記錄硬盤中Object分布的情況。如果Squid配置成為一個Squid集群中的一個的話,它還會建立一個 Digest Table(摘要表),用來存儲其它 Squid 上的Object摘要。當用戶端想要的資料本地硬盤上沒有時,可以很快的知道應該去集群中的哪一臺機器獲得。在硬盤空間快要達到配置限額的時候,可以配置使用某種策略(默認使用LRU:Least Recently Used-最近最少用)刪除一些Object,從而騰出空間[28][29]。 集群中的Squid Server 之間可以有兩種關(guān)系:第一種關(guān)系是:Child 和 Parent。當 Child Squid Server 沒有資料時,會直接向 Parent Squid Server 要資料,然后一直等,直到 Parent 給它資料為止。 第二種關(guān)系是:Sibling 和 Sibling。當 Squid Server 沒有資料時,會先向 Sibling 的 Squid Server 要資料,如果 Sibling 沒資料,就跳過它向 Parent 要或直接上原始網(wǎng)站去拿。 默認配置的Squid,沒有經(jīng)過任何優(yōu)化的時候,一般可以達到 50% 的命中率[30](圖4)。如果需要,還可以通過參數(shù)優(yōu)化,拆分業(yè)務,優(yōu)化文件系統(tǒng)等辦法,使得Squid達到 90% 以上的緩存命中率。 Squid處理TCP連接消耗的服務器資源比真正的HTTP服務器要小的多,當Squid分擔了大部分連接,網(wǎng)站的承壓能力就大大增強了。
藍線表示Squid的流量,綠色部分表示Apache流量 4.4 內(nèi)存級緩存 Memcached是danga.com(運營Live Journal[32]的技術(shù)團隊)開發(fā)的一套非常優(yōu)秀的分布式內(nèi)存對象緩存系統(tǒng),用于在動態(tài)系統(tǒng)中減少數(shù)據(jù)庫負載,提升性能。和 Squid 的前端緩存加速不同,它是通過基于內(nèi)存的對象緩存來減少數(shù)據(jù)庫查詢的方式改善網(wǎng)站的性能,而其中最吸引人的一個特性就是支持分布式部署;也就是說可以在一群機器上建立一堆 Memcached 服務,每個服務可以根據(jù)具體服務器的硬件配置使用不同大小的內(nèi)存塊,這樣,理論上可以建立一個無限大的基于內(nèi)存的緩存系統(tǒng)。 Memcached 是以守護程序方式運行于一個或多個服務器中,隨時接受客戶端的連接操作,客戶端可以由各種語言編寫,目前已知的客戶端 API 包括 Perl/PHP/Python/Ruby/Java/C#/C 等等[附錄1]??蛻舳耸紫扰c Memcached 服務建立連接,然后存取對象。每個被存取的對象都有一個唯一的標識符 key,存取操作均通過這個 key 進行,保存的時候還可以設(shè)置有效期。保存在 Memcached 中的對象實際上是放置在內(nèi)存中的,而不是在硬盤上。Memcached 進程運行之后,會預申請一塊較大的內(nèi)存空間,自己進行管理,用完之后再申請一塊,而不是每次需要的時候去向操作系統(tǒng)申請。Memcached將對象保存在一個巨大的Hash表中,它還使用NewHash算法來管理Hash表,從而獲得進一步的性能提升。所以當分配給Memcached的內(nèi)存足夠大的時候,Memcached的時間消耗基本上只是網(wǎng)絡(luò)Socket連接了[33]。 Memcached也有它的不足。首先它的數(shù)據(jù)是保存在內(nèi)存當中的,一旦服務進程重啟(進程意外被關(guān)掉,機器重啟等),數(shù)據(jù)會全部丟失。其次Memcached以root權(quán)限運行,而且Memcached本身沒有任何權(quán)限管理和認證功能,安全性不足。第一條是Memcached作為內(nèi)存緩存服務使用無法避免的,當然,如果內(nèi)存中的數(shù)據(jù)需要保存,可以采取更改Memcached的源代碼,增加定期寫入硬盤的功能。對于第二條,我們可以將Memcached服務綁定在內(nèi)網(wǎng)IP上,通過Linux防火墻進行防護。 4.5 CPU與IO均衡 4.6 讀寫分離 一般的文件系統(tǒng),會綜合考慮各種大小和格式的文件的讀,寫效率,因而對特定的文件讀或?qū)懙男什皇亲顑?yōu)。如果有必要,可以通過選擇文件系統(tǒng),以及修改文件系統(tǒng)的配置參數(shù)來達到對特定文件的讀或?qū)懙男首畲蠡?。比如說,如果文件系統(tǒng)中需要存儲大量的小文件,則可以使用ReiserFS[37]來替代Linux操作系統(tǒng)默認的ext3系統(tǒng),因為ReiserFS是基于平衡樹的文件系統(tǒng)結(jié)構(gòu),尤其對于大量文件的巨型文件系統(tǒng),搜索速度要比使用局部的二分查找法的ext3快。 ReiserFS里的目錄是完全動態(tài)分配的,因此不存在ext3中常見的無法回收巨型目錄占用的磁盤空間的情況。ReiserFS里小文件(< 4K)可以直接存儲進樹,小文件讀取和寫入的速度更快,樹內(nèi)節(jié)點是按字節(jié)對齊的,多個小文件可共享同一個硬盤塊,節(jié)約大量空間。ext3使用固定大小的塊分配策略,也就是說,不到4K的小文件也要占據(jù)4K的空間,導致的空間浪費比較嚴重[38]。 但ReiserFS對很多Linux內(nèi)核支持的不是很好,包括2.4.3、2.4.9 甚至相對較新的 2.4.16,如果網(wǎng)站想要使用它,就必須要安裝與它配合的較好的2.4.18內(nèi)核——一般管理員都不是很樂意使用太新的內(nèi)核,因為在它上面運行的軟件,都還沒有經(jīng)過大量的實踐測試,也許有一些小的bug還沒有被發(fā)現(xiàn),但對于服務器來說,再小的bug也是不能接受的。ReiserFS還是一個較為年輕的,發(fā)展迅速的文件系統(tǒng),它相對于ext3來說有一個很大的缺陷就是,每次ReiserFS文件系統(tǒng)升級的時候,必須完全重新格式化整個磁盤分區(qū)。所以在選擇使用的時候,需要權(quán)衡取舍[39]。 5 應用程序?qū)觾?yōu)化 5.1 網(wǎng)站服務器程序的選擇 經(jīng)統(tǒng)計[40],當前互聯(lián)網(wǎng)上有超過50%的網(wǎng)站主機使用Apache[41]服務器程序。 Apache是開源界的首選Web服務器,因為它的強大和可靠,而且適用于絕大部分的應用場合。但是它的強大有時候卻顯得笨重,配置文件復雜得讓人望而生畏,高并發(fā)情況下效率不太高。而輕量級的Web服務器Lighttpd[42]卻是后起之秀,基于單進程多路復用技術(shù),其靜態(tài)文件的響應能力遠高于Apache。 Lighttpd對PHP的支持也很好,還可以通過Fastcgi方式支持其他的語言,比如Python等。 雖然Lighttpd是輕量級的服務器,功能上不能跟Apache比,某些復雜應用無法勝任,但即使是大部分內(nèi)容動態(tài)生成的網(wǎng)站,仍免不了會有一些靜態(tài)元素,比如圖片、JS腳本、CSS等等,可以考慮將Lighttpd放在Squid的前面,構(gòu)成 Lighttpd->Squid->Apache的一條處理鏈,Lighttpd在最前面,專門處理靜態(tài)內(nèi)容的請求,把動態(tài)內(nèi)容請求通過Proxy模塊轉(zhuǎn)發(fā)給Squid,如果Squid中有該請求的內(nèi)容且沒有過期,則直接返回給Lighttpd。新請求或者過期的頁面請求交由Apache中的腳本程序來處理。經(jīng)過Lighttpd和Squid的兩級過濾,Apache需要處理的請求大大減少,減少了Web應用程序的壓力。同時這樣的構(gòu)架,便于把不同的處理分散到多臺計算機上進行,由Lighttpd在前面統(tǒng)一分發(fā)。 在這種架構(gòu)下,每一級都是可以進行單獨優(yōu)化的,比如Lighttpd可以采用異步IO方式,Squid可以啟用內(nèi)存來緩存,Apache可以啟用MPM(Multi -Processing Modules,多道處理模塊)等,并且每一級都可以使用多臺機器來均衡負載,伸縮性好。 著名視頻分享網(wǎng)站YouTube就是選擇使用Lighttpd作為網(wǎng)站的前臺服務器程序。 5.2 數(shù)據(jù)庫選擇 MySQL數(shù)據(jù)庫能為網(wǎng)站提供: 高性能。MySQL支持海量,快速的數(shù)據(jù)庫存儲和讀取。還可以通過使用64位處理器來獲取額外的一些性能,因為MySQL在內(nèi)部里很多時候都使用64位的整數(shù)處理。 易用性。MySQL的核心是一個小而快速的數(shù)據(jù)庫。它的快速連接,快速存取和安全可靠的特性使MySQL非常適合在互聯(lián)網(wǎng)站上使用。 開放性。MySQL提供多種后臺存儲引擎的選擇,如MyISAM, Heap, InnoDB,Berkeley Db等。缺省格式為MyISAM。 MyISAM 存儲引擎與磁盤兼容的非常好[44]。 支持企業(yè)級應用。MySQL有一個用于記錄數(shù)據(jù)改變的二進制日志。因為它是二進制的,這一日志能夠快速地將數(shù)據(jù)的更改從一臺機器復制(replication)到另一臺機器上。即使服務器崩潰,這一二進制日志也能夠保持完整。這一特性通常被用來搭建數(shù)據(jù)庫集群,以支持更大的流量訪問要求[30](圖5)。 圖
國外的Yahoo!,國內(nèi)的新浪,搜狐等很多大型商業(yè)網(wǎng)站都使用MySQL 作為后臺數(shù)據(jù)庫。對于一般的網(wǎng)站系統(tǒng),無論從成本還是性能上考慮,MySQL應該是最佳的選擇。 5.3 服務器端腳本解析器的選擇 ASP全名Active Server Pages,以及它的升級ASP.NET,是微軟公司出品的一個WEB服務器端的開發(fā)環(huán)境,利用它可以產(chǎn)生和運行動態(tài)的、交互的、高性能的WEB服務應用程序。ASP采用腳本語言VBScript(C#)作為自己的開發(fā)語言。 但因為只能運行在Windows環(huán)境下,這里我們不討論它。 PHP是一種跨平臺的服務器端的嵌入式腳本語言。它大量地借用C,Java和Perl語言的語法, 并耦合PHP自己的特性,使WEB開發(fā)者能夠快速地寫出動態(tài)生成頁面。它支持目前絕大多數(shù)數(shù)據(jù)庫。PHP也是開源的,它的發(fā)行遵從GPL開源協(xié)議,你可以從 PHP官方站點(http://www.)自由下載到它的二進制安裝文件及全部的源代碼。如果在Linux平臺上與MySQL搭配使用,PHP是最佳的選擇。 JSP是Sun公司推出的新一代站點開發(fā)語言,是Java語言除Java應用程序和Java Applet之外的第三個應用。Jsp可以在Serverlet和JavaBean的支持下,完成功能強大的站點程序。 作為采用Java技術(shù)家族的一部分,以及Java 2(企業(yè)版體系結(jié)構(gòu))的一個組成部分,JSP技術(shù)擁有Java技術(shù)帶來的所有優(yōu)點,包括優(yōu)秀的跨平臺性,高度可重用的組件設(shè)計,健壯性和安全性等,能夠支持高度復雜的基于Web的應用。 除了這三種常見的腳本之外,在Linux下我們其實還有很多其他的選擇:Python(Google使用),Perl等,如果作為CGI調(diào)用,那么可選擇范圍就更廣了。使用這些不太常見的腳本語言的好處是,它們對于某些特殊的應用有別的腳本所不具有的優(yōu)勢;不好的地方是,這些腳本語言在國內(nèi)使用的人比較少,當碰到技術(shù)上的問題的時候,能找到的資料也較少。 5.4 可配置性 首先,也是最重要的一點,功能和展示必須分開。PHP和JSP都支持模板技術(shù),如PHP的Smarty,Phplib,JSP的JSTL(JSP Standard Tag Library)等。核心功能使用腳本語言編寫,前臺展示使用帶特殊標簽的HTML,不僅加快了開發(fā)速度,而且方便以后的維護和升級[47]。 其次,對于前臺模板,一般還需要將頁面的頭,尾單獨提取出來,頁面的主體部分也按模塊或者功能拆分。對CSS,JS等輔助性的代碼,也建議以單獨的文件形式存放。這樣不僅方便管理,修改,而且還可以在用戶訪問的時候進行緩存,減少網(wǎng)絡(luò)流量,減輕服務器壓力。 再次,對于核心功能腳本,必須將與服務器相關(guān)的配置內(nèi)容,如數(shù)據(jù)庫連接配置,腳本頭文件路徑等,與代碼分離開。尤其當網(wǎng)站使用集群技術(shù),CDN加速等技術(shù)的時候,每一臺服務器上的配置可能都會不一樣。如果不使用配置文件,則需要同時維護幾份不同的代碼,很容易出錯。 最后,應該盡量做到修改配置文件后能實時生效,避免修改配置文件之后需要重啟服務程序的情況。 5.5 封裝和中間層思想 在更高的層次,可以將網(wǎng)站分為表示層,邏輯層,持久層,分別進行封裝,做到當某一層架構(gòu)發(fā)生變化時,不會影響到其他層。比如新浪播客在一次升級的時候,將持久層的數(shù)據(jù)庫由原來的集中式改為分布式架構(gòu),因為封裝了數(shù)據(jù)庫連接及所有操作[附錄2],做到了不修改任何上層代碼,平穩(wěn)的實現(xiàn)了過渡。近來流行的MVC架構(gòu),將整個網(wǎng)站拆分成Model(模型/邏輯)、View(視圖/界面)、Controller(控制/流程)三個部分,而且有很多優(yōu)秀的代碼框架可供選擇使用, 像JSP的Structs,Spring,PHP的php.MVC, Studs 等。使用現(xiàn)成的代碼框架,可以使網(wǎng)站開發(fā)事半功倍。 6 擴容、容錯處理 6.1 擴容 一個大型網(wǎng)站,在設(shè)計架構(gòu)的時候,必須考慮到以后可能的容量擴充。新浪播客在設(shè)計時充分地考慮了這一點。對于視頻分享類網(wǎng)站來說,視頻存儲空間消耗是巨大的。新浪播客在主存儲服務器上,采用配置文件形式指定每一個存儲盤柜上存儲的視頻文件的ID范圍。當前臺服務器需要讀取一個視頻的時候,首先通過詢問主存儲服務器上的接口獲得該視頻所在的盤柜及目錄地址,然后再去該盤柜讀取實際的視頻文件。這樣如果需要增加存儲用的盤柜,只需要修改配置文件即可,前臺程序絲毫不受影響。 新浪播客采用MySQL數(shù)據(jù)庫集群,在邏輯層封裝了所有的數(shù)據(jù)庫連接及操作。當數(shù)據(jù)庫存儲架構(gòu)發(fā)生改變的時候,如增加一臺主庫,將某些數(shù)據(jù)表獨立成庫,增加讀取數(shù)據(jù)用的從庫等,都只需要修改封裝了的數(shù)據(jù)庫操作類,上層代碼不用修改。 新浪播客的前臺頁面服務器使用F5公司的硬件第四層交換機,網(wǎng)通,電信分別導向不同的虛擬IP,每一個虛擬IP后面又有多個服務器提供服務。當訪問流量增大的時候,可以很方便往虛擬IP后面增加服務器,分擔壓力。 6.2 容錯 2006年12月27日臺灣東部外海發(fā)生里氏7.6級地震,造成途徑臺灣海峽的多條海底電纜中斷,導致許多國外網(wǎng)站,像MSN, NBA, Yahoo?。ㄓ⑽闹髡荆┑葒鴥?nèi)無法訪問,但也有例外,以Google為代表的在國內(nèi)建設(shè)有分布式數(shù)據(jù)節(jié)點的很多網(wǎng)站卻仍然可以訪問。雖然說地震造成斷網(wǎng)是不可抗原因,但如果在這種情況下網(wǎng)站仍然可以訪問,無疑能給網(wǎng)站用戶留下深刻的印象。這件事情給大型商業(yè)網(wǎng)站留下的教訓是:網(wǎng)站需要在用戶主要分布區(qū)域保持數(shù)據(jù)存在,以防止可能的網(wǎng)絡(luò)故障。 對于服務器錯誤,一般采取冗余設(shè)計的方法來避免。對于存儲服務器(主要是負責寫入的服務器),可以使用RAID(冗余磁盤陣列);對于數(shù)據(jù)庫(主要是負責寫入的主庫),可以采用雙主庫設(shè)計[30];對于提供服務的前臺,則可以使用第四層交換的集群,由多臺服務器同時提供服務,不僅分擔了流量壓力,同時還可以互相作為備份。 在應用層程序中,也要考慮“用戶友好”的出錯設(shè)計。典型例子如HTTP 404 出錯頁面,程序內(nèi)部錯誤處理,錯誤返回提示等,盡可能的做到人性化。 7 總結(jié)及展望 7.1 總結(jié) ![]() 對于一個高并發(fā)高流量的網(wǎng)站來說,任何一個環(huán)節(jié)的瓶頸都會造成網(wǎng)站性能的下降,影響用戶體驗,進而造成巨大的經(jīng)濟損失。在全互聯(lián)網(wǎng)層面,應該使用分布式設(shè)計,縮短網(wǎng)站與用戶的網(wǎng)絡(luò)距離,減少主干網(wǎng)上的流量,以及防止在網(wǎng)絡(luò)意外情況下網(wǎng)站無法訪問的問題。在局域網(wǎng)層面,應該使用服務器集群,一方面可以支撐更大的訪問量,另一方面也作為冗余備份,防止服務器故障導致的網(wǎng)站無法訪問。在單服務器層面,應該配置操作系統(tǒng),文件系統(tǒng)及應用層軟件,均衡各種資源的消耗,消除系統(tǒng)性能瓶頸,充分發(fā)揮服務器的潛能。在應用層,可以通過各種緩存來提升程序的效率,減少服務器資源消耗(圖6)。另外,還需要合理設(shè)計應用層程序,為以后的需求變更,擴容做好準備。 圖6 典型高并發(fā)高流量網(wǎng)站的架構(gòu) 在每一個層次,都需要考慮容錯的問題,嚴格消除單點故障,做到無論應用層程序錯誤,服務器軟件錯誤,服務器硬件錯誤,還是網(wǎng)絡(luò)錯誤,都不影響網(wǎng)站服務。 7.2展望 隨著互聯(lián)網(wǎng)的持續(xù)發(fā)展,Web2.0的興起,在可以預見的未來里,互聯(lián)網(wǎng)的用戶持續(xù)增多,提供用戶參與的網(wǎng)站不斷增加,用戶參與的內(nèi)容日益增長,越來越多的網(wǎng)站的并發(fā)量,訪問量會達到一個新的高度,這就會促使越來越多的個人,公司以及研究機構(gòu)來關(guān)注高并發(fā)高流量的網(wǎng)站架構(gòu)問題。就像Web1.0成就了無數(shù)中小網(wǎng)站,成就了LAMP一樣,Web2.0注定也會成就一個新的,高效的,成本較低的解決方案。這個方案應該包括透明的第三方CDN網(wǎng)絡(luò)加速服務,價格低廉的第四層甚至更高層網(wǎng)絡(luò)交換設(shè)備,優(yōu)化了網(wǎng)絡(luò)性能的操作系統(tǒng),優(yōu)化了讀寫性能,分布式,高可靠的文件系統(tǒng),揉合了內(nèi)存,硬盤等各個級別緩存的HTTP服務器,更為高效的服務器端腳本解析器,以及封裝了大部分細節(jié)的應用層設(shè)計框架。 技術(shù)的進步永無止境。我們期待互聯(lián)網(wǎng)更為美好的明天 |
|
|
來自: cppmonkey > 《ARCHITECT》