<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Java-Android-jwebee
    Java-Android-jwebee
    對IT人來說,要成為一個優秀的技術型管理者,除了需要具備扎實的技術基礎之外,還應該培養良好的人際關系能力、談判與溝通技能、客戶關系與咨詢技能、商業頭腦和財務技能以及創新意識,此外還要有巧妙的激勵技巧和化解沖突與解決突發問題的能力.

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

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

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

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

    關鍵詞:高并發 高流量 網站架構 網站擴容 容錯

    高并發高流量網站架構


    1 引言

    1.1 互聯網的發展

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

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

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

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

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

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

    1.3 新浪播客的簡介

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

    本文是作者在新浪愛問搜索部門實習及參與新浪播客開發的經驗和教訓的回顧,是作者對一般高并發高流量網站架構的總結和抽象。

    2 網絡層架構

    2.1 鏡像網站技術

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

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




    1 上圖:天空軟件站首頁的鏡像選擇頁面

    下圖:SourceForge下載時的鏡像選擇頁面

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

    2.2 CDN內容分發網絡

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

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



    2 CDN原理示意圖

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

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


    3 新浪網使用ChinaCache CDN服務。

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

    其中中國節點超過80個,

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

    2.3 應用層分布式設計

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

    2.4 網絡層架構小結

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

    3 交換層架構

    3.1 第四層交換簡介

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

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

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

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

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

    3.2 硬件實現

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

    3.3 軟件實現

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

    4 服務器優化

    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表示關閉,下同) 啟用 RFC25132326] 定義的 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環境下硬盤級緩存一般使用Squid27]。

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

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

    Squid 運行的時候,默認會在硬盤上建兩層hash目錄,用來存儲緩存的Object。它還會在內存中建立一個Hash Table,用來記錄硬盤中Object分布的情況。如果Squid配置成為一個Squid集群中的一個的話,它還會建立一個 Digest Table(摘要表),用來存儲其它 Squid 上的Object摘要。當用戶端想要的資料本地硬盤上沒有時,可以很快的知道應該去集群中的哪一臺機器獲得。在硬盤空間快要達到配置限額的時候,可以配置使用某種策略(默認使用LRULeast 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分擔了大部分連接,網站的承壓能力就大大增強了。


    4 某網站使用MRTG工具檢測到的Squid命中率

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

    4.4 內存級緩存

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

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

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

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

    4.5 CPUIO均衡

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

    4.6 讀寫分離

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

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

    5 應用程序層優化

    5.1 網站服務器程序的選擇

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

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

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

    5.2 數據庫選擇

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

    MySQL數據庫能為網站提供:

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

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

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

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


    5 MySQL主輔庫模式集群示意


    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采用腳本語言VBScriptC#)作為自己的開發語言。 但因為只能運行在Windows環境下,這里我們不討論它。

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

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

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

    5.4 可配置性

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

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

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

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

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

    5.5 封裝和中間層思想

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

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

    6 擴容、容錯處理

    6.1 擴容

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

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

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

    6.2 容錯

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

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

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

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

    7 總結及展望

    7.1 總結


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


    6 典型高并發高流量網站的架構


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

    7.2展望

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

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

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


    參考文獻

    1Robert Hobbes' Zakon, Hobbes' Internet Timeline v8.2 , available at http://www.zakon.org/robert/internet/timeline/

    2GlobalReach Inc.Global Internet Statistics (by language), available at

    http://www.glreach.com/globstats/index.php3

    3]中國互聯網絡信息中心,第十九次中國互聯網絡發展狀況統計報告,available at: http://www.cnnic.net.cn/index/0E/index.htm

    4Web2.0Definition available at http://www.wikilib.com/wiki/Web2.0

    5Alexa Internet, Inc. http://www.alexa.com/

    6Yahoo! Inc. http://www.yahoo.com/

    7eBay Inc. 著名的網上拍賣網站,http://www.ebay.com/

    8Chet Dembeck, Yahoo! Cashes In On eBay's Outage, available at:

    http://www.ecommercetimes.com/perl/story/545.html

    9YouTube, Inc. http://www.youtube.com/

    10]數據來源:互聯網周刊,2007年第3

    11]新浪網技術(中國)有限公司,http://www.sina.com.cn/

    12]數據來源:新浪播客改版公告,available at:

    http://games.sina.com.cn/x/n/2007-04-16/1427194553.shtml

    13]鄧宏炎, 葉娟麗,網絡參考文獻初探,武漢大學學報: 人文社會科學版, 2000

    14]彭湘凱,CDN網絡及其應用,微計算機信息,200502

    15]數據來源:ChinaCache, http://www.chinacache.com/

    16Open System Interconnect,開放式系統互聯模型,1984年由國際標準化組織(ISO)提出的一個開放式網絡互聯參考模型,參考 http://www.iso.org/

    17]凌仲權,丁振國,基于第四層交換技術的負載均衡,中國數據通信,2003

    18]陳明銳,邱釗,黃曦,黃俊,智能負載均衡技術在高負荷網站上的應用,廣西師范大學學報(自然科學版),200604

    19Alteon Inc. http://www.alteon.com/

    20F5 Networks, Inc. http://www.f5.com.cn/

    21]數據來源:http://www.toplee.com/blog/archives/71.html

    22] 傅明,程曉恒,王瑋,基于Linux的服務器負載均衡性訪問的解決方案,計算機系統應用,200109

    23Ming-Wei Wu, Ying-Dar Lin, Open source software development: an overview, Computer, 2001 - ieeexplore.ieee.org

    24]王?;?, 楊斌,Linux TCP/IP協議棧的設計及實現特點,云南民族大學學報(自然科學版),200701

    25Requests for CommentsRFC),the publication vehicle for technical specifications and policy documents produced by the (IETF (Internet Engineering Task Force) , the IAB (Internet Architecture Board), or the IRTF (Internet Research Task Force)http://www.ietf.org/rfc.html

    26RFC 1323,http://www.ietf.org/rfc/rfc1323.txt?number=1323

    27Squid web proxy cache team, http://www.squid-cache.org/

    28]馬俊昌 , 古志民,網絡代理緩存Squid存儲系統分析,計算機應用,200310

    29]韓向春,郭婷婷,林星宇,豐保杰,集群緩存系統中代理緩存技術的研究,計算機工程與設計,200620

    30Brad Fitzpatrick, LiveJournal's BackendA history of scaling, oscon 2005 ,http://www.danga.com/words/

    31Danga Interactive, http://www.danga.com/memcached/

    32LiveJournal,著名的博客托管商(BSP), http://www.livejournal.com/

    33Brad FitzpatrickDistributed caching with memcached,Linux Journal ,Volume 2004,Issue 124Page 5August 2004

    34]周楓,面向 Internet 服務的可擴展集群對象 存儲及磁盤日志緩存技術研究,清華大學碩士畢業論文,2002

    35]陳赟,楊根科,吳智銘,RAID系統中RAID級別的具體實現算法,微型電腦應用,200306

    36]陳平仲,硬件實現RAID與軟件實現RAID的比較,現代計算機(專業版),200501

    37NAMESYS,http://www.namesys.com/

    38D Bobbins,Advanced file system implementor s guide: Journalling and ReiserFSIBM's Developer Works Journal,June,2001

    39]劉章儀,Linux文件系統分析,貴州工業大學學報(自然科學版),200204

    40]數據來源:http://news.netcraft.com/archives/2007/04/02/april_2007_web_server_survey.html

    41The Apache Software Foundation ,http://httpd.apache.org/

    42Lighttpdhttp://www.lighttpd.net/

    43MySQL AB,http://www.mysql.com/

    44]顧治華,忽朝儉,MySQL存儲引擎與數據庫性能,計算機時代,200610

    45The PHP Group,http://www.php.net/

    46]范云芝,動態網頁制作技術ASPPHPJSP比較分析,電腦知識與技術(學術交流),200510

    47]王耀希,王麗清,徐永躍,利用模板技術實現B/S 研發過程的分離與并行,計算機應用研究,2004

    附 錄

    [附錄1]

    1. Memcache的客戶端PHP 封裝

    class memcache_class

    {

    function memcache_class()

    {

    }

    /**

    * post方法,執行memcache的寫入操作

    * $data參數,允許是php的數組。

    * exp參數是設定的超時時間,單位是秒。

    */

    function p_memcache_write($key, $data, $exp=3600)

    {

    $mmPageStartTime = microtime();

    $ip = MEMCACHE_SERVER_IP;

    $port = MEMCACHE_SERVER_PORT;

    $type = MEMCACHE_SERVER_TYPE;

    //$data進行序列化,允許$data是數組

    $data = serialize($data);

    //$data進行壓縮

    //$data = gzcompress ($data);

    $submit=array( type => $type,

    cmd => "set",

    key => $key,

    data => $data,

    exp => $exp

    );

    $ret = memcache_class::posttohost($query, $submit);

    return $ret;

    }

    /**

    * post方法,執行memcache的讀出操作

    */

    function p_memcache_read($key)

    {

    $mmPageStartTime = microtime();

    $ip = MEMCACHE_SERVER_IP;

    $port = MEMCACHE_SERVER_PORT;

    $type = MEMCACHE_SERVER_TYPE;

    $submit=array( type => $type,

    cmd => "get",

    key => $key

    );

    $res = memcache_class::posttohost($query, $submit);

    //$res進行解壓縮

    //$res = gzuncompress($res);

    //$res進行反序列化,允許$res是數組

    $res = unserialize($res);

    return $res;

    }

    /**

    * 執行post的函數

    */

    function posttohost($url, $data)

    {

    $mmPageStartTime = microtime();

    $url = parse_url($url);

    $encoded = "";

    while (list($k,$v) = each($data))

    {

    $encoded .= ($encoded ? "&" : "");

    $encoded .= rawurlencode($k)."=".rawurlencode($v);

    }

    for ($i = 0; $i < 3; $i ++)

    {

    $fp = @fsockopen($url['host'], $url['port'],$errno, $errstr, 1);

    if ($fp)

    break;

    }

    if (!$fp)

    {

    return "";

    }

    @stream_set_timeout($fp, 2);

    @fputs($fp, sprintf("POST %s%s%s HTTP/1.0\n", $url['path'], $url['query'] ? "?" : "", $url['query']));

    @fputs($fp, "Host: $url[host]\n");

    @fputs($fp, "Content-type: application/x-www-form-urlencoded\n");

    @fputs($fp, "Content-length: " . strlen($encoded) . "\n");

    @fputs($fp, "Connection: close\n\n");

    @fputs($fp, "$encoded\n");

    $line = @fgets($fp,1024);

    if (!eregi("^HTTP/1\.. 200", $line)) return;

    $results = "";

    $inheader = 1;

    while(!feof($fp))

    {

    $line = @fgets($fp,1024);

    if ($inheader && ($line == "\n" || $line == "\r\n"))

    {

    $inheader = 0;

    }

    elseif (!$inheader)

    {

    $results .= $line;

    }

    }

    @fclose($fp);

    return $results;

    }

    }


    2.使用示例

    $out="";

    if (MEMCACHE_FLAG === true)

    {

    $memcache_key = md5(trim($key));

    $time_before = getmicrotime();

    $mdata = memcache_class::p_memcache_read($memcache_key);

    $time_after = getmicrotime();

    $memcache_read_time = $time_after - $time_before;

    if (strlen($mdata) >= MIN_RESULT) {

    $out = $mdata;

    $memhit = 1;

    memcached_log("CACHE_HIT");

    }

    else {

    $memhit = 0;

    memcached_log("CACHE_NOT_HIT");

    }

    }

    if (!(strlen($out) >= MIN_RESULT))

    {

    $query = get_query();

    $time_before=getmicrotime();

    $out = http_read($MySQLHost,$MySQLPort,$query,&$errstr,10);

    $time_after=getmicrotime();

    }


    $len = strlen($out);

    if(MEMCACHE === true && $memhit <= 0)

    {

    $memcache_key = md5(trim($key));

    $time_before = getmicrotime();

    memcache_class::p_memcache_write($memcache_key, $out, MEMCACHE_TIME);

    $time_after = getmicrotime();

    $memcache_write_time = $time_after - $time_before;

    memcached_log("CACHE_WRITE");

    }


    [附錄2]

    MySQL wrap class

    <?php

    class mysqlRpc

    {

    var $_hostWrite = '';

    var $_userWrite = '';

    var $_passWrite = '';

    var $_hostRead = '';

    var $_userRead = '';

    var $_passRead = '';

    var $_dataBase = '';

    var $db_write_handle = null;

    var $db_read_handle = null;

    var $db_last_handle = null;

    var $_cacheData = array();

    var $mmtime = 60;

    function mysqlRpc($database, $w_servername, $w_username, $w_password, $r_servername='', $r_username='', $r_password='') {}


    function connect_write_db() {}

    function connect_read_db() {}

    function query_write($sql, $return = false) {}

    function query_read($sql, $return = false) {}


    function query_first($sql, $return = false) {}

    function insert_id(){}

    function affected_rows(){}


    function escape_string($string){}

    function fetch_array($queryresult, $type = MYSQL_ASSOC){}


    }



    jwebee

    我的個人網站
    posted on 2007-12-12 17:27 周行 閱讀(5968) 評論(3)  編輯  收藏 所屬分類: IT技術

    FeedBack:
    # re: 高并發高流量網站架構
    2012-07-31 16:42 | 何楊
    原創還是轉載?  回復  更多評論
      
    # re: 高并發高流量網站架構
    2013-01-23 16:30 | 阿斯頓發
    阿薩法  回復  更多評論
      
    # re: 高并發高流量網站架構
    2013-01-23 16:30 | 阿斯頓發
    阿斯頓發  回復  更多評論
      
    Java-Android-jwebee
    主站蜘蛛池模板: 亚洲熟妇无码久久精品| 亚洲精品制服丝袜四区| 亚洲国产91精品无码专区| 中文字幕日韩亚洲| 亚洲国产美国国产综合一区二区| 亚洲高清资源在线观看| 亚洲偷自拍另类图片二区| 亚洲成人免费电影| 91在线品视觉盛宴免费| 四虎永久精品免费观看| 久久亚洲高清观看| 亚洲最大在线视频| 精品国产_亚洲人成在线| 成人A毛片免费观看网站| 午夜成人无码福利免费视频| 国产成人亚洲精品电影| 在线观看免费视频一区| 国产国产人免费视频成69堂| 国产大片线上免费看| 亚洲精品乱码久久久久66| 亚洲人成激情在线播放| 四虎国产精品永免费| 99re免费在线视频| 国产一区二区三区免费看| 亚洲国产成人片在线观看无码 | 国产亚洲AV夜间福利香蕉149| 久久亚洲精品国产精品| 亚洲成a人无码亚洲成av无码| a级毛片无码免费真人久久| 成人免费毛片观看| 久久久亚洲欧洲日产国码农村| 亚洲熟妇自偷自拍另欧美| 国产一区二区三区免费观在线| 久久久久久久91精品免费观看| 4338×亚洲全国最大色成网站| 亚洲国产精品网站久久| 一个人免费观看www视频| 国产日本一线在线观看免费| 亚洲小说区图片区另类春色| 夜夜春亚洲嫩草影院| 国产亚洲精aa在线看|