開(kāi)始時(shí),Picnik使用了一個(gè)開(kāi)源項目,Mogilefs,用于文件存儲。我們的大部分服務(wù)器都有幾個(gè)空閑的驅動(dòng)器插槽,我們在這些插槽上接入大容量的SATA驅動(dòng)器,用于 Mogilefs文件存儲。大部分后臺服務(wù)都是CPU密集型的,所以與這些I/O密集型的存儲配合得相當好。這個(gè)策略工作得很好,但存儲需求超過(guò)CPU需求之后,就不行了,這時(shí)候,Amazon的S3服務(wù)看起來(lái)好像是我們擴展存儲的最容易也最便宜的方法。
在測試S3之前,我們實(shí)際上并沒(méi)有對費用用做多少評估,一方面是當時(shí)并沒(méi)有太多的云計算可供選擇,另外就是一些令人尊敬的工程師也極力推薦S3,最后,我們從來(lái)就沒(méi)指望會(huì )大量使用。
因為開(kāi)發(fā)者的機器沒(méi)有使用Mogile,所以已經(jīng)有一個(gè)框架用于接口不同的文件存儲系統,這樣一來(lái),增加S3的支持就相對容易些。事實(shí)上,僅用了大約一天就實(shí)現了S3支持,又測試了一兩天,然后就將其打包到我們的每周例行發(fā)布中了。這種實(shí)現的簡(jiǎn)易性也是我們選擇S3的另一個(gè)關(guān)鍵因素。

最初,我們計劃只將最早的文件遷移到S3,這些文件是從2007年12月份開(kāi)始的,因為這些文件訪(fǎng)問(wèn)頻率比較低,不用怎么擔心性能和可用性方面的問(wèn)題。這個(gè)模式非常棒,S3看起來(lái)性能也很好。
唯一的不足,我們從Mogilefs中遷移文件的速度不夠快,沒(méi)有跟上文件增長(cháng)的速度。而且 Mogilefs也開(kāi)始出現一些性能問(wèn)題了。我們的解決方案跟其他幾家大型網(wǎng)站一樣:將文件直接存儲到S3。開(kāi)始時(shí),只將一小部分新文件直接存儲到S3,然后逐漸增加,一直到絕大部分新文件都流向Amazon。這樣,事情又搞定了,我們就轉去解決其他問(wèn)題了。
雖然S3已經(jīng)相當可靠了,仍然出現了一些值得注意的問(wèn)題。我們遇到的第一個(gè)問(wèn)題是最終一致性(eventual consistency)問(wèn)題,基本上,這意味著(zhù)不能保證立即讀取剛寫(xiě)入的文件,在寫(xiě)入到西雅圖的S3集群后,再試圖從EC2中讀,這個(gè)問(wèn)問(wèn)題會(huì )更嚴重。通過(guò)將所有的文件訪(fǎng)問(wèn)都從我們在西雅圖的數據中心代理而使這個(gè)問(wèn)題有所緩和,但這樣一來(lái),我們的帶寬就增加了。
我們遇到的第二個(gè)問(wèn)題是Amazon?返回HTTP500錯誤,我們的代碼能夠對不成功的請求進(jìn)行重試,這在大多數情況下工作良好。每一兩周,我們都會(huì )遇到錯誤突然爆發(fā),以至于重試邏輯都不起作用了。這種爆發(fā)會(huì )持續一小時(shí)左右。一天,我正在查看發(fā)生錯誤的關(guān)鍵字(keys),注意到這些關(guān)鍵字都有相同的前綴!結果證明,S3是基于關(guān)鍵字的范圍對數據進(jìn)行分區的,這意味著(zhù)維護(如增減某個(gè)分區容量)會(huì )導致某個(gè)范圍內的關(guān)鍵字大量出錯。Amazon這樣做是為了保持S3的高性能。對我們而言,這種突發(fā)性錯誤更大程度上是種煩惱,因為我們還有Mogilefs在起作用,如果寫(xiě)到S3失敗,將其寫(xiě)到Mogile:就是了。隨著(zhù)增長(cháng)率趨于穩定,這個(gè)問(wèn)題現在已經(jīng)很少出現了,但Mogile仍然在發(fā)揮作用。
其實(shí)我們遇到的這些問(wèn)題是構建大規模系統必然會(huì )發(fā)生的,所以 Amazon也用不著(zhù)掩飾什么。人們很容易忘記,這其實(shí)是一個(gè)有著(zhù)很多用戶(hù)的規模巨大的分布式系統。
隨著(zhù)流量的增長(cháng),我們越來(lái)越依賴(lài)于S3。要是S3宕掉了,一天的大部分時(shí)間里,我們的Mogl都無(wú)法處理龐大的請求。幸運的是,S3大部分問(wèn)題都不是發(fā)生在我我們網(wǎng)站的高峰時(shí)間,所以 Mogilev還能夠應付。我也應該提到的是,Mogile在兩種情況下會(huì )宕機幾個(gè)小時(shí),種情況是修改 MYSQL的表結構,還有就是調試Mogilev的Perl代碼。這種時(shí)候,1009%的流量都會(huì )壓到S3上,而我們的用戶(hù)則從來(lái)不知道發(fā)生了什么。
“無(wú)限”存儲的一個(gè)危險是很容易造成浪費。對我們來(lái)說(shuō),我并沒(méi)怎么注意刪除無(wú)用文件的后臺作業(yè)業(yè),對于創(chuàng )建的文件,最終會(huì )刪除掉近75%,而無(wú)用文件增長(cháng)起來(lái)是很快的。
即使我們曾經(jīng)注意到了這個(gè)問(wèn)題,我們事實(shí)上還是決定忽略它。Picnik的每一個(gè)人都很忙,而且這看起來(lái)也不是什么大不了的問(wèn)題,再說(shuō)了,還有更棒的新功能或其他的伸縮性問(wèn)題需要我們去關(guān)注。有趣的是,S3讓我們選擇或者雇用和訓練更多的人,或者更簡(jiǎn)單,寫(xiě)張支票就行了。在我們的信用卡月度額度快用光的時(shí)候,一切都變了。
經(jīng)過(guò)幾個(gè)月的調整、分析和重寫(xiě)代碼,我們最后拿出了一份清理無(wú)用文件的可伸縮方案。首先是數據庫對無(wú)用文件記錄進(jìn)行清理,然后在數據庫的文件記錄和S3上的關(guān)鍵字列表之間做一個(gè)大型的連接操作(a large merge-join),以執行實(shí)際的刪除。
在實(shí)現更好的清理系統的過(guò)程中間,我們開(kāi)始意識到,S3對我們的工作負荷(workload)來(lái)說(shuō),實(shí)際上是非常昂貴的。先前的成本分析完全沒(méi)有考慮PUT操作的成本。很多S3的負荷中,存儲成本占了大頭,因為文件上載以后,在隨后的一個(gè)很長(cháng)時(shí)段內,只是偶爾訪(fǎng)問(wèn)下。正如前面所提到的,我們的負荷是創(chuàng )建大量文件,然后在隨后的幾天里就刪掉了這意味著(zhù)PUT操作的成本上升了。
意識到這點(diǎn)以后,我們開(kāi)始努力優(yōu)化Mogilefsl的性能,并且研究高性能的NAS產(chǎn)品。最后,我們實(shí)現了一個(gè)基于Linux的NFS概念系統作為前端存儲,這意味著(zhù)只需要在S3上存儲超過(guò)1周的大約25%的文件,這些留下來(lái)的文件也有了一個(gè)對S3來(lái)說(shuō)更加友好的存取模式。
有很長(cháng)一段時(shí)間,我們都不清楚S3是不是仍然合適。盡管更為傳統的NAS硬件看起來(lái)貴了點(diǎn),但如果你對長(cháng)期存儲需求有信心的話(huà),可以在一年或兩年內分期付款。而另一方面,許多創(chuàng )業(yè)公司的CFO(包括我們自己的)都會(huì )告訴你,為了保持靈活性和一定程度的自由,多花點(diǎn)兒錢(qián)也值得一一這種靈活與自由就是S3提供的。當然,這種靈活性比將此花費算做運維費用還是資本費用更為重要。至于我們所關(guān)心的,就只是運維費用了,因為這直接與流量和功能有關(guān)。
混合計算
Picnik主要的服務(wù)端組件之一是我們的渲染場(chǎng)(render farm)。用戶(hù)在Picnik上保存圖片時(shí),經(jīng)常需要在服務(wù)端重建這個(gè)圖片。這時(shí),客戶(hù)端會(huì )向服務(wù)器發(fā)送一大段XML文本描述用戶(hù)的編輯操作。Web服務(wù)器收到后,會(huì )將所需要的圖片連同XML文本一起打包,并將其加入到渲染作業(yè)隊列中。渲染服務(wù)器獲取該作業(yè),重建圖片,然后將結果圖片返回給Web服務(wù)器。此時(shí),客戶(hù)端處于阻塞狀態(tài),等待服務(wù)器的響應。大多數時(shí)間,客戶(hù)只需要等待幾秒鐘。
雖然這是可伸縮系統的典型架構,我們在設計時(shí)仍然考慮到了未來(lái)對云計算的需求。這時(shí)的渲染服務(wù)器不需要訪(fǎng)問(wèn)任何內部服務(wù),如數據庫或存儲服務(wù)器。簡(jiǎn)言之,它們非常適合于運行在EC2上,另外,我們已有了一個(gè)自己開(kāi)發(fā)的配置管理和代碼部署系統,稱(chēng)為Server manager。
像S3一樣,實(shí)際實(shí)現起來(lái)既簡(jiǎn)單又快速。內部的渲染場(chǎng)已經(jīng)考慮到了運行在Xen之上的WM了,所以我需要做的就是一些簡(jiǎn)單修改,使渲染服務(wù)器的VM映像適合于EC2的Xen找,然后將其打包為AMI。在映像啟啟動(dòng)時(shí),首先連接Server manager?獲取需要安裝和運行的組件列表,其中之一是Renderserver,Renderserver用于連接渲染隊列以獲取渲染作業(yè)。我要做的第一件事就是激活兩個(gè)實(shí)例運行一下看看怎么樣一一棒極了!
第二階段就是去實(shí)現云操作的終極目標(loly Grail)了:自動(dòng)伸縮(auto-scaling)。我們的自動(dòng)伸縮實(shí)現起來(lái)還是很容易的,因為所有處理都是通過(guò)隊列實(shí)現的。由于用戶(hù)在等待渲染結果,所以自動(dòng)伸縮代碼的目標是維護一個(gè)空隊列5。每分鐘都會(huì )喚醒Server manager的一個(gè)線(xiàn)程,輪詢(xún)隊列的統計信息(上一分鐘已做過(guò)平衡),然后進(jìn)行計算,看為了維持閑者和忙者的比例需要做些什么。當然,由于流量和網(wǎng)絡(luò )延遲會(huì )有小幅波動(dòng),為避免不必要的振蕩而對閑忙比例的修正會(huì )出現遲滯現象,如EC2實(shí)例有的時(shí)候需要幾分鐘才能啟動(dòng),我們的代碼也考慮到了這些問(wèn)題。所有這些經(jīng)驗性的調整經(jīng)歷了一兩周的時(shí)間,系統運行起來(lái)以后,就非常簡(jiǎn)單啦。
自動(dòng)伸縮并不僅僅是典型的容量需求問(wèn)題,我們也遇到了諸如到EC2的網(wǎng)絡(luò )延遲加大了,或發(fā)布了一個(gè)代碼修正而使得渲染速度變慢了。遇到這些情況時(shí),我們先停止自動(dòng)伸縮,直到找出背后真正的原因并加以改正為止。我們還修正了一個(gè)錯誤,這個(gè)錯誤使一小部分用戶(hù)的保存操作失敗,這一修正使渲染負載増加了20%正好在圣誕節之前。
這種設置也很適合批處理作業(yè)。一段時(shí)間以前,我們要重建一批縮略圖,我就寫(xiě)了一些代碼,將作業(yè)提交給渲染隊列,然后用新的縮略圖文件更新數據庫記錄。我不需要做任何特別的事情來(lái)分配空間或將作業(yè)設置在晚上負載較輕的時(shí)候處理,Server manager只是增加新的實(shí)例以適應新的負載需求。
從財務(wù)方面來(lái)說(shuō),使用EC2比使用S3更清楚。我們試圖擴建內部渲染以滿(mǎn)足平均的容量需求,同時(shí),將做渲染的CPU轉換到做Web服務(wù)的CPU也容易。這意味著(zhù)將云作為渲染服務(wù)器給Web服務(wù)器帶來(lái)了一些動(dòng)態(tài)特性,這讓我們易于適應負載模式的變化,而且,通過(guò)逐漸購買(mǎi)硬件的方式,這也讓我們更有效地使用現有的硬件。例如,可以在數據中心訂購個(gè)新的機柜,然后把服務(wù)器上架,而不用擔心浪費大部分的機柜電力。
一般與EC2有關(guān)的問(wèn)題主要集中在連接性上。雖然互聯(lián)網(wǎng)作為一個(gè)整體是可靠的,但任何兩點(diǎn)之間的連接卻并非如此。通常,如果問(wèn)題出現在網(wǎng)絡(luò )和數據中心之間,只有一小部分用戶(hù)受影響,但是,假如網(wǎng)絡(luò )恰好是云計算提供者,則所有用戶(hù)都會(huì )受影響。這種類(lèi)型的宕機可能非常嚴重,因為問(wèn)題可能出在這樣的區域,就是不論是你還是云計算提供者都沒(méi)有為之付費,即雙不管的區域。
在發(fā)生嚴重問(wèn)題時(shí)(而且是在繁忙時(shí)段),唯一的選擇就是甩掉負載。過(guò)去,我們只有種辦法控制讓多少用戶(hù)進(jìn)來(lái),現在我們按優(yōu)先級將用戶(hù)分類(lèi)(游客、免費用戶(hù)、合作伙伴、金牌用戶(hù))??汕榈氖?,大多數情況下,你不得不等待宕機恢復。不論哪種情況,我們做的第一件事情就是更新 Twitter信息(fecd),這些消息也顯示在我們的It's raining onour Picnik”頁(yè)面上。我們并不指責任何人一個(gè)用戶(hù)才不關(guān)心這些呢。
我們并不像對內部服務(wù)器那樣監控EC2實(shí)例。Nagiosi通過(guò) Servermanager自動(dòng)獲取EC2實(shí)例的信息,Nagiost也監控隊列深度,因為這是很多問(wèn)題的預警器(early indicator)。
Caci以圖示方式顯示運行實(shí)例數(通過(guò)EC2API)及集群層層面上的性能數據。我們不需要在 Cacti上增加單個(gè)實(shí)例的信息,因為它并不實(shí)際處理集群,何況實(shí)例還是動(dòng)態(tài)變化的。
事實(shí)上,我們并不關(guān)心單個(gè)實(shí)例的性能,已經(jīng)知道這些實(shí)例比本地機器上的要慢一點(diǎn)。沒(méi)關(guān)系的,因為自動(dòng)伸縮系統總能在現有資源的條件下找到平衡。
由于實(shí)例是從隊列中獲取作業(yè)的,EC2實(shí)例稍微慢一點(diǎn),只是少干點(diǎn)活兒而已,不會(huì )躺倒不干。這使我能夠集中精力關(guān)注高層的性能數據,如一天中使用EC2實(shí)例的比例是多少。在一天結束時(shí),只需要針對web服務(wù)器做容量規劃,從而決定硬件購買(mǎi)決策,而渲染服務(wù)器只是從未使用的容量中獲益。
要想有效使用網(wǎng)站建設云計算資源,需要對應用架構和配置管理/自動(dòng)化有一個(gè)合理的“增長(cháng)”態(tài)度。我們將渲染服務(wù)器設計為可分解的,以及我們手邊已經(jīng)具備配置管理系統等,這些事實(shí)使得自動(dòng)伸縮實(shí)現起來(lái)既容易又可靠。
本文地址:http://havencoinwallet.com//article/3306.html