ホームページ >バックエンド開発 >Golang >Go で同時 HTTP リクエストを最大化するには?

Go で同時 HTTP リクエストを最大化するには?

Linda Hamilton
Linda Hamiltonオリジナル
2024-11-26 15:06:10619ブラウズ

How to Maximize Concurrent HTTP Requests in Go?

同時 HTTP リクエストを効果的に「最大化」する方法?

Go のパフォーマンスを実験するときに、大量の HTTP リクエストを同時に実行しようとすると制限に遭遇する可能性があります。 。この記事では、直面する課題を検討し、最大の同時実行性を達成するためのソリューションを提供します。

問題

最初のアプローチでは、HTTP リクエストを並行して送信するために多数のゴルーチンを起動し、それらのゴルーチンが利用されることを期待します。利用可能なすべての CPU。ただし、ファイル記述子の制限によりエラーが発生します。

解決策

これらの制限を克服するには、次のアプローチを検討してください。

  • 境界のあるファイルを使用する同時実行性を制御するセマフォ チャネル: セマフォとして機能するバッファー チャネルを実装し、同時リクエストの数。チャネル バッファ サイズを調整し、GOMAXPROCS を調整することで、システムの同時実行性を最適化できます。
  • ディスパッチャを使用してワーカー プールを利用する: リクエストがチャネルにキューイングされるワーカー プール パターンを採用します。 。ディスパッチャーがチャネルにデータを入力し、ワーカーのプールがリクエストを一度に 1 つずつ処理します。このアプローチにより、同時リクエストの最大数が確実に維持されます。
  • 専用のコンシューマ goroutine を使用して応答を処理します。 リクエスト処理のブロックを回避するには、専用の goroutine を使用してワーカーからの応答を消費します。プール。これにより、リクエストの継続的な実行が保証され、システムがより多くの同時リクエストを処理できるようになります。

最適化されたコード

これらの最適化を組み込んだコードの修正バージョンを次に示します。

package main

import (
    "fmt"
    "net/http"
    "runtime"
    "sync"
    "time"
)

var (
    reqs       int
    concurrent int
    work       chan *http.Request
    results    chan *http.Response
)

func init() {
    reqs = 1000000
    concurrent = 200
}

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    work = make(chan *http.Request, concurrent)
    results = make(chan *http.Response)
    start := time.Now()

    // Create a semaphore channel to limit concurrency
    sem := make(chan struct{}, concurrent)

    // Create a dispatcher to populate the work channel
    go func() {
        for i := 0; i < reqs; i++ {
            req, _ := http.NewRequest("GET", "http://localhost/", nil)
            work <- req
        }
        close(work) // Signal to workers that no more requests are incoming
    }()

    // Create a worker pool to process requests
    for i := 0; i < concurrent; i++ {
        go func() {
            for req := range work {
                resp, err := http.DefaultClient.Do(req)
                if err != nil {
                    fmt.Println(err)
                }
                results <- resp

                // Release semaphore token to allow another worker to proceed
                <-sem
            }
        }()
    }

    // Consume responses from worker pool
    var (
        conns int64
        totalSize int64
        wg     sync.WaitGroup
    )

    wg.Add(1)
    go func() {
        defer wg.Done()
        for {
            select {
            case resp, ok := <-results:
                if ok {
                    conns++
                    totalSize += resp.ContentLength
                    resp.Body.Close()
                } else {
                    return
                }
            }
        }
    }()

    // Block until all responses are processed
    wg.Wait()

    elapsed := time.Since(start)
    fmt.Printf("Connections:\t%d\nConcurrent:\t%d\nTotal size:\t%d bytes\nElapsed:\t%s\n", conns, concurrent, totalSize, elapsed)
}

同時実行変数を調整して結果を観察することで、システムに最適な同時実行レベル、つまり「最大化」を決定できます。同時 HTTP リクエストの処理能力。

以上がGo で同時 HTTP リクエストを最大化するには?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。