Golang"Connection reset"&"EOF"問題
【場景】
在呼叫微信生成小程式二維碼生成介面的時候,使用golang預設的http client傳送請求。
程式碼如下:
req, err := http.NewRequest(method, url, body) iferr !=nil{ return nil, err } resp, err := http.DefaultClient.Do(req) if err !=nil{ return nil, err } defer resp.Body.Close() b, err := ioutil.ReadAll(resp.Body) if err !=nil{ return nil, err }
當併發量大的時候就會出現大量的錯誤
ERROR 10108 socket.cpp:985 0x7fffe81426e0 recvmsg(62, 1): (104, "Connection reset by peer") WARN 10108 server.cpp:4670x7fffe80abd60-2 Unexpected SocketException
【原因】
在解決問題之前需要了解關於go是如何實現connection的一些背景小知識:有兩個協程,一個用於讀,一個用於寫(就是readLoop和writeLoop)。在大多數情況下,readLoop會檢測socket是否關閉,並適時關閉connection。如果一個新請求在readLoop檢測到關閉之前就到來了,那麼就會產生EOF錯誤並中斷執行,而不是去關閉前一個請求。
我執行時建立一個新的連線併發送keep-alive,伺服器收到後將我的keep-alive發回並立即關閉了連線。當這段程式執行後退出,再次執行時伺服器已經關閉了連線,而我的客戶端卻仍在重用之前建立的連線,所以提示連線被重置;如果我不退出程式而使用for迴圈多次傳送時,舊連線未及時關閉,新連線卻到來,EOF的錯誤也就產生了。
【解決】
req.Close = true
它會阻止連線被重用,可以有效的防止這個問題,也就是Http的短連線。