首页 >后端开发 >Golang >Go中如何高效最大化并发HTTP请求,同时避免系统资源耗尽?

Go中如何高效最大化并发HTTP请求,同时避免系统资源耗尽?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-11-26 01:39:09855浏览

How Can I Efficiently Maximize Concurrent HTTP Requests in Go While Avoiding System Resource Exhaustion?

Go 中并发 HTTP 请求的有效最大化

在您的代码中,您尝试并发发送 100 万个 HTTP 请求,但遇到了错误文件描述符限制。以下是如何在系统限制内用请求有效地“淹没”您的笔记本电脑:

使用基于通道的并发修​​改代码:

<br>package main <p>导入(</p><pre class="brush:php;toolbar:false">"flag"
"fmt"
"log"
"net/http"
"runtime"
"sync"
"time"

)

var (

reqs int
max  int

)

func init() {

flag.IntVar(&amp;reqs, "reqs", 1000000, "Total requests")
flag.IntVar(&amp;max, "concurrent", 200, "Maximum concurrent requests")

}

类型响应结构{

*http.Response
err error

}

func 调度程序(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
}

}

func workerPool(reqChan chan http.Request,respChan chan 响应,wg sync.WaitGroup) {

t := &amp;http.Transport{}
for i := 0; i < max; i++ {
    go worker(t, reqChan, respChan, wg)
}

}

func worker(t http.Transport, reqChan chan http.Request, respChan chan Response, wg *同步.WaitGroup) {

for req := range reqChan {
    resp, err := t.RoundTrip(req)
    r := Response{resp, err}
    respChan <- r
}
wg.Done()

}

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, max)
respChan := make(chan Response)
wg := sync.WaitGroup{}
wg.Add(max)

start := time.Now()
go dispatcher(reqChan)
go workerPool(reqChan, respChan, &amp;wg)
conns, size := consumer(respChan)
wg.Wait()
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)

}

说明:

  • 调度员:创建请求通道并将 HTTP 请求发送到
  • 工作池: 创建一个 goroutine 池,这些协程同时消费来自请求通道的请求并向响应通道发送响应。
  • 消费者: 等待响应通道上的响应并处理它们,计算连接数和总数

修改的好处:

  • 基于通道的并发:通过使用通道传递来避免文件描述符限制goroutine 之间的数据。
  • Worker池: 将 goroutine 数量限制为指定的最大并发数,防止资源耗尽。
  • 同步: 使用sync.WaitGroup 确保所有 goroutine 在退出前完成,提供干净退出。
  • 响应处理: 计算连接和响应的总大小,以提供有关资源使用情况的指标。

通过进行这些修改,您可以在系统资源的限制内使用尽可能多的 HTTP 请求有效地“淹没”您的笔记本电脑.

以上是Go中如何高效最大化并发HTTP请求,同时避免系统资源耗尽?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn