使用下面的客戶端代碼(以及此框上端口 8088 上的偵聽 Web 服務器),在從以下位置彈出此錯誤之前,我很少能夠獲得超過 23000 次點擊client.Get():panic: Get http://localhost:8088/: dial tcp 127.0.0.1:8088: can't assign requested address奇怪的是,如果我增加計時器延遲(即從一毫秒到一微秒),需要更多的點擊才能獲得錯誤,170,000 甚至更多。查看網絡流量,每個客戶端連接在斷開連接之前只使用了幾次(即客戶端發送一個 FIN)。很明顯,它正在建立許多 TCP 連接并溢出套接字表。鑒于 Golang HTTP 文檔說默認情況下啟用了 keepalive,我不希望出現這種情況。內核跟蹤顯示在關閉之前底層套接字沒有發出任何錯誤(EAGAIN 除外,這是預期的并且并不總是在套接字關閉之前)。這是 OSX (14.4.0) 上的 Go 1.4.2。為什么客戶端連接沒有一直被重用?package mainimport ( "io/ioutil" "net/http" "runtime" "sync" "time")var reqnum = 0func hit(client *http.Client) { resp, err := client.Get("http://localhost:8088/") if err != nil { println(reqnum) panic(err) } defer resp.Body.Close() _, err = ioutil.ReadAll(resp.Body) if err != nil { panic(err) } reqnum++ // not thread safe, but shouldn't cause errors.}func main() { var wg sync.WaitGroup runtime.GOMAXPROCS(runtime.NumCPU()) client := &http.Client{} for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() ticker := time.NewTicker(time.Microsecond * 1000) for j := 0; j < 120000; j++ { <-ticker.C hit(client) } ticker.Stop() }() } wg.Wait()}
1 回答

阿波羅的戰車
TA貢獻1862條經驗 獲得超6個贊
can't assign requested address
撥號期間的錯誤是由于用于客戶端連接的本地臨時端口用完了。端口用完的原因僅僅是因為您建立的連接太多,速度太快。當您加快連接速率時會發生什么,您開始捕捉空閑連接在它們關閉之前返回到池中。有一個代碼路徑可以在撥號期間捕獲這些新的空閑連接以更快地返回連接,但是沒有辦法每次都確定性地捕獲這些連接。
由于您僅連接到一臺主機(如評論中所述),因此您需要做的是將其設置得Transport.MaxIdleConnsPerHost
更高。您需要查看它在太多開放連接之間以及何時開始過快回收它們之間的平衡。
在客戶端上使用信號量甚至可能是有利的,以防止過多的同時連接,這將開始導致連接再次過快回收。
- 1 回答
- 0 關注
- 272 瀏覽
添加回答
舉報
0/150
提交
取消