我有这个测试程序,它将并行获取url,但是当我将并行数增加到大约1040时,我开始出现lookup www.httpbin.org: no such host错误。

经过一番Google搜索后,我发现其他人说不关闭响应会导致问题,但是我确实使用res.Body.Close()关闭了它。

这是什么问题非常感谢。

package main

import (
    "fmt"
    "net/http"
    "io/ioutil"
)

func get(url string) ([]byte, error) {

    client := &http.Client{}
    req, _ := http.NewRequest("GET", url, nil)

    res, err := client.Do(req)

    if err != nil {
        fmt.Println(err)
        return nil, err
    }

    bytes, read_err := ioutil.ReadAll(res.Body)
    res.Body.Close()

    fmt.Println(bytes)

    return bytes, read_err
}

func main() {
    for i := 0; i < 1040; i++ {
        go get(fmt.Sprintf("http://www.httpbin.org/get?a=%d", i))
    }
}

最佳答案

那是因为您的代码中最多可能有1040个并发调用,因此您很可能处于1040主体打开且尚未关闭的状态。

您需要限制使用的goroutine的数量。

这是一个最大可能限制为100个并发调用的解决方案:

func getThemAll() {
    nbConcurrentGet := 100
    urls :=  make(chan string, nbConcurrentGet)
    for i := 0; i < nbConcurrentGet; i++ {
        go func (){
            for url := range urls {
                get(url)
            }
        }()
    }
    for i:=0; i<1040; i++ {
        urls <- fmt.Sprintf("http://www.httpbin.org/get?a=%d", i)
    }
}

如果在程序的主函数中调用此函数,则它可能在所有任务完成之前停止。您可以使用sync.WaitGroup来防止它:
func main() {
    nbConcurrentGet := 100
    urls :=  make(chan string, nbConcurrentGet)
    var wg sync.WaitGroup
    for i := 0; i < nbConcurrentGet; i++ {
        go func (){
            for url := range urls {
                get(url)
                wg.Done()
            }
        }()
    }
    for i:=0; i<1040; i++ {
        wg.Add(1)
        urls <- fmt.Sprintf("http://www.httpbin.org/get?a=%d", i)
    }
    wg.Wait()
    fmt.Println("Finished")
}

10-07 17:13