什么樣的硬件設(shè)備在支撐 Stack Overflow?
我更愿意把Stack Overflow看作是能夠運行于大規(guī)模數(shù)據(jù)下,但本身并不算大規(guī)模的(running with scale but not at scale)。意思是我們的網(wǎng)站非常有效率,但至少目前為止,我們的規(guī)模還不夠“大”。讓我們通過一些數(shù)字來介紹Stack Overflow當(dāng)前是一個怎樣的規(guī)模吧。以下是一些核心的數(shù)字,來自于不久前在一整天(24小時)內(nèi)的統(tǒng)計,準(zhǔn)確說是2013年11月12日。這是一個典型的工作日,并且只統(tǒng)計了我們活動的數(shù)據(jù)中心,也就是我們自己的服務(wù)器。那些對CDN節(jié)點的請求和流量被排除在外,因為它們并不直接訪問我們的網(wǎng)絡(luò)。
- 負(fù)載均衡器接受了148,084,833次HTTP請求
- 其中36,095,312次是加載頁面
- 833,992,982,627 bytes (776 GB) 的HTTP流量用于發(fā)送
- 總共接收了286,574,644,032 bytes (267 GB) 數(shù)據(jù)
- 總共發(fā)送了1,125,992,557,312 bytes (1,048 GB) 數(shù)據(jù)
- 334,572,103次SQL查詢(僅包含來自于HTTP請求的)
- 412,865,051次Redis請求
- 3,603,418次標(biāo)簽引擎請求
- 耗時558,224,585 ms (155 hours) 在SQL查詢上
- 耗時99,346,916 ms (27 hours) 在Redis請求上
- 耗時132,384,059 ms (36 hours) 在標(biāo)簽引擎請求上
- 耗時2,728,177,045 ms (757 hours) 在ASP.Net程序處理上
(我覺得應(yīng)該發(fā)表一篇文章介紹我們?nèi)绾慰焖俨杉@些數(shù)據(jù),以及為什么值得耗費精力去獲取它們)
注意以上數(shù)字包括了整個Stack Exchange網(wǎng)絡(luò),但那并不是我們?nèi)康?。除此之外,這些數(shù)字也僅僅來自于我們?yōu)榱藱z測性能而記錄的HTTP請求。“哇,一天有這么多個小時,你們怎么做到的?”我們把這叫做魔法,當(dāng)然有些人喜歡說成“許多個有多核處理器的服務(wù)器”,但我們依然堅持這是魔法。以下是那個數(shù)據(jù)中心里運行Stack Exchange網(wǎng)絡(luò)的設(shè)備:
- 4個MS SQL 服務(wù)器
- 11個IIS服務(wù)器
- 2個Redis服務(wù)器
- 3個標(biāo)簽引擎服務(wù)(任何針對標(biāo)簽的請求都會訪問它們,比如/questions/tagged/c++)
- 3個ElasticSearch服務(wù)器
- 2個負(fù)載均衡器(HAProxy)
- 2個交換機(Nexus 5596和Fabric Extenders)
- 2個Cisco 5525-X ASA (可看作是防火墻)
- 2個Cisco 3945 Router
我們不僅僅運行網(wǎng)站,旁邊架子上還有一些運行著虛擬機的服務(wù)器和其他設(shè)備,它們并不直接服務(wù)于網(wǎng)站,而是進(jìn)行部署、域名控制、監(jiān)控、操作數(shù)據(jù)庫等其他工作。上面列表中的兩個數(shù)據(jù)庫服務(wù)器之前一直都是用作備份,直到最近才作為只讀的負(fù)載(主要用于Stack Exchange API),于是我們可以不需要太多考慮便繼續(xù)擴大規(guī)模了。Web服務(wù)器有兩個分別用于開發(fā)和存儲元數(shù)據(jù),運行負(fù)載非常低。
核心設(shè)備
如果除去那些多余的設(shè)備,以下是Stack Exchange運行需要的(保持目前的性能水平):
- 2個MS SQL服務(wù)器(Stack Overflow在一臺,其他的在另一臺,實際上只需一臺機器運行還能有富余)
- 2個Web服務(wù)器(或許3個吧,不過我有信心2個足矣)
- 1個Redis服務(wù)器
- 1個標(biāo)簽引擎服務(wù)器
- 1個ElasticSearch服務(wù)器
- 1個負(fù)載均衡器
- 1個交換機
- 1個ASA
- 1個路由器
(我們真該找個機會嘗試這個配置,關(guān)閉部分設(shè)備,看看極限在哪)
現(xiàn)在還有一些虛擬機運行在后臺,執(zhí)行一些輔助功能,比如域名控制等等。但那都是些相當(dāng)?shù)拓?fù)載的任務(wù),我們就不做討論了,這里把重心放在Stack Overflow本身,看看它是怎樣全速加載出頁面的。如果你希望更精確全面,可以增加一個VMware虛擬機進(jìn)來,用于執(zhí)行所有的輔助工作。這樣看來并不需要很多機器,但是這些機器的規(guī)格通常在云上難以實現(xiàn),除非你有足夠多的錢。以下是這些“增強型”服務(wù)器簡要的配置介紹:
- 數(shù)據(jù)庫服務(wù)器有384GB內(nèi)存和1.8TB的SSD硬盤
- Redis服務(wù)器有96GB內(nèi)存
- ElasticSearch服務(wù)器有196GB內(nèi)存
- 標(biāo)簽引擎服務(wù)器有著我們能買得起的最快的處理器
- 交換機每個端口有10Gb的帶寬
- Web服務(wù)器不是很特別,有32GB內(nèi)存、2個4核處理器和300GB的SSD硬盤
- 有些服務(wù)器有2個10Gb帶寬的接口(比如數(shù)據(jù)庫),其他有4個1Gb帶寬的
20Gb的帶寬太多余了?你還真特么說對了,活動的數(shù)據(jù)庫服務(wù)器平均只利用了20Gb通道中的100-200Mb。然而,像備份、重建等等操作,根據(jù)當(dāng)前內(nèi)存和SSD硬盤的情況,可以使帶寬完全飽和,所以說這樣設(shè)計還是有意義的。
#p#
存儲設(shè)備
我們目前有大約2TB的數(shù)據(jù)庫存儲(第一個集群有18塊SSD硬盤—— 總共1.63TB,使用1.06TB;第二個集群由4塊SSD硬盤組成—— 總共1.45TB,使用889GB),這是我們在云服務(wù)器上需要的(嗯哼,又要吐槽價格了吧),請記住這全部都是SSD硬盤。歸功于存儲器良好的表現(xiàn),我們數(shù)據(jù)庫的平均寫入時間是0毫秒,甚至超出我們能度量的精度了。算上內(nèi)存中的數(shù)據(jù)以及兩級緩存,Stack Overflow中實際的數(shù)據(jù)庫讀寫比例是40:60。你沒看錯,60%是寫操作(點此了解讀寫比)。此外,每個Web服務(wù)器都有兩塊320GB SSD硬盤組成的RAID1。ElasticSearch在每個區(qū)塊大約需要300GB的容量,由于我們會非常頻繁的寫入或重建索引,SSD硬盤在這里是更好的選擇。
值得注意的是我們擁有一個SAN(存儲區(qū)域網(wǎng)絡(luò))連接到核心網(wǎng)絡(luò),那就是 Equal Logic PS6110X,它有24個可熱交換的10K SAS磁盤和2個10Gb的控制器。這個設(shè)備僅僅被VM服務(wù)器用作共享儲存空間以保證虛擬機高度的可用性,但并不實際支撐網(wǎng)站的運行。換句話說,如果SAN掛掉了,在一段時間內(nèi)網(wǎng)站甚至無法察覺(只有虛擬機中的域名控制器能感知到)。
整合到一起
這所有的設(shè)備在一起是為了什么?性能。我們需要很高的性能,這是一個對我們來說很重要的特性。所有站點的首頁都是問題頁面,我們內(nèi)部把它親切地稱作Question/Show(路由的名字)。在11月12日,這個頁面平均渲染時間是28毫秒,而我們的要求是至多50ms。為了使用戶獲得更好的體驗,我們盡一切可能縮短頁面加載的時間,哪怕只有一毫秒。在和性能有關(guān)的問題上,我們所有的開發(fā)人員都是“錙銖必較”的,這也有助于我們的網(wǎng)站保持快速響應(yīng)。以下是一些Stack Overflow上熱門頁面的平均渲染時間,數(shù)據(jù)還是來自于前面統(tǒng)計的那24小時:
- Question/Show: 28 ms (2970萬次點擊)
- User Profiles: 39 ms (170萬次點擊)
- Question List: 78 ms (110萬次點擊)
- Home page: 65 ms (100萬次點擊) (這對我們來說已經(jīng)很慢了,Kevin Montrose正在著手修復(fù)這個問題)
憑借對每一次請求的時間線的記錄,我們能夠準(zhǔn)確觀察到頁面加載的過程。我們需要這樣的數(shù)據(jù),否則難道靠腦補來做決定嗎?有數(shù)據(jù)在手,我們就可以這樣監(jiān)控性能:
如果你對某個特定頁面的數(shù)據(jù)感興趣,我也很樂意發(fā)布出來。但這里我重點關(guān)注渲染時間,因為它表示我們的服務(wù)器需要多久來生成一個網(wǎng)頁。網(wǎng)絡(luò)傳輸速度是一個完全不同的話題了(盡管不得不承認(rèn)它也有很大的關(guān)系),不過將來我會講到的。
增長空間
非常值得一提的是我們這些服務(wù)器運行時的使用率都非常低。比如Web服務(wù)器的CPU平均使用率為5-15%,內(nèi)存只使用了15.5GB,網(wǎng)絡(luò)流量只有20-40Mb/s;而數(shù)據(jù)庫服務(wù)器CPU平均使用率為5-10%,使用了365GB內(nèi)存,以及100-200Mb/s的網(wǎng)絡(luò)。這使我們能做到幾件重要的事情:在網(wǎng)站規(guī)模增大時不至于需要馬上升級設(shè)備;當(dāng)出現(xiàn)問題時(錯誤的查詢、代碼以及攻擊等等,無論是什么樣的問題),我們能保持網(wǎng)站始終不掛;在必要的時候降低功耗。這里有個我們Web層的監(jiān)控項目:
利用率如此之低的主要原因是高效的代碼。盡管本文的主題并不是這個,但是高效的代碼對挖掘服務(wù)器的性能也有著決定性的作用。做一件非必要的事情所損失的,居然比無所作為還要多——把這引申到代碼中就是說,你需要把它們改進(jìn)得更高效了。這些損失或者消耗可以是能源、硬件(你需要更多更快的服務(wù)器)、開發(fā)人員理解代碼更困難(平心而論,這個有兩面性,高效的代碼并不一定那么簡單),以及緩慢的頁面渲染——可能導(dǎo)致用戶更少地瀏覽網(wǎng)站其他頁面甚至再也不訪問你的網(wǎng)站了。低效率代碼帶來的損失可能比你想象的大很多。
現(xiàn)在我們了解了Stack Overflow運行在怎樣的硬件上,下次可以討論一下為何我們不使用云。
原文鏈接: SO 團隊成員 Nick Craver 翻譯: 伯樂在線 - 蔣生武