Heim >Backend-Entwicklung >Golang >Kann mein Laptop mit Go eine Million gleichzeitige HTTP-Anfragen verarbeiten?
Kann Ihr Laptop eine Million gleichzeitige HTTP-Anfragen verarbeiten?
Stellen Sie sich vor, Sie senden 1.000.000 gleichzeitige HTTP-Anfragen an einen REST-API-Dienst und stoßen damit an die Grenzen Ihres Computers um die Parallelität zu maximieren. Für diese Aufgabe gibt es zwar Tools, aber schauen wir uns an, wie man sie in Go mithilfe von Goroutinen macht.
package main import ( "fmt" "net/http" "runtime" "time" ) func main() { runtime.GOMAXPROCS(runtime.NumCPU()) // Use all available CPU cores transport := &http.Transport{} // Create an HTTP transport for i := 0; i < 1000000; i++ { go func() { // Start a goroutine for each HTTP request req, _ := http.NewRequest("GET", "http://myapi.com", nil) req.Header.Set("User-Agent", "custom-agent") req.SetBasicAuth("xxx", "xxx") resp, err := transport.RoundTrip(req) if err != nil { panic("HTTP request failed.") } defer resp.Body.Close() if resp.StatusCode != 302 { panic("Unexpected response returned.") } location := resp.Header.Get("Location") if location == "" { panic("No location header returned.") } fmt.Println("Location Header Value:", location) }() } time.Sleep(60 * time.Second) // Sleep for 60 seconds }
Aber Moment, es gibt ein Problem!
Dieses Skript ausführen führt aufgrund von Dateideskriptorbeschränkungen zu Fehlern. Das System kann einfach nicht mit so vielen gleichzeitigen Verbindungen umgehen.
Eine verbesserte Lösung
Um diese Einschränkungen zu überwinden, müssen wir einen ausgefeilteren Ansatz verwenden.
Verwendung eines Dispatcher- und Worker-Pools
Diese Lösung beinhaltet die Erstellung einer Dispatcher-Goroutine schiebt Anfragen auf einen Kanal. Ein Worker-Pool von Goroutinen ruft Anfragen aus dem Kanal ab, verarbeitet sie und sendet sie an einen Antwortkanal. Eine Verbraucher-Goroutine verarbeitet dann die Antworten.
// Dispatcher function func dispatcher(reqChan chan *http.Request, reqs int) { defer close(reqChan) for i := 0; i < reqs; i++ { req, err := http.NewRequest("GET", "http://localhost/", nil) if err != nil { log.Println(err) } reqChan <- req } } // Worker function func worker(t *http.Transport, reqChan chan *http.Request, respChan chan Response) { for req := range reqChan { resp, err := t.RoundTrip(req) r := Response{resp, err} respChan <- r } } // Consumer function func consumer(respChan chan Response, reqs int) (int64, int64) { var ( conns int64 size int64 ) for conns < int64(reqs) { select { case r, ok := <-respChan: if ok { if r.err != nil { log.Println(r.err) } else { size += r.ContentLength if err := r.Body.Close(); err != nil { log.Println(r.err) } } conns++ } } } return conns, size }
Ergebnisse
Das Ausführen dieses verbesserten Skripts generiert beeindruckende Ergebnisse, wie zum Beispiel:
Verbindungen: 1000000
Gleichzeitig: 200
Gesamtgröße: 15000000 Bytes
Gesamtzeit: 38m20.3012317s
Durchschnittszeit: 2.280131ms
Optimierung für Leistung
Das Optimieren der Anzahl gleichzeitiger Anfragen und der Gesamtanzahl der Anfragen hilft Ihnen jedoch beim Pushen Ermitteln Sie die Grenzen Ihres Systems und testen Sie dessen Leistungsfähigkeit. Denken Sie daran, dass dies ein extremer Test ist und schnell Systemressourcen verbrauchen kann.
Das obige ist der detaillierte Inhalt vonKann mein Laptop mit Go eine Million gleichzeitige HTTP-Anfragen verarbeiten?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!