成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

理解Go、容器以及Linux調度器

開發 后端 Linux
在容器中運行Go應用程序時,需要設置合理的GOMAXPROCS,從而避免調度中因為資源不足而造成STW。

Go開發的應用程序通常部署在容器中。在容器中運行時,重要的一點是要設置CPU限制以確保容器不會耗光主機上的所有CPU。但Go運行時不知道容器上設置的CPU限制,因此有可能會把所有可用的CPU都用光,從而造成應用延遲很高。這個問題曾經困擾過我,在這篇文章中,我將解釋發生了什么以及如何修復。

Go垃圾收集器是如何工作的

這是對Go垃圾收集器(GC)的概要介紹,想要更深入了解,建議閱讀Go文檔[2]以及Will Kennedy的系列文章[3]。

絕大多數情況下,Go運行時在執行程序的同時執行垃圾收集,這意味著GC會與程序同時運行。然而,在GC過程中有兩個點需要Go運行時暫停所有Goroutine,從而確保數據完整性。在GC標記階段(Mark Phase)之前,運行時將暫停所有Goroutine,用以啟用寫屏障(write barrier),確保在此之后創建的任何對象都不會被GC,這個階段稱為掃描終止(Sweep Termination)。在標記階段完成后,還有一個STW(stop the world)階段,被稱為標記終止(Mark Termination),并且也是刪除寫屏障的過程。整個流程通常需要幾十微秒。

我創建了一個簡單的web應用,分配了大量內存,并使用以下命令在一個限制為4個CPU核的容器中運行,源代碼在Github[4]上。

docker run --cpus=4 -p 8080:8080 $(ko build -L main.go)

值得注意的是,docker CPU限制是硬性限制。可以設置--CPU-shares,表示只在主機CPU受限時強制執行。這意味著如果主機有空閑容量,容器可以使用超出分配的CPU核。但是如果主機資源受限,那么應用程序也將受到限制。

可以使用runtime/trace[5]包收集trace,然后用go tool trace對其進行分析。下面的trace顯示了在我的機器上捕獲的一個GC周期,可以看到在Proc 5中STW階段的掃描終止和標記終止。

這個GC周期只花了不到2.5ms,但我們在STW階段花費了近10%的時間。這是相當長的一段時間,特別是對于延遲敏感應用來說。

Linux調度器

完全公平調度程序(Complete Fair Scheduler, CFS)[6]是在Linux 2.6.23中引入的,在2023年10月份發布的Linux 6.6之前一直是默認調度程序,很可能你正在使用CFS。

CFS是一個比例共享調度器[7],意味著進程權重與允許使用的CPU內核數量成正比。例如,如果允許一個進程使用4個CPU核,那么它的權重將為4。如果一個進程被允許使用2個CPU核心,它的權重將為2。

CFS通過分配一小部分CPU時間來實現,一個4核系統每秒鐘有4秒的CPU時間可以分配。當我們為容器分配多個CPU內核時,實際上是要求Linux調度器給它n個CPU的時間。

在上面的docker run命令中,指定了4個CPU,意味著容器每秒將獲得4秒的CPU時間。

問題

當Go運行時啟動時,為每個CPU內核創建一個操作系統線程。這意味著如果有一個16核的機器,Go運行時將創建16個操作系統線程,不管任何CGroup CPU限制。然后Go運行時使用這些操作系統線程來調度程序。

問題是Go運行時不知道CGroup的CPU限制,而是在所有16個操作系統線程上調度goroutine,意味著Go運行時預計每秒能夠使用16秒的CPU時間。

由于Go運行時需要在等待Linux調度器調度的線程上停止gooutine,因此將面臨長時間的STW時間,因為一旦容器使用超過了CPU配額,線程就不會被調度。

解決方案

Go通過設置GOMAXPROCS環境變量限制運行時將創建的CPU線程數量。這一次,使用以下命令來啟動容器:

docker run --cpus=4 -e GOMAXPROCS=4 -p 8080:8080 $(ko build -L main.go)

下面是從與上面相同的應用程序捕獲的trace,現在使用與CPU配額匹配的GOMAXPROCS環境變量。

在這個trace中,盡管負載完全相同,但垃圾收集時間要短得多。GC周期小于1ms,STW時間為26μs,約為無限制時的1/10。

GOMAXPROCS應該設置為容器允許使用的CPU核數,通常情況應該向下取整,如果分配的CPU內核少于1個,則向上取整。可以用GOMAXPROCS=max(1, floor(cpu))來計算。Uber開源了一個庫automaxprocs[8]來自動從容器的cgroups中計算這個值。

有一個Github問題[9]支持將這個特性添加到Go運行時中,使其開箱即用,希望最終會被Go運行時接受!

結論

在容器化應用程序中運行Go時,設置CPU限制非常重要。通過設置合理的GOMAXPROCS值或使用像automaxprocs這樣的庫,確保Go運行時意識到這些限制也很重要。

參考資料

[1]Go, Containers, and the Linux Scheduler: https://www.riverphillips.dev/blog/go-cfs

[2]Go文檔: https://tip.golang.org/doc/gc-guide

[3]Garbage Collection In Go: https://www.ardanlabs.com/blog/2018/12/garbage-collection-in-go-part1-semantics.html

[4]示例代碼: https://github.com/RiverPhillips/go-cfs-blog

[5]runtime/trace package: https://golang.org/pkg/runtime/trace

[6]完全公平調度程序(Complete Fair Scheduler, CFS): https://docs.kernel.org/scheduler/sched-design-CFS.html

[7]Proportional share scheduling: https://en.wikipedia.org/wiki/Proportional_share_scheduling

[8]automaxprocs: https://github.com/uber-go/automaxprocs

[9]Github問題: https://github.com/golang/go/issues/33803

責任編輯:趙寧寧 來源: DeepNoMind
相關推薦

2023-10-25 12:51:28

Go調度器

2024-12-03 15:15:22

2021-07-05 06:51:45

Linux內核調度器

2021-07-02 06:54:44

Linux內核主調度器

2011-01-21 07:36:00

LinuxBFSCFS

2017-05-08 11:37:41

Go調度器源碼分析程序

2011-01-13 13:59:14

2021-05-12 07:50:02

CFS調度器Linux

2025-06-16 05:10:00

2025-01-15 09:13:53

2010-01-28 10:11:13

Linux 2.6公平調度器

2017-03-25 21:33:33

Linux調度器

2025-05-13 06:41:08

2022-10-30 15:00:50

2020-10-13 09:23:57

LinuxKernel調度器

2022-02-14 11:08:07

Linux容器命令

2022-09-15 10:42:21

API安全網絡攻擊

2022-07-29 10:01:50

Docker退出碼

2019-12-10 13:55:10

Go指針存儲

2009-09-16 08:40:53

linux進程調度linuxlinux操作系統
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品久久久久久福利一牛影视 | 久久午夜精品福利一区二区 | 一级毛片免费 | 亚洲欧洲成人 | 久久久久久久久91 | 久久男女视频 | 亚洲成人免费av | 亚洲综合视频 | 天天干天天干 | 亚洲九九精品 | 婷婷综合色 | 中文字幕免费中文 | 91色在线 | 国产成人网 | 欧美日韩国产精品一区 | 中文字幕一区二区在线观看 | 在线免费黄色 | 精品成人佐山爱一区二区 | 夜夜爽99久久国产综合精品女不卡 | 亚洲精品自在在线观看 | 亚洲成av人片在线观看 | 成人免费视频一区二区 | 成人影院免费视频 | 成人一级黄色毛片 | 国产精品一区视频 | 成人深夜福利网站 | 国产在线观看 | 久久久久久亚洲欧洲 | 玖玖在线免费视频 | 欧美一区二区三区在线 | 亚洲人免费视频 | 久久久久久久久久毛片 | 91精品国产高清一区二区三区 | 高清成人免费视频 | 日韩中文在线 | 亚洲精品一区在线观看 | 精品国产一二三区 | 亚洲久草视频 | 亚洲一区二区三区免费 | 中文字幕亚洲区一区二 | 欧美日韩视频在线 |