過去幾個月,我在用Go語言編寫系統,所以一直密切關注能夠證實我的選擇是正確的”的那些訊息。當Iron.io記錄下使用Go重寫IronWorker的經驗時,機會出現了。Iron.io中非常忙碌的作業執行系統最初是用Ruby編寫的。
重寫的結果是:
- 伺服器數量從30台減少到2台,而且第2台僅用於實現冗餘。
- CPU利用率下降至5%以下。
- 所用記憶體也下降了很多。Rails應用在啟動時需要接近50MB記憶體,而Go版本在啟動時只需要幾百KB記憶體。
- 連鎖故障成為曆史。
- 運行於成百上千台伺服器上的新服務完全用Go編寫。
- 他們認為,Go的使用使他們得以“構建偉大的產品,得以成長和擴充,同時還能吸引一流人才”。他們的部落格中寫道:“我們認為,在可預見的未來,它將繼續協助我們成長。”一般建議根據人才庫的規模來選擇程式設計語言,他們發現Go語言的選擇協助他們吸引了頂級人才。
- 容易部署,因為Go程式會編譯為一個單一靜態映像。
- Go存在的小問題:需要學習一種新語言,庫還有限。
- 如果伺服器流量很高,或者你想應對突發的增長,Go是很好的選擇。
當然,如果沒有第二系統效應(Second System Effect)的影響,重寫會快得多,不過你可能會回想起LinkedIn的類似經驗:LinkedIn從Rails遷移到Node:伺服器減少27台,速度提升多達20倍。
下面說明一下Go解決的問題:
- 在使用Ruby時,伺服器的CPU利用率維持在50%到60%之間。為將CPU利用率保持在50%左右,可以增加伺服器,這樣就可以優雅地處理流量峰值。但這種方式有個缺點:需要昂貴的伺服器來進行水平擴充。
- 他們有一個非常有趣的故障模式。當流量出現峰值時,Rails伺服器的CPU利用率將達到100%。這就致使該伺服器看上去是失效了,進而引發負載平衡器把流量路由到其餘伺服器上,這樣更多伺服器的CPU利用率會飆升到100%。最終導致連鎖故障。
使用Ruby有助於產品快速上市,這個理由十分在理。雖說效能並非一切,但這裡我們看到了效能的價值,尤其是在Web層之外,效能更為重要。表現良好的服務在健壯性和成本方面都有巨大優勢。
以往,系統的弱點被伺服器的量所掩蓋,但大量伺服器要花很多錢,而且未必總能解決問題。
效能起到了緩衝作用,使系統既能承載流量而不至崩潰,又能容忍一次次的突發衝擊。即時(Just-in-time)分配和啟動新執行個體都需要時間,而長時間的流量峰值可能引發連鎖故障。針對效能編碼,而不是針對產品上市時間編碼,即可防患於未然。
Go並不完美
如果看一下Go的Google網上論壇,你會發現Go並不是沒有效能問題。不過這些問題往往可以編碼繞過。比如用bufio.ReadSlice代替bufio.ReadString,能夠去掉一次資料複製,代碼魔法般地快了若干倍。
學習這些技巧是需要時間的,尤其對這樣一種新語言而言。
讓Go真正處於不利地位的是,JVM和V8 JavaScript引擎在記憶體回收最佳化和代碼產生方面已經有了許多年的經驗積累。Go要趕上尚需時日。
效能永遠不會是免費的。你必須巧妙地編碼,將狀態共用最小化,不要老翻騰記憶體,要儘力剖析,理解自己的語言並且能夠用這種語言來做正確的事。
查看英文原文:Iron.io Moved From Ruby to Go: 28 Servers Cut and Colossal Clusterf**ks Prevented
來源:http://www.infoq.com/cn/news/2013/03/ruby-to-go