Heim > Backend-Entwicklung > Golang > Wie maximiere ich gleichzeitige HTTP-Anfragen in Go mithilfe von Goroutinen und Worker-Pools?

Wie maximiere ich gleichzeitige HTTP-Anfragen in Go mithilfe von Goroutinen und Worker-Pools?

Patricia Arquette
Freigeben: 2024-12-02 01:40:10
Original
944 Leute haben es durchsucht

How to Maximize Concurrent HTTP Requests in Go Using Goroutines and Worker Pools?

So maximieren Sie gleichzeitige HTTP-Anfragen in Go

Viele Programmiersprachen und Frameworks bieten Tools zum Senden von HTTP-Anfragen Bei einer großen Anzahl von Anfragen gleichzeitig ist es wichtig zu verstehen, wie die Parallelität maximiert werden kann, um die Leistung zu optimieren. Dieser Artikel befasst sich mit den Feinheiten der „Maximierung“ gleichzeitiger HTTP-Anfragen in Go und nutzt Goroutinen, um das volle Potenzial der Verarbeitungsfunktionen Ihres Systems freizusetzen.

Das Problem:

Betrachten wir ein Szenario, in dem wir mithilfe mehrerer Goroutinen so schnell wie möglich eine Million HTTP-Anfragen an eine bestimmte URL generieren möchten. Allerdings führte der im ersten Beitrag bereitgestellte Code zu Fehlern, da die Grenzwerte für Dateideskriptoren überschritten wurden. Dies ist ein häufiges Problem, wenn versucht wird, eine große Anzahl gleichzeitiger Anfragen zu bearbeiten.

Die Lösung:

Um die Parallelität effektiv zu maximieren, können wir die Dateideskriptorbeschränkung beheben Verwendung eines gepufferten Kanals als Semaphormechanismus innerhalb eines Worker-Pool-Modells. Hier ist eine Aufschlüsselung der Lösung:

  • Worker-Pool:

    • Erstellen Sie einen Worker-Pool, der die Anzahl der Goroutinen verwaltet, die HTTP-Anfragen verarbeiten .
    • Jede Worker-Routine verarbeitet jeweils eine Anfrage und signalisiert, wann sie bereit ist ein anderer.
  • Semaphorkanal:

    • Verwenden Sie einen gepufferten Kanal mit begrenzter Kapazität, um die Anzahl gleichzeitiger HTTP-Verbindungen zu steuern Anfragen.
    • Wenn eine Worker-Routine eine Anfrage abschließt, signalisiert sie dem Semaphorkanal, dass eine weitere Anfrage erfolgen kann verarbeitet.
  • Dispatcher:

    • Der Dispatcher generiert kontinuierlich HTTP-Anfragen und sendet diese über einen Request an den Worker-Pool Kanal.
    • Sobald Mitarbeiter verfügbar werden, ruft der Dispatcher Anforderungen aus dem Kanal ab und weist sie zu Arbeiter.
  • Verbraucher:

    • Eine separate Goroutine überwacht den Antwortkanal und erhöht die Verbindungsanzahl für jede gültige Antwort . Außerdem wird die durchschnittliche Antwortzeit berechnet.

Optimierter Code:

package main

import (
    "flag"
    "fmt"
    "log"
    "net/http"
    "runtime"
    "time"
)

var (
    reqs int
    max  int
)

func init() {
    flag.IntVar(&reqs, "reqs", 1000000, "Total requests")
    flag.IntVar(&max, "concurrent", 200, "Maximum concurrent requests")
}

type Response struct {
    *http.Response
    err error
}

// Dispatcher
func dispatcher(reqChan chan *http.Request) {
    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 Pool
func workerPool(reqChan chan *http.Request, respChan chan Response) {
    t := &amp;http.Transport{}
    for i := 0; i < max; i++ {
        go worker(t, reqChan, respChan)
    }
}

// Worker
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
func consumer(respChan chan Response) (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
}

func main() {
    flag.Parse()
    runtime.GOMAXPROCS(runtime.NumCPU())
    reqChan := make(chan *http.Request)
    respChan := make(chan Response)
    start := time.Now()
    go dispatcher(reqChan)
    go workerPool(reqChan, respChan)
    conns, size := consumer(respChan)
    took := time.Since(start)
    ns := took.Nanoseconds()
    av := ns / conns
    average, err := time.ParseDuration(fmt.Sprintf("%d", av) + "ns")
    if err != nil {
        log.Println(err)
    }
    fmt.Printf("Connections:\t%d\nConcurrent:\t%d\nTotal size:\t%d bytes\nTotal time:\t%s\nAverage time:\t%s\n", conns, max, size, took, average)
}
Nach dem Login kopieren

Dieser verbesserte Code kombiniert die zuvor besprochenen Elemente Erstellen Sie ein hocheffizientes Worker-Pool-basiertes System zum gleichzeitigen Senden einer großen Menge an HTTP-Anfragen. Durch sorgfältige Kontrolle der Anzahl gleichzeitiger Anfragen über den Semaphorkanal können wir Probleme im Zusammenhang mit Dateideskriptorbeschränkungen vermeiden und die Nutzung der Ressourcen unseres Systems maximieren.

Zusammenfassend lässt sich sagen, dass wir durch die Verwendung von Goroutinen, einem Semaphorkanal, einem Worker-Pool und einem dedizierten Verbraucher für die Verarbeitung von Antworten die gleichzeitigen HTTP-Anfragen in Go effektiv „maximieren“ können. Dieser Ansatz ermöglicht es uns, Leistungstests und Stresstests effektiv durchzuführen, unsere Systeme an ihre Grenzen zu bringen und wertvolle Erkenntnisse über ihre Leistungsfähigkeit zu gewinnen.

Das obige ist der detaillierte Inhalt vonWie maximiere ich gleichzeitige HTTP-Anfragen in Go mithilfe von Goroutinen und Worker-Pools?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage