Go 部落格

奇虎 360 和 Go

楊州
2015 年 7 月 6 日

這篇客座部落格文章由奇虎 360 的軟體工程師楊州撰寫。

奇虎 360 是中國主要的網際網路與行動安全產品及服務供應商,並經營一個主要的 Android 系統行動裝置發行平台。截至 2014 年 6 月底,奇虎擁有約 5 億名每月活躍的電腦網際網路使用者,以及超過 6.4 億名行動裝置使用者。奇虎也經營中國其中一個最受歡迎的網際網路瀏覽器和電腦搜尋引擎。

我的團隊,推播服務團隊,為公司內超過 50 種產品提供基本通訊服務(包含電腦與行動裝置),包括我們的開放平台上數千種應用程式。

我們與 Go 的「戀情」始於 2012 年,當時我們首次嘗試為奇虎的產品提供推送服務。初始版本採用 nginx + lua + redis 構建,但因負載過重而無法滿足我們的即時性能需求。在這種情況下,我們注意到了新發布的 Go 1.0.3 版本。得益於它提供的 goroutine 和管道功能,我們在幾週內就完成了一個原型。

最初,我們基於 Go 的系統在 20 台伺服器上運行,總共建立了 2000 萬個即時連線。系統每天發送 200 萬條訊息。現在,該系統在 400 台伺服器上運行,支援 2 億以上的即時連線。它現在每天發送超過 100 億條訊息。

隨著業務快速擴張和應用程式對推送服務的需求不斷增加,最初的 Go 系統很快就遇到了瓶頸:堆大小增加到 69G,最大垃圾回收 (GC) 暫停為 3-6 秒。更糟的是,我們必須每週重新開機系統以釋放記憶體。如果我們不考慮放棄 Go,而是使用 C 重新編寫整個核心元件,那就太不誠實了。然而,事情的發展並不如我們計劃的那樣,我們在移植業務邏輯層的程式碼時遇到了問題。結果,當時的唯一負責人(我自己)不可能在確保邏輯傳輸到 C 服務架構的同時維護 Go 系統。

因此,我決定繼續使用 Go 系統(這可能是我的明智之舉),很快就取得了重大進展。

以下是一些我們做出的調整和主要心得

  • 使用持續連線(使用連線池)取代短暫連線,以減少通訊期間的緩衝區和物件建立。
  • 適當地使用物件和記憶體池,以降低 GC 負載。
  • 使用任務池,這是一種具有長存 goroutine 群組的機制,用於使用連線 goroutine 所傳送的全球性任務或訊息佇列,以替換短暫的 goroutine。

  • 監控並控制程式中的 goroutine 數量。失控的 goroutine 數量會對 GC 造成沉重負擔,因為接受外部要求時,會不受限制地激增 goroutine,而傳送到內部伺服器的 RPC 呼叫可能會封鎖最近建立的 goroutine。

  • 記得在行動網路下為連線新增 讀取和寫入期限,否則可能會導致 goroutine 阻塞。在區域網路下使用時務必正確而且小心,否則 RPC 通訊效率會受到影響。

  • 使用管道(TCP 的全雙工功能)來提升 RPC 框架的通訊效率。

因此,在人力資源有限的狀況下,我們成功發佈了三次架構版本以及兩次 RPC 框架版本。這一切都要歸功於 Go 的開發便利性。以下是最新的系統架構

持續改進旅程可以用表格來說明

此外,在這些最佳化後,不需要暫時釋放記憶體或重新開機系統。

更令人興奮的是,我們開發了一個線上、即時的可見性平台來剖析 Go 程式。現在,我們可以輕鬆存取和診斷系統狀態,找出潛在風險。以下是一個顯示系統運作的螢幕截圖

此平台的優點是我們可以實際模擬數百萬名線上使用者的連線和行為,方法是使用分散式壓力測試工具(也是用 Go 撰寫)並觀察所有即時可視化資料。這讓我們可以評估最佳化的有效性,並透過辨識系統瓶頸來預防問題。

到目前為止,已經執行幾乎所有可能的系統最佳化。我們期待 GC 團隊有更多好消息,如此一來,我們可以進一步減輕繁重的開發工作。我想隨著 Go 持續演進,我們的經驗有一天也會過時。

這就是我想要藉由分享結束時表達我的真誠感謝,感謝有機會參加 Gopher China。能夠學習、分享並提供一個櫥窗展示 Go 在中國受歡迎及繁榮的程度,對我們來說是一場盛宴。奇虎內部已有許多其他團隊認識了 Go,或是嘗試使用 Go。

我確信很多中國網際網路公司將加入我們,用 Go 重新建立他們的系統,而 Go 團隊的努力將會在可見的未來,惠及更多開發人員和企業。

下一篇:Go 開源與社群
前一篇:GopherChina 行程報告
部落格索引