Go 部落格

奇虎 360 與 Go

周洋
2015 年 7 月 6 日

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

奇虎 360 是中國主要的網際網路和移動安全產品及服務提供商,並運營著一個大型的基於 Android 的移動分發平臺。截至 2014 年 6 月底,奇虎擁有約 5 億月活躍 PC 網際網路使用者和超過 6.4 億移動使用者。奇虎還運營著中國最受歡迎的網際網路瀏覽器和 PC 搜尋引擎之一。

我的團隊,推送服務團隊,為公司內部 50 多個產品(包括 PC 和移動端)提供了基礎訊息服務,其中包括我們開放平臺上的數千個應用。

我們與 Go 的“情緣”可以追溯到 2012 年,當時我們首次嘗試為奇虎的一款產品提供推送服務。最初的版本是使用 nginx + lua + redis 構建的,由於負載過高,未能滿足我們對即時效能的要求。在這種情況下,新發布的 Go 1.0.3 版本引起了我們的注意。我們僅用了幾周時間就完成了一個原型,這主要得益於它提供的 goroutine 和 channel 特性。

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

隨著業務的快速擴張和對推送服務日益增長的應用需求,最初的 Go 系統很快達到了瓶頸:堆大小上升到 69G,最大垃圾回收 (GC) 暫停時間達到 3-6 秒。更糟糕的是,我們不得不每週重啟系統以釋放記憶體。如果我們不考慮放棄 Go 並用 C 重寫整個核心元件,那是不誠實的。然而,事情並沒有完全按照我們的計劃進行,我們在遷移業務邏輯層的程式碼時遇到了麻煩。結果是,當時唯一的維護人員(我自己)不可能在維護 Go 系統的同時,確保邏輯轉移到 C 服務框架。

因此,我決定繼續使用 Go 系統(這可能是我必須做出的最明智的決定),並且很快取得了很大的進展。

以下是我們進行的一些調整和一些關鍵的收穫:

  • 使用持久連線(使用連線池)替換短連線,以減少通訊過程中緩衝和物件的建立。
  • 適當使用物件池和記憶體池,以減輕 GC 的負載。
  • 使用任務池,這是一種由一組長期執行的 goroutine 消費連線 goroutine 傳送的全域性任務或訊息佇列的機制,以替代短期執行的 goroutine。

  • 監控和控制程式中的 goroutine 數量。缺乏控制可能導致 GC 承受難以承受的負擔,這是由於無限制地接受外部請求導致的 goroutine 激增造成的,因為傳送到內部伺服器的 RPC 呼叫可能會阻塞最近建立的 goroutine。

  • 在行動網路下,記得給連線新增讀寫截止時間;否則,可能會導致 goroutine 阻塞。在區域網下,應謹慎且適當地應用此設定,否則會影響 RPC 通訊效率。

  • 使用管道 (Pipeline)(利用 TCP 的全雙工特性)來提高 RPC 框架的通訊效率。

結果,儘管人力資源有限,我們成功推出了三次架構迭代和兩次 RPC 框架迭代。這一切都歸功於 Go 的開發便利性。下面是最新的系統架構圖:

持續改進的過程可以用下表說明:

此外,經過這些最佳化後,不再需要臨時釋放記憶體或重啟系統。

更令人興奮的是,我們開發了一個線上即時 Go 程式效能剖析的視覺化平臺。現在我們可以輕鬆訪問和診斷系統狀態,找出任何潛在的風險。這是一個系統執行中的螢幕截圖:

這個平臺最棒的地方在於,我們可以透過使用分散式壓力測試工具(也是用 Go 構建的)來模擬數百萬線上使用者的連線和行為,並觀察所有即時視覺化資料。這使我們能夠評估任何最佳化的有效性,並透過識別系統瓶頸來排除問題。

到目前為止,幾乎所有可能的系統最佳化都已實踐過。我們期待著 GC 團隊帶來更多好訊息,以便進一步減輕繁重的開發工作。我想我們的經驗總有一天會過時,因為 Go 還在不斷發展。

這就是為什麼我想以誠摯感謝能夠參加Gopher China 來結束我的分享。這對我們來說是一場盛會,可以學習、分享,並提供了一個視窗,展示 Go 在中國的普及和繁榮。奇虎內部的許多其他團隊都已經瞭解或嘗試使用 Go。

我相信,未來將有更多中國網際網路公司加入我們,用 Go 重建他們的系統,Go 團隊的努力將使更多開發者和企業受益。

下一篇文章:Go、開源、社群
上一篇文章:GopherChina 之行報告
部落格索引