某大型社區網站系統

流量集中

大部分bbs的流量都是冷熱不均,相差很大,熱帖一天可達數百萬訪問,冷貼就是一個訪問量也沒有。熱帖主要是在列表第一版的帖子,和精華貼,這些帖子的流量加起來至少佔到整個bbs流量的50%以上。雖然熱帖佔了很大流量,但這些熱帖的數量不會太多,所以用緩存架構的話對這些熱帖優化程度就很大,對熱帖優化程度大相當於對整個系統優化程度大。

實時性

每發或回覆一張貼,就必須讓這張貼立刻發佈出去,用戶能馬上看到。所以用到緩存架構的話,這個緩存要能實時更新。

回帖少,看帖多

因爲bbs也是由人來組成,所以這個現象是不可改變的,1/10是比較保守,估計大部分都在1/100以下吧。雖然有實時性,但是因爲回帖少看帖多,意味着觸發更新緩存的頻率少,比率越小,優化效果越大。


系統主要解決問題

bbs因爲是實時系統,所以常規上都是設計爲純動態+直讀數據庫架構,純動態架構的性能問題是一個突出問題,在達到一定訪問量或受到一些攻擊時,系統就容易掛掉,嚴重的時候數據庫還會損壞,數據庫壞掉的話服務恢復時間就很長。更困惑人的是,以往即使知道性能是個問題,但是去解決這個問題的風險很大,需要對系統進行很大的變動。做很大的變動就難免會引發很多新的bug,這樣很容易導致大量的網友流失。

今天講的這個架構基本可以解決性能問題,而且對程序部分的修改不算很多,而且有一個成形的實施步驟,按步驟就能做完。

架構圖

前面是lvs負載均衡,lvs下面掛幾臺squid,squid的配置統一指向到中層代理nginx,由nginx負載均衡到幾臺應用服務器,後面就是數據庫。其中lvs安裝調試起來可能麻煩一些,可以用haproxy替換,haproxy是目前7層純代理中性能最好的,安裝配置和出問題時處理也相對簡單。squid的配置比較特別的是緩存時間可以儘可能長,對單貼的緩存時間可以配到一天以上,目的是讓帖子儘量不要過期,只有後端發來更新的請求才會更新。

高性能

因爲有了緩存,很多帖子都被緩存住了,請求的時候當然直接從緩存出去,不會觸及到應用服務器,所以效率很高。

gzip壓縮可以減少頁面流量80%左右,100k的頁面可以壓到20k這樣,一方面減少了帶寬,另一方面用戶訪問起來感覺也會快很多。這個是在中層代理的nginx上完成的,用nginx做這個事情在效率方面沒有任何感覺。

應用服務器可以看作一個很慢的,很容易掛掉的系統,中層代理的負載均衡可以將它們保護起來,在這裏用nginx作負載均衡有幾個優點:
1,可以用多端口,這樣在一臺服務器上可以多開幾個應用服務器。
2、nginx可以在訪問一個後端出錯之後,將這個請求再發到另一個後端,這樣基本可以保證每個請求都能返回正確的數據。

實時性靜態化

因爲用到了緩存,所以頁面中有不少要修改的地方:
1、用rewrite把帖子變成一個.html結尾的文件,雖然squid也可以緩存帶?的鏈接,但是rewrite技術可以使鏈接固定並且簡潔,比如帖子有兩個參數帖子id和分頁的頁數,用?有兩個參數,如果把這兩個參數的順序調過來,那麼squid就認爲是兩個鏈接,有兩份緩存,更新緩存時就會漏掉一個。
2、squidclient是squid自帶的一個程序,可以用它來觀察squid的運行狀態,和更新緩存,更新緩存的機制就是向squid發送一個特殊的請求讓squid去刪掉對應的緩存鏈接,然後下一次訪問到這個鏈接的時候,squid就會重新去後端取這個鏈接的內容。
3、因爲用到了緩存,頁面上是不能直接放一些信息,比如用戶登錄狀態,在動態程序中可以直接用程序語言讀取顯示,但在這個架構中只能把它從頁面中除去,然後用javascript讀取cookie來顯示。有其它需求的話,還要用到ajax或json技術。
4、同樣是因爲有緩存,每次更新緩存都要花去一些時間,爲了加快速度,所以會用到異步更新緩存的機制。用到異步更新會出一個問題,當用戶得到發帖成功的響應的時候,事實上這張貼還沒有更新,如果讓用戶直接訪問這張帖子,那他往往看不到自己剛發表的回帖,這會讓用戶聯想到“審覈”這個動作,感覺非常不好。所以這個發帖成功這個動作應該讓用戶看到“5秒後跳到某某頁面”這樣的提示,讓他緩衝一下,這樣程序就有足夠的時間來執行更新緩存的動作了。另外一個是更新緩存時遇到分頁帖子就不好處理,所以應讓頁面儘可能長,像貓撲天涯的帖子都很長,就是這個原因。
5、因爲脫離了動態程序,所以之前如果是用動態程序直接統計點擊量的話,點擊量就會有問題,這時可以通過統計squid的log來統計帖子的點擊量,然後再更新到後臺的一個接口裏。


二級緩存的優點是可以進一步減少請求量,這裏配置了4臺緩存,意味着一個熱門帖子每次更新都會更新這4臺機器,這4臺機器就會發出4個請求,用一臺二級緩存就可以化爲1個請求,理論上可以將請求優化掉3/4。另外是squid這個服務器在一些情況下會出現某臺機請求全部穿透的現象,這時二級緩存就可以攔截住這些量很大的請求。一般來說,一個系統用到二級緩存就基本足夠了,沒有必要用到三級。

緩存過期時間在nginx或squid做,比較方便,比如有個沒有被緩存的頁面,訪問量突然很大,這時可以立刻調整它讓它暫時被緩存住。

在nginx可以通過log觀察,屏蔽掉一些ip和訪問,比如一些設計不良的爬蟲來爬頁面,造成系統負載突增,可以直接將它的ip或user-agent屏蔽掉。

權重和分流調節是lvs和nginx都有的功能,如果機器性能不均造成負載不均,或者有機器處於調試狀態,可以調整他們的訪問權重。lvs因爲工作在http的第4層,所以分流功能不算太強,除了可以調權重,另外就是可以根據客戶端ip分,還有根據後端負載動態分。nginx是7層代理,分配方式就更多,可以實現基於ip/url/header/後端響應速度等等來分。

高可用性就是說系統的穩固狀態,最好的就是這個系統永遠都能正常訪問,無論什麼時候訪問都絕對能打得開,當然這世界上根本沒有永遠都能打開的系統了,所以我們也只能讓它儘可能訪問正常。在計算機系統中某一臺單機的可用性都是不可靠的,單機即使軟件性能做到很強,但是硬件也會有問題,所以要用到集羣架構。

lvs通過雙機熱備,實時切換,可保證有故障時會自動換到備機。
squid直接利用lvs的故障屏蔽
nginx可利用自己寫的程序來實現熱備,也可以用lvs分到兩臺nginx上
應用服務器就是nginx集羣
數據庫就麻煩一些,現用的方案是通過程序判斷來做雙機熱備

因爲用到緩存架構,大量的流量都是通過緩存直接輸出的,這樣就可以輕鬆實現流量分配,一般的分流問題有兩種,電信網通的分流和雙線路分流,都可以做。

電信網通,在電信機房和網通機房各架一組緩存,中層代理和應用服務器都用一套。
多線路分流和電信網通分流差不多,就是比如兩條100M的帶寬,怎麼一起服務。

權限劃分,這個是大公司纔會有的問題了,大公司分工比較細,比如我就是做運維的,所以我就主要管理前面的squid和nginx這個部分,應用服務器和數據庫就讓產品維護的兄弟去做,在性能優化有什麼問題需要他們幫忙的,我只提供方案,讓他們去實施。有部分要合作的,要想辦法減少耦合度,像點擊量統計這部分,他們設計一個接口,然後我去寫統計log的腳本,然後往接口發。反過來也一樣,我設計接口,然後他們發來。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章