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