Maison >développement back-end >Golang >Pourquoi net/http ne prend-il pas en compte les durées d'expiration supérieures à 30 secondes ?
L'éditeur PHP Banana a découvert en discutant de la durée d'expiration dans les requêtes réseau, pourquoi net/http n'a-t-il pas pris en compte une limite de délai d'attente supérieure à 30 secondes dans la conception ? Le délai d'attente signifie qu'après l'envoi d'une demande, si aucune réponse n'est reçue dans le délai spécifié, la demande sera considérée comme ayant échoué. Dans les requêtes réseau, le réglage du délai d'attente est très important. S'il est trop court, la requête peut échouer, et s'il est trop long, des ressources seront gaspillées. Grâce à l'analyse, la raison principale est que l'équilibre entre les performances et les ressources, ainsi que l'incertitude de l'environnement réseau, ont été pris en compte lors de la conception. Ensuite, nous répondrons à cette question en détail.
Utilisez Golang 1.20.1.
Dans les packages net/http et context de Golang, je ne peux pas définir un délai d'attente supérieur à trente secondes. Définir un délai d'attente plus court fonctionne bien, comme
Code :
log.infof("elasticsearch url is %v", elasticsearchurl) client := &http.client{timeout: time.duration(time.second * 60)} req, err := http.newrequest("get", listbackupsurl, nil) if err != nil { internalerror(w, fmt.sprintf("error creating request: %v", err)) return } req.setbasicauth(username, password) resp, err := client.do(req) if err != nil { // handle error internalerror(w, fmt.sprintf("error accessing elasticsearch: %v", err)) return }
Journal :
i0503 23:01:55.973821 1 somecode.go:85] url is http://elasticsearch.example.ingest:9200 e0503 23:02:25.976345 1 caller_handler.go:63] 500 internal server error: error accessing elasticsearch: get "http://elasticsearch.example.ingest:9200/_cat/snapshots/object-store-repo?v&s=id": dial tcp 1.2.3.4:9200: i/o timeout
Le délai d'attente est de trente secondes et non de soixante secondes.
Si j'utilise http.newrequestwithcontext(...)
et que j'utilise un contexte avec le même délai d'attente, j'obtiens le même comportement :
Code :
log.infof("elasticsearch url is %v", elasticsearchurl) ctx, cancel := context.withtimeout(context.background(), time.duration(time.second * 60)) defer cancel() req, err := http.newrequestwithcontext(ctx, "get", listbackupsurl, nil) if err != nil { internalerror(w, fmt.sprintf("error creating request: %v", err)) return } req.setbasicauth(username, password) resp, err := client.do(req) if err != nil { // handle error internalerror(w, fmt.sprintf("error accessing elasticsearch: %v", err)) return }
Journal :
i0503 23:31:10.941169 1 somecode.go:85] elasticsearch url is http://elasticsearch.example.ingest:9200 e0503 23:31:40.941642 1 caller_handler.go:63] 500 internal server error: error accessing elasticsearch: get "http://elasticsearch.example.ingest:9200/_cat/snapshots/object-store-repo?v&s=id": dial tcp 1.2.3.4:9200: i/o timeout
Cependant, si je modifie le délai d'attente à trois secondes (time.duration(time.second * 3))
) dans l'une ou l'autre méthode, cela fonctionne comme prévu :
I0503 23:44:17.622121 1 somecode.go:85] Elasticsearch URL is http://elasticsearch.example.ingest:9200 E0503 23:44:20.624795 1 caller_handler.go:63] 500 Internal Server Error: error accessing elasticsearch: Get "http://elasticsearch.example.ingest:9200/_cat/snapshots/object-store-repo?v&s=id": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
J'isolerais le problème pour éliminer les possibilités et aider à déterminer la cause du problème. Si possible, utilisez un petit morceau de code afin de ne pouvoir traiter que ce que vous voulez.
Pour tester votre infrastructure, httpstat vous aidera à simuler des timeouts à distance. Exemple :
func main() { client := &http.Client{Timeout: time.Duration(time.Second * 200)} req, err := http.NewRequest("GET", "https://www.php.cn/link/1a59ef90d1ea801448e1567d0896a99f/504?sleep=120000", nil) if err != nil { log.Fatal(err) return } resp, err := client.Do(req) if err != nil { log.Fatal(err) return } fmt.Println(resp) }
Si vous recevez un délai d'attente dial tcp ip:port: i/o timeout
à ce moment-là, vous devez alors vérifier votre système d'exploitation et votre pare-feu. Quels que soient les délais d'attente que vous avez définis, ils doivent remplacer les paramètres par défaut du système d'exploitation. Si vous obtenez des délais d'attente de cette manière, c'est probablement un pare-feu (local ou distant) qui en est la cause.
Alternativement, es peut expirer si vous parvenez à vous connecter en externe, bien que, selon la documentation, vous devriez vous attendre à un message d'erreur directement de es . Vous pouvez définir le délai d'attente pour es directement dans l'url et le tester.
J'espère que cela vous aidera.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!