I'm just having a bit of a go with golang, I built a little load tester to play with concurrency stuff in go which looks cool.
My tester app starts a bunch of threads and each thread does a bunch of http requests as fast as possible to some endpoint. After a few seconds I get the following error:
connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted.
I've come across this problem before in dotnet, its to do with running out of ports allocated by windows (https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/). HttpClient (dotnet) solves this by reusing ports between requests.
Does go have a similar way to reuse the OS allocated port between http requests?
Code to reproduce:
package main
import (
"fmt"
"io/ioutil"
"net/http"
"time"
)
const numberOfCallsPerThread = 100
const numberOfThreads = 128
func main() {
var chans [numberOfThreads]chan time.Duration
for i := range chans {
chans[i] = make(chan time.Duration, 5) //only let one thread get 5 calls ahead
go callGet(numberOfCallsPerThread, chans[i])
}
var durations [numberOfCallsPerThread * numberOfThreads]time.Duration
for i := 0; i < numberOfCallsPerThread; i++ {
for j := range chans {
durations[(i*numberOfThreads)+j] = <-chans[j]
}
}
}
func callGet(numberOfTimes int, responseTime chan time.Duration) {
for i := 0; i < numberOfTimes; i++ {
start := time.Now()
response, httpError := http.Get("http://google.com")
if httpError != nil {
close(responseTime)
panic(httpError)
}
responseBody, _ := ioutil.ReadAll(response.Body)
response.Body.Close()
elapsed := time.Since(start)
fmt.Println(len(responseBody), " in ", elapsed)
responseTime <- elapsed
}
}
(sorry no playground link as it doesn't support http things)
NOTE: This issue only occurs on windows (osx is not reproducable)