引用書籍<<GO語言程式設計之旅>>
問題描述
在Go語言中,Go scheduler的P數量非常重要,因為它會極大地影響Go在運作時的表現。
在目前的Go語言中,P的數量預設是系統的CPU核數。在容器化的環境中,Go程式所擷取的CPU核數是錯誤的,它所擷取的是主控端的CPU核數。即使容器和主控端的CPU核數是共享的,但在叢集中我們會針對每個Pod配置設定指定的核數,是以實際上我們需要的是Pod的核數,而不是主控端的CPU核數。
造成的後果
曾提到Go的M:N排程模型,其要求M必須與P進行綁定,然後才能不斷地在M上循環尋找可運作的G來執行相應的任務。
注意,M必須與P進行綁定,其綁定的這個P,要求必須是空閑狀态。
但在容器化的部署環境中,P 的數量由于被“錯誤”設定,是以擁有大量空閑的 P。可以這樣了解,隻要有足夠多的M,那麼P就可以都被綁定。這時又産生了另外一個問題,M的數量是否會不斷增加呢?答案是會的。在程式運作過程中,由于産生了網絡I/O阻塞,導緻M會随着程式的不斷執行而不斷增加,,即能夠達到前面假設的情況。最終導緻Go程式的延遲加大,程式響應緩慢。
解決方法
産生這個問題的本質原因是Go程式沒有正确地獲得我們所期望的CPU核數(應當擷取具體配置設定給Pod的配額),是以解決方案有兩種:· 結合部署情況,主動設定正确的GOMAXPROCS核數。· 通過cgroup資訊,讀取容器内的正确GOMAXPROCS核數。
目前,Go 尚沒有非常完美的辦法來解決這個問題,是以這裡推薦使用 Uber 公司推出的uber-go/automaxprocs 開源庫,它會在 Go 程式運作時根據 cgroup 的挂載資訊來修改GOMAXPROCS核數,并基于一定規則選擇一個最合适的數值
在main裡面初始化導入這個包
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2YfNWawNCM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TP310dZpXT4FFVOBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL2UDO5ADN1UTM2ETOwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
我們隻需在 Go 程式啟動時進行引用即可,如果有特殊的需求,那麼主動設定GOMAXPROCS也是可以的。