https://blog.csdn.net/mingzhehaolove/article/details/77305832
情景描述:
30台服務器負載均衡,初始化建立rpc連接池,在rpc連接異常時,會進行重試,重試過程需要進行rand.Int 獲取隨機數,讀取一台連接,但是一開始沒有設定隨機種子導致,每一台第一次獲取的都是同一個機器,這樣所有的流量都打到一台,導致機器掛了。影響其它服務。
后來添加了隨機種子,但是有一次量上來的比較大,單個機器的內存飆升,接連影響其它機器的rpc連接,導致goroutinue達到250萬,pprof分析,是rand.Seed導致,查看文檔發現,官方給出這么一句
- // Seed uses the provided seed value to initialize the generator to a deterministic state.
- // Seed should not be called concurrently with any other Rand method.
因為我們的獲取機器方法,每次都需要seed,所以導致了這個問題,后續把rand.Seed 提到初始化方法,實現一次,這個問題就規避了。
使用rand.Int 獲取隨機數,不加隨機種子,每次遍歷獲取都是重復的一些數據
- package main
- import (
- "fmt"
- "math/rand"
- "sync"
- )
- func main() {
- num := 10
- for j := 0; j < num; j++ {
- res := getRand(num)
- fmt.Println(res)
- }
- }
- func getRand(num int) int {
- var mu sync.Mutex
- mu.Lock()
- v := rand.Intn(num)
- mu.Unlock()
- return v
- }
- 結果:
- 1
- 7
- 7
- 9
- 1
- 8
- 5
- 0
- 6
- 0
添加隨機種子 rand.Seed(time.Now().UnixNano()) 保證每次都是隨機的
- package main
- import (
- "fmt"
- "math/rand"
- "sync"
- "time"
- )
- func main() {
- num := 10
- for j := 0; j < num; j++ {
- res := getRand(num)
- fmt.Println(res)
- }
- }
- func getRand(num int) int {
- rand.Seed(time.Now().UnixNano())
- var mu sync.Mutex
- mu.Lock()
- v := rand.Intn(num)
- mu.Unlock()
- return v
- }
- 結果:
- 1
- 5
- 4
- 8
- 3
- 1
- 4
- 4
- 3
- 0
正常情況,做一些小的開發,這些無所謂,但是當開發一些高並發的處理時,rand.Seed就會發生問題,官方不建議在高並發情況下,使用rand.Seed,之所以我會遇到這種問題,也是因為,當時線上出了一個大問題,為了快速解決,就使用了rand.Seed. 為了得到隨機的線上機器,進行rpc調用。
