<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Uber:大規(guī)模、半自動(dòng)化 Go GC 調(diào)優(yōu)

          共 4719字,需瀏覽 10分鐘

           ·

          2022-01-19 14:04

          Uber 是國外大規(guī)模使用 Go 的公司之一,在 GitHub 上,他們開源了不少 Go 相關(guān)項(xiàng)目。最出名的有以下幾個(gè):

          • zap
          • fx、dig
          • guide

          其中 guide 是他們內(nèi)部的 Go 編碼規(guī)范,目前已經(jīng)被翻譯成了多國語言,其中包括簡體中文版本:https://github.com/xxjwxc/uber_go_guide_cn。

          Uber 更多內(nèi)容開源項(xiàng)目可以訪問他們的 GitHub 首頁:https://github.com/uber-go。

          此外,https://github.com/jaegertracing/jaeger 也是 Uber 開發(fā)的,之后捐贈(zèng)給 CNCF,這是一個(gè)分布式追蹤平臺(tái),用于監(jiān)控基于微服務(wù)的分布式系統(tǒng)。

          因此他們?cè)?Go 上有很多經(jīng)驗(yàn)。本文介紹 Uber 如何在 30 個(gè)關(guān)鍵任務(wù)服務(wù)中節(jié)省 7 萬個(gè)內(nèi)核。

          本文作者是 Cristian Velazquez,他是 Uber Maps Production Engineering 團(tuán)隊(duì)的 Sr Production Engineer II。他負(fù)責(zé)跨多個(gè)組織的多個(gè)效率計(jì)劃,其中最相關(guān)的是 Java 和 Go 的垃圾收集調(diào)優(yōu)。

          1、介紹

          實(shí)現(xiàn)盈利的方式有開源和節(jié)流,對(duì)于 Uber 技術(shù)團(tuán)隊(duì)(其他公司技術(shù)團(tuán)隊(duì)其實(shí)也類似)來說,提升資源利用率,進(jìn)而減少服務(wù)器數(shù)量,這是減少成本的一種方式。有些公司通過換語言實(shí)現(xiàn),比如 Python 換為 Go 等。而對(duì) Go 服務(wù)來說,可能最有效的工作是針對(duì) GOGC 的優(yōu)化。在本文中,我們將分享在高效、低風(fēng)險(xiǎn)、大規(guī)模、半自動(dòng)化的 Go GC 調(diào)優(yōu)機(jī)制方面的經(jīng)驗(yàn)。

          Uber 有數(shù)千個(gè)微服務(wù),并由基于云原生和基于調(diào)度程序的基礎(chǔ)設(shè)施提供支持,這些服務(wù)大部分是用 Go 編寫的。我們的 Maps Production Engineering 團(tuán)隊(duì)之前在 Java 微服務(wù) GC 調(diào)優(yōu)方面有很多經(jīng)驗(yàn),也取得了很好的效果,現(xiàn)在這些經(jīng)驗(yàn)在 Go GC 方面也發(fā)揮了重要的作用。

          2021 年初,我們探索了對(duì) Go 服務(wù)進(jìn)行 GC 調(diào)優(yōu)的可能性。我們運(yùn)行了幾個(gè) CPU 配置文件來評(píng)估當(dāng)前的事務(wù)狀態(tài),我們發(fā)現(xiàn) GC 是絕大多數(shù)關(guān)鍵任務(wù)服務(wù)的 CPU 最大消耗者。以下是一些 CPU 配置文件的表示,其中 GC(由 runtime.scanobject 方法標(biāo)識(shí))消耗了分配的計(jì)算資源的很大一部分。

          示例服務(wù) #1:

          圖 1:示例服務(wù) #1 的 GC CPU 成本

          示例服務(wù) #2

          圖 2:示例服務(wù) #2 的 GC CPU 成本

          受到這一發(fā)現(xiàn)的啟發(fā),我們開始為相關(guān)服務(wù)調(diào)整 GC。令我們高興的是,Go 的 GC 實(shí)現(xiàn)和調(diào)整的簡單性使我們能夠自動(dòng)化大部分檢測(cè)和調(diào)整機(jī)制。我們將在以下部分詳細(xì)介紹我們的方法及其效果。

          2、GOGC Tuner

          除了觸發(fā)事件,Go 運(yùn)行時(shí)會(huì)定期調(diào)用并發(fā)垃圾收集器,其中觸發(fā)事件是基于內(nèi)存值的。因此, 更多內(nèi)存對(duì) Go 服務(wù)來說更有利,因?yàn)樗鼫p少了 GC 必須運(yùn)行的時(shí)間。此外,我們意識(shí)到我們的主機(jī) CPU 與內(nèi)存的比例是 1:5(1 核:5 GB RAM),而大多數(shù) Go 服務(wù)的配置比例是 1:1 ~ 1:2。因此,我們有信心可以利用更多內(nèi)存來減少 GC 的 CPU 影響。這是一種與服務(wù)無關(guān)的機(jī)制,如果應(yīng)用得當(dāng),會(huì)產(chǎn)生很大的影響。

          深入研究 Go 的垃圾收集超出了本文的范圍,但以下是這項(xiàng)工作的相關(guān)部分:Go 中的垃圾收集是并發(fā)的,涉及分析所有對(duì)象以確定哪些對(duì)象仍然可以訪問。我們將可到達(dá)對(duì)象稱為“實(shí)時(shí)數(shù)據(jù)集”。Go 僅提供一個(gè)選項(xiàng):GOGC, 以實(shí)時(shí)數(shù)據(jù)集的百分比表示,用于控制垃圾收集。GOGC 值充當(dāng)數(shù)據(jù)集的乘數(shù)。GOGC 的默認(rèn)值為 100%,這意味著 Go 運(yùn)行時(shí)將為新分配保留與實(shí)時(shí)數(shù)據(jù)集相同的內(nèi)存量。例如:

          hard_target = live_dataset + live_dataset * (GOGC / 100).

          然后,pacer 負(fù)責(zé)預(yù)測(cè)觸發(fā) GC 的最佳時(shí)間,以避免命中硬目標(biāo)(軟目標(biāo))。

          圖 3:具有默認(rèn)配置的示例堆

          3、動(dòng)態(tài)多樣:一個(gè)值無法適應(yīng)所有場(chǎng)景

          我們發(fā)現(xiàn)固定的 GOGC 值的調(diào)整不適合 Uber 的服務(wù)。以下是可能的挑戰(zhàn):

          • 它不知道分配給容器的最大內(nèi)存,并可能導(dǎo)致內(nèi)存不足問題。
          • 我們的微服務(wù)有各種內(nèi)存利用率組合。例如,分片系統(tǒng)可以有非常不同的實(shí)時(shí)數(shù)據(jù)集。我們?cè)谄渲幸豁?xiàng)服務(wù)中遇到了這種情況,其中 p99 利用率為 1G 但 p1 為 100MB,因此 100MB 實(shí)例具有巨大的 GC 影響。

          4、自動(dòng)化案例

          GOGCTuner 是一個(gè)庫,它簡化了為服務(wù)所有者調(diào)整垃圾收集的過程,并在其之上添加了一個(gè)可靠層。

          GOGCTuner 根據(jù)容器的內(nèi)存限制(或服務(wù)所有者的上限)動(dòng)態(tài)計(jì)算正確的 GOGC 值,并使用 Go 的運(yùn)行時(shí) API 設(shè)置它。以下是 GOGCTuner 庫功能的詳細(xì)信息:

          • 簡化配置,便于推理和確定性計(jì)算。對(duì)于初學(xué)者來說,GOGC=100% 的確定性不足,因?yàn)樗匀灰蕾囉趯?shí)時(shí)數(shù)據(jù)集。另一方面,70% 的限制可確保服務(wù)始終使用 70% 的堆空間。
          • 防止 OOM(內(nèi)存不足):該庫從 cgroup 讀取內(nèi)存限制并使用 70% 的默認(rèn)硬限制,根據(jù)我們的經(jīng)驗(yàn),這是一個(gè)安全值。
            • 需要注意的是,這種保護(hù)是有限制的。Tuner 只能調(diào)整緩沖區(qū)分配,因此如果你的服務(wù)活動(dòng)對(duì)象高于限制,則 Tuner 將設(shè)置默認(rèn)下限為 1.25X 你的活動(dòng)對(duì)象利用率。
          • 對(duì)于極端情況允許更高的 GOGC 值,例如:
            • 正如我們上面提到的,手動(dòng) GOGC 不是確定性的。我們?nèi)匀灰蕾噷?shí)時(shí)數(shù)據(jù)集的大小。如果 live_dataset 將我們的最后一個(gè)峰值翻倍了怎么辦?GOGCTuner 將以更多 CPU 為代價(jià)強(qiáng)制執(zhí)行相同的內(nèi)存限制。相反,手動(dòng)調(diào)整可能會(huì)導(dǎo)致 OOM。因此,服務(wù)所有者過去常常為這些類型的場(chǎng)景提供足夠的緩沖。請(qǐng)參見下面的示例:

          正常流量(實(shí)時(shí)數(shù)據(jù)集為 150M)

          圖 4:正常操作。左側(cè)為默認(rèn)配置,右側(cè)為手動(dòng)調(diào)整

          流量增加了 2 倍(實(shí)時(shí)數(shù)據(jù)集為 300M)

          圖 5:雙倍負(fù)載。左側(cè)為默認(rèn)配置,右側(cè)為手動(dòng)調(diào)整

          GOGCTuner 達(dá)到 70% 時(shí)流量增加了 2 倍(實(shí)時(shí)數(shù)據(jù)集為 300M)

          圖 6:將負(fù)載加倍,但使用調(diào)諧器。左邊是默認(rèn)配置,右邊是GOGCTuner調(diào)優(yōu)
          • 使用 MADV_FREE[1] 內(nèi)存策略的服務(wù)會(huì)導(dǎo)致錯(cuò)誤的內(nèi)存指標(biāo)。例如,我們的可觀察性指標(biāo)顯示 50% 的內(nèi)存利用率(實(shí)際上它已經(jīng)釋放了 50% 中的 20%)。然后服務(wù)所有者只是使用這個(gè)“不準(zhǔn)確”的指標(biāo)來調(diào)整 GOGC。

          5、可觀察性

          我們發(fā)現(xiàn)缺乏一些關(guān)鍵指標(biāo),這些指標(biāo)可以讓我們更深入地了解每個(gè)服務(wù)的垃圾收集。

          • 垃圾收集之間的間隔:了解我們是否仍然可以調(diào)整很有用。例如,Go 強(qiáng)制每 2 分鐘進(jìn)行一次垃圾收集。如果你的服務(wù)仍然具有較高的 GC 影響,但你已經(jīng)看到此圖的 120 秒,這意味著你不能再使用 GOGC 進(jìn)行調(diào)優(yōu)。在這種情況下,你需要優(yōu)化分配。

          圖 7:GC 之間的間隔圖表
          • GC CPU 影響:知道哪些服務(wù)受 GC 影響最大。

          圖 8:p99 GC CPU 成本圖表
          • 實(shí)時(shí)數(shù)據(jù)集(Live dataset)大小:幫助我們識(shí)別內(nèi)存泄漏。服務(wù)所有者注意到的問題是他們看到內(nèi)存利用率有所增加。為了向他們展示沒有內(nèi)存泄漏,我們添加了“實(shí)時(shí)使用”指標(biāo),該指標(biāo)顯示了穩(wěn)定的利用率。

          圖 9:估計(jì)的 p99 實(shí)時(shí)數(shù)據(jù)集圖表
          • GOGC 值:有助于了解調(diào)諧器的反應(yīng)。

          圖 10:調(diào)諧器分配給應(yīng)用程序的 min、p50、p99 GOGC 值圖表

          6、實(shí)現(xiàn)

          我們最初的方法是每秒運(yùn)行一次代碼來監(jiān)控堆指標(biāo),然后相應(yīng)地調(diào)整 GOGC 值。這種方法的缺點(diǎn)是開銷開始變得相當(dāng)大,因?yàn)闉榱俗x取堆指標(biāo),Go 需要執(zhí)行 STW(ReadMemStats[2]),并且它有點(diǎn)不準(zhǔn)確,因?yàn)槲覀兠棵肟梢赃M(jìn)行多次垃圾收集。

          幸運(yùn)的是,我們找到一個(gè)不錯(cuò)的方法。Go 有終結(jié)器(SetFinalizer[3]),它們是在對(duì)象將被垃圾收集時(shí)運(yùn)行的函數(shù)。它們主要用于清理 C 代碼或其他一些資源的內(nèi)存。我們能夠使用一個(gè)自引用終結(jié)器,它會(huì)在每次 GC 調(diào)用時(shí)自行重置。這使得我們能夠減少 CPU 開銷。例如:

          圖 11:GC 觸發(fā)事件的示例代碼

          調(diào)用 runtime.SetFinalizer(f, finalizerHandler) 代替直接調(diào)用 finalizerHandler 以允許處理程序在每次 GC 上運(yùn)行;它基本上不會(huì)讓引用消失,因?yàn)樗皇潜;畹陌嘿F資源(它只是一個(gè)指針)。

          7、影響

          在我們的幾十個(gè)服務(wù)中部署了 GOGCTuner 之后,我們深入研究了其中一些顯著的、CPU 利用率提高到兩位數(shù)的服務(wù)。僅這些服務(wù)就累計(jì)節(jié)省了大約 70K 個(gè)內(nèi)核。以下是 2 個(gè)這樣的示例:

          圖 12:可觀察性服務(wù)在數(shù)千個(gè)計(jì)算內(nèi)核上運(yùn)行,live_dataset 具有高標(biāo)準(zhǔn)偏差(最大值是最小值的 10 倍),顯示 p99 CPU 利用率降低了約 65%

          圖 13:任務(wù)關(guān)鍵型 Uber 吃掉在數(shù)千個(gè)計(jì)算核心上運(yùn)行的服務(wù),顯示 p99 CPU 利用率降低了約 30%

          由此產(chǎn)生的 CPU 利用率降低在戰(zhàn)術(shù)上改善了 p99 延遲(以及相關(guān)的 SLA、用戶體驗(yàn)),并在戰(zhàn)略上改善了容器成本(因?yàn)榉?wù)是根據(jù)其利用率進(jìn)行擴(kuò)展的)。

          8、總結(jié)

          垃圾收集(GC)是應(yīng)用程序中最難以捉摸,同時(shí)也是被低估的性能影響因素之一。Go 強(qiáng)大的 GC 機(jī)制和簡化的調(diào)優(yōu),加之我們大規(guī)模的 Go 服務(wù)以及強(qiáng)大的內(nèi)部平臺(tái)(如 Go、計(jì)算、可觀察性),使我們能夠產(chǎn)生如此大規(guī)模的影響。由于技術(shù)和能力的變化,同時(shí)問題空間本身的發(fā)展,我們希望繼續(xù)改進(jìn)我們調(diào)整 GC 的方式。

          最后再次重申我們?cè)陂_頭提到的內(nèi)容:沒有一個(gè)適合所有場(chǎng)景的 GOGC 值。由于公有云和運(yùn)行在其中的容器化工作負(fù)載的性能高度可變,我們認(rèn)為 GC 性能在云原生設(shè)置中將保持可變。再加上我們使用的絕大多數(shù) CNCF 可觀測(cè)項(xiàng)目都是用 Go 編寫的(如 Kubernetes、Prometheus、Jaeger 等),這意味著任何外部的大規(guī)模部署也可以從這種努力中受益。

          比較可惜的是,目前沒看到 Uber 開源了這個(gè)工具。

          來自公眾號(hào):幽鬼

          原文鏈接:https://eng.uber.com/how-we-saved-70k-cores-across-30-mission-critical-services/

          參考資料

          [1]

          MADV_FREE: https://man7.org/linux/man-pages/man2/madvise.2.html

          [2]

          ReadMemStats: https://golang.org/pkg/runtime/#ReadMemStats

          [3]

          SetFinalizer: https://golang.org/pkg/runtime/#SetFinalizer



          推薦閱讀


          福利

          我為大家整理了一份從入門到進(jìn)階的Go學(xué)習(xí)資料禮包,包含學(xué)習(xí)建議:入門看什么,進(jìn)階看什么。關(guān)注公眾號(hào) 「polarisxu」,回復(fù)?ebook?獲?。贿€可以回復(fù)「進(jìn)群」,和數(shù)萬 Gopher 交流學(xué)習(xí)。

          瀏覽 128
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久国产高清视频免费看 | www色老板 | 91麻豆精品国产91久久久久久久久 | 国产精品久久久久久久久久中字幕 | 超碰乱轮|