首頁 >後端開發 >Golang >我的筆記型電腦可以使用 Go 處理一百萬個並發 HTTP 請求嗎?

我的筆記型電腦可以使用 Go 處理一百萬個並發 HTTP 請求嗎?

Linda Hamilton
Linda Hamilton原創
2024-12-01 17:01:081014瀏覽

Can My Laptop Handle One Million Concurrent HTTP Requests Using Go?

您的筆記型電腦可以處理一百萬個並發 HTTP 請求嗎?

想像一下,向 REST API 服務發送 1,000,000 個並發 HTTP 請求,從而突破電腦的限制以最大化並發性。雖然存在用於此任務的工具,但讓我們深入了解如何在 Go 中使用 goroutine 來完成此任務。

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
}

但是等等,有一個問題!

執行此腳本由於檔案描述符限製而導致錯誤。系統根本無法處理如此多的並發連接。

改進的解決方案

要克服這些限制,我們需要使用更複雜的方法。

使用排程器和工作池

此解決方案涉及建立一個將請求推送到通道的排程器 goroutine。 Goroutine 的工作池從通道中提取請求,處理它們,然後將它們發送到回應通道。然後消費者 Goroutine 處理回應。

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

結果

執行這個改進的腳本會產生令人印象深刻的結果,例如:

;

連線: 1000000

併發:200

總大小:15000000位元組

總時間:38m20.3012317s


2.280131ms

最佳化效能

但是,調整並發請求數和總請求數將有助於您推送您的系統的限制並對其功能進行壓力測試。請記住,這是一項極端測試,會快速消耗系統資源。

以上是我的筆記型電腦可以使用 Go 處理一百萬個並發 HTTP 請求嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn