奇虎360 和go語言中文譯版
在中國,奇虎 360 是一個互聯網和手機安全產品及服務的主要供應商,截止到 2014 年 6 月,奇虎擁有 5 億的 PC 活躍用戶以及超過 6.4 億移動用戶。奇虎還運營著中國最受歡迎的網絡瀏覽器和 PC 搜索引擎。
我的團隊,推動服務團隊,為超過 50 個公司的產品提供服務(PC 和移動),包括成千上萬放在我們的開放平臺的應用程序。
我們對Go的青睞要從2012年第一次嘗試為奇虎的一個產品提供推送功能開始。最初的nginx + lua + redis方案因為負載過大沒能滿足我們對實時性能的需求。在這種情況下,最新發布的1.0.3版Go引起了我們的注意,借助它提供的goroutine 和channel特性,我們在幾周之內開發完成了一個原型。我們的系統最初運行在20臺服務器上,能夠處理2000萬實時連接,每天發送200萬信息。現在這套系統在超過400臺服務器運行,支持2億實時連接,每天發送超過100億條信息。
隨著商業上的快速擴張以及對我們推送服務的需求的增長,最初的Go系統很快遇到了瓶頸:堆大小達到69G、GC停頓最高能到3-6秒。更頭疼的是,我們必須每周重啟系統來釋放內存。實話實話,我們考慮過放棄Go,用C來重寫全部的核心組件作為替代。然而,并未如我們所愿,我們在遷移業務邏輯層的代碼時遇到了麻煩。結果就是,作為當時唯一的人員,我不可能在維護這個Go系統的時候確保業務邏輯順利遷移到C的服務框架上。
因此,我決定繼續留在Go系統上(可能是我最機智的一次無奈選擇),并且很快就取得了重大進展。
下面是幾個要點和我們總結的小技巧:
- 用長連接(使用連接池)替代短連接,減少通信過程中緩沖區和對象的創建。
- 適當的使用對象池和內存池,減少GC的負載。
- 使用任務池,原理是由一組協程作為消費者輪詢并執行全局的任務或者來自消息隊列的任務——由持有連接的協程作為生產者發送任務,用這種模式取代為每個任務生成一個臨時協程。
- 監視并控制程序中協程的數量。缺乏控制會使GC不堪重負,比如,因為不加控制的接受外部請求而出現的協程數峰值施加在GC上,同時發往內部服務的RPC調用可能阻塞新創建的協程。
- 在移動網絡中,要記得給連接[設置讀寫超時限制](http://golang.org/pkg/net/#Conn),否則可能導致協程阻塞。在局域網中就要慎重使用此設置,否則會降低RPC通信的效率。
- 使用Pipeline(在TCP全雙工特征下)來增強RPC框架的通信效率。
最后,我們成功的對架構進行了三次迭代,其中有兩次對 RPC 框架的迭代還是在人手有限的情況下完成的。這都得益于 Go 開發的便利性,下面是我們當前的系統架構:
持續優化的過程可以通過下表來說明:
還有,在這些優化之后,再也不需要臨時的釋放內存或者重啟系統了。
更令人興奮的時我們已經開發了一個線上實時反映 Go 程序運行概況的可視化平臺。現在我們很輕松的就可以拿到系統狀態并做出診斷,消除隱患。這是系統運行中的截圖:
這個平臺還可以做一件很棒的事情——模擬數百萬用戶在線的連接和操作。通過使用這個分布式的壓力測試工具(也是用 Go 實現),并觀察所有這些直觀的實時數據。我們評估每一次優化的效果并且定位系統瓶頸然后排除問題。
到目前為止,我們幾乎試遍了所有系統優化的手段。我們還是期盼 GC 團隊能帶來更多的好消息讓我們進一步的從繁重的開發工作中解脫出來。想來,也許有一天我們的這些經驗會因為 Go 的持續發展而變得無用武之地。
這也是為什么我要以表達獲得了這次出席 Gopher China 的機會的謝意來結束此次分享的原因。這是一個我們去學習,去分享的盛會,也是一個展現 Go 在中國的普及和繁榮的契機。在奇虎內部有許多其他的團隊開始去了解 Go,或者已經在試著使用 Go。
在可預見的將來,我相信中國會有更多的互聯網公司加入我們的行列,用 Go 來重新創建他們的系統,而 Go 開發團隊的成果會使更多的開發者和公司收益。