查找[主机]:Go中没有这样的主机错误

时间:2012-10-18 10:43:39

标签: linux http networking concurrency go

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

在谷歌之后,我发现其他人说没有关闭响应会导致问题,但我确实用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))
    }
}

2 个答案:

答案 0 :(得分:11)

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

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

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

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

如果您在程序的main函数中调用它,它可能会在所有任务完成之前停止。您可以使用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")
}

答案 1 :(得分:11)

从技术上讲,您的过程受限(通过内核)到大约1000个打开的文件描述符。根据具体情况,您可能需要增加此数字。

在你的shell运行中(注意最后一行):

$ ulimit -a
-t: cpu time (seconds)         unlimited
-f: file size (blocks)         unlimited
-d: data seg size (kbytes)     unlimited
-s: stack size (kbytes)        8192
-c: core file size (blocks)    0
-v: address space (kb)         unlimited
-l: locked-in-memory size (kb) unlimited
-u: processes                  709
-n: file descriptors           2560

增加(临时):

$ ulimit -n 5000
(no output)

然后验证fd限制:

$ ulimit -n
5000