Comment le multithreading affecte-t-il la connexion http keep-alive?
var (
httpClient *http.Client
)
const (
MaxIdleConnections int = 20
RequestTimeout int = 5
)
// init HTTPClient
func init() {
client := &http.Client{
Transport: &http.Transport{
MaxIdleConnsPerHost: MaxIdleConnections,
},
Timeout: time.Duration(RequestTimeout) * time.Second,
}
return client
}
func makeRequest() {
var endPoint string = "https://localhost:8080/doSomething"
req, err := http.NewRequest("GET", ....)
response, err := httpClient.Do(req)
if err != nil && response == nil {
log.Fatalf("Error sending request to API endpoint. %+v", err)
} else {
// Close the connection to reuse it
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatalf("Couldn't parse response body. %+v", err)
}
log.Println("Response Body:", string(body))
}
}
J'ai le code suivant dans Go. Go utilise une connexion http-keep-alive. Ainsi, d'après ce que je comprends, httpClient.Do(req)ne créera pas de nouvelle connexion, car golang utilise les connexions persistantes par défaut.
D'après ce que je comprends, la connexion persistante HTTP fait une demande à la fois, c'est-à-dire que la deuxième demande ne peut être effectuée qu'après la première réponse. Cependant, si plusieurs threads appellent,
makeRequest()que se passera-t-il?httpClient.Do(req)Envoie- t-il une autre demande avant même que la précédente n'obtienne une réponse?Je suppose que le serveur expire toute connexion persistante établie par le client. Si le serveur devait expirer, la prochaine fois qu'il
httpClient.Do(req)sera appelé, établirait-il une nouvelle connexion?
Réponses
an http.Clienta un Transportauquel il délègue de nombreux détails de bas niveau pour faire une demande. Vous pouvez changer à peu près n'importe quoi en donnant à votre client un transport personnalisé. Le reste de cette réponse supposera en grande partie que vous utilisez http.DefaultClientou du moins un client avec http.DefaultTransport.
Lors d'une nouvelle demande, si une connexion inactive au serveur approprié est disponible, le transport l'utilisera.
Si aucune connexion inactive n'est disponible (parce qu'il n'y en a jamais eu, ou parce que d'autres goroutines les utilisent toutes, ou parce que le serveur a fermé la connexion, ou qu'il y a eu une autre erreur), le transport envisagera d'établir une nouvelle connexion, limitée par MaxConnsPerHost( par défaut: pas de limite). Si MaxConnsPerHostserait dépassé, la demande sera bloquée jusqu'à ce qu'une demande existante se termine et qu'une connexion devienne disponible. Sinon, une nouvelle connexion sera établie pour cette demande.
À la fin d'une demande, le client mettra en cache la connexion pour une utilisation ultérieure (limitée par MaxIdleConnset MaxIdleConnsPerHost; DefaultTransporta une limite de 100 connexions inactives globalement, et aucune limite par hôte).
Les connexions inactives seront fermées après IdleConnTimeoutsi elles ne sont pas utilisées pour faire une demande; car DefaultTransportla limite est de 90 secondes.
Tout cela signifie que par défaut, Go établira suffisamment de connexions pour satisfaire le parallélisme (jusqu'à certaines limites que vous pouvez ajuster), mais il réutilisera également les connexions persistantes autant que possible en conservant un pool de connexions inactives pendant une certaine durée de temps.
Cela n'affectera pas la connexion http keep-alive, basée sur votre code, vous utilisez httpClient global, cela ne créera pas de nouvelle connexion si elle est appelée dans plusieurs threads comme vous vous y attendiez response.Body. Si le fourni response.Bodyest un io.Closer, il sera fermé après la demande.