Heim  >  Artikel  >  Backend-Entwicklung  >  Warum berücksichtigt net/http keine Zeitüberschreitungen von mehr als 30 Sekunden?

Warum berücksichtigt net/http keine Zeitüberschreitungen von mehr als 30 Sekunden?

WBOY
WBOYnach vorne
2024-02-11 17:30:08775Durchsuche

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

PHP-Redakteur Banana hat bei der Erörterung der Timeout-Dauer in Netzwerkanfragen herausgefunden, warum net/http im Design kein Timeout-Limit von mehr als 30 Sekunden berücksichtigt hat? Der Timeout-Zeitraum bedeutet, dass nach dem Senden einer Anfrage die Anfrage als fehlgeschlagen gilt, wenn innerhalb der angegebenen Zeit keine Antwort eingeht. Bei Netzwerkanfragen ist die Einstellung des Timeouts sehr wichtig. Wenn es zu kurz ist, kann die Anfrage fehlschlagen, und wenn es zu lang ist, werden Ressourcen verschwendet. Der Hauptgrund für die Analyse besteht darin, dass beim Entwurf das Gleichgewicht zwischen Leistung und Ressourcen sowie die Unsicherheit der Netzwerkumgebung berücksichtigt wurden. Als nächstes werden wir diese Frage im Detail beantworten.

Frageninhalt

Verwenden Sie Golang 1.20.1.

In den Net/http- und Kontextpaketen von Golang kann ich kein Timeout festlegen, das länger als dreißig Sekunden ist. Das Festlegen eines kürzeren Timeouts funktioniert gut, z. B.

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
    }

Protokoll:

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

Das Timeout beträgt dreißig Sekunden, nicht sechzig Sekunden.

Wenn ich http.newrequestwithcontext(...) verwende und einen Kontext mit demselben Timeout-Satz verwende, erhalte ich das gleiche Verhalten:

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
    }

Protokoll:

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

Wenn ich jedoch bei beiden Methoden das Timeout auf drei Sekunden (time.duration(time.second * 3))) ändere, funktioniert es wie erwartet:

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)

Lösung

Ich würde das Problem isolieren, um Möglichkeiten auszuschließen, die dabei helfen, die Ursache des Problems einzugrenzen. Verwenden Sie nach Möglichkeit einen kleinen Codeausschnitt, damit Sie nur das verarbeiten können, was Sie möchten.

Um Ihre Infrastruktur zu testen, hilft Ihnen Hystat dabei, Remote-Timeouts zu simulieren. Beispiel:

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)
}

Wenn Sie zu diesem Zeitpunkt eine dial tcp ip:port: i/o timeoutZeitüberschreitung erhalten, müssen Sie Ihr Betriebssystem und Ihre Firewall überprüfen. Unabhängig davon, welche Zeitüberschreitungen Sie in go festlegen, sollten die Standardeinstellungen des Betriebssystems überschrieben werden. Wenn Sie auf diese Weise Zeitüberschreitungen erhalten, ist dies wahrscheinlich auf eine Firewall (lokal oder remote) zurückzuführen.

Alternativ kann es zu einer Zeitüberschreitung kommen, wenn Sie eine externe Verbindung herstellen können. Laut Dokumentation sollten Sie jedoch mit einer Fehlermeldung direkt von es rechnen. Sie können das Timeout für es direkt in der URL festlegen und testen.

Ich hoffe, das hilft.

Das obige ist der detaillierte Inhalt vonWarum berücksichtigt net/http keine Zeitüberschreitungen von mehr als 30 Sekunden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen