Maison >développement back-end >Golang >Pourquoi net/http ne prend-il pas en compte les durées d'expiration supérieures à 30 secondes ?

Pourquoi net/http ne prend-il pas en compte les durées d'expiration supérieures à 30 secondes ?

WBOY
WBOYavant
2024-02-11 17:30:08834parcourir

为什么 net/http 不考虑超过 30 秒的超时持续时间?

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.

Contenu de la question

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)

Solution

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer