У меня есть простая программа ниже, которая представляет собой простой HTTP-клиент и сервер.Я проверяю, работает ли MaxConnsPerHost
в http.Transport
, введенном в Go 1.11 , как рекламируется.Однако, когда я запускаю код более 10-30 минут, количество УСТАНОВЛЕННЫХ соединений медленно превышает установленное значение MaxConnsPerHost
.Я что-то не так делаю?
package main
import (
"io/ioutil"
"log"
"net"
"net/http"
"time"
)
func main() {
// Server
//
go func() {
if err := http.ListenAndServe(":8081", http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hi"))
},
)); err != nil {
log.Fatal(err)
}
}()
// Client settings
//
c := &http.Client{
Timeout: 30 * time.Second,
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
MaxConnsPerHost: 50,
},
}
// Worker loop
//
threads := 500
for i := 0; i < threads; i++ {
go func() {
for {
req, err := http.NewRequest("GET", "http://localhost:8081", nil)
if err != nil {
log.Fatal(err)
}
res, err := c.Do(req)
if err != nil {
log.Fatal(err)
}
if _, err := ioutil.ReadAll(res.Body); err != nil {
log.Fatal(err)
}
res.Body.Close()
}
}()
}
var done chan bool
<-done
log.Println("Done")
}
После длительного выполнения этого УСТАНОВЛЕННЫЕ соединения, о которых сообщают netstat
, уже превышают 50.
PS У нас проблема в одномнаших услуг, которые ужасно пропускают УСТАНОВЛЕННЫЕ соединения, даже если мы правильно закрываем тело ответа.В настоящее время он построен с использованием Go 1.10 , и я надеялся, что Go 1.11 MaxConnsPerHost
будет решением, но, похоже, он также трескается при большой нагрузке.