在Go中发送多个请求时发生零星的EOF错误

问题描述:

让我首先说我是Go的新手,并欢迎任何指示/更正。在Go中发送多个请求时发生零星的EOF错误

我想写一个小的Go应用程序,它将创建一些DNS查询并将它们发送到各自的Go例程中。我从一个包含1000个URL的文件中获取URL并创建一个切片,对切片中的每个URL我为A记录进行查询,并在成功时将URL和经过的时间推送到结果通道,并且如果出现错误各自的错误通道。然后,我听取选择。

我一直在努力的是,当使用TCP时,我会收到(看似随机)的一些EOF错误,并在使用UDP时收到I/O超时错误。我想使用TCP并确保响应,我失去了为什么我会得到一个EOF错误。这也发生,如果我做1000次查询到同一URL VS 1000个不同的网址

上OSX和围棋版本工作1.6

这是我到目前为止有:

package main 

import (
    "bufio" 
    "fmt" 
    "github.com/miekg/dns" 
    "os" 
    "time" 
) 

// CHECK AND PRINT ERRORS 
func checkErr(e error) { 
    if e != nil { 
     fmt.Println("Error: %s", e) 
    } 
} 

// MAKES A SLICE OF URLS FROM TXT FILE 
func urlSlice() []string { 
    result := []string{} 
    file, err := os.Open("topsites.txt") 
    checkErr(err) 
    defer file.Close() 
    scanner := bufio.NewScanner(file) 
    for scanner.Scan() { 
     result = append(result, scanner.Text()) 
    } 
    return result 
} 

func makeQuery(target string) (string, error) { 
    server := "8.8.8.8" 
    // WILL RECIEVE EOF ERROR IF TCP - I/O TIMEOUT IF UDP 
    c := dns.Client{Net: "tcp", Timeout: time.Duration(100 * time.Second)} 
    m := dns.Msg{} 
    m.SetQuestion(dns.Fqdn(target+"."), dns.TypeA) 

    _, t, err := c.Exchange(&m, server+":53") 
    if err != nil { 
     return "", err 
    } 
    return "Url: " + target + " - - Took: " + t.String(), nil 
} 

func main() { 
    start := time.Now() 
    targets := urlSlice() 
    resch, errch := make(chan string), make(chan error) 
    for _, url := range targets { 
     go func(url string) { 
      res, err := makeQuery(url) 
      if err != nil { 
       errch <- err 
       return 
      } 
      resch <- res 
     }(url) 
    } 

    for i := 0; i < len(targets); i++ { 
     select { 
     case res := <-resch: 
      fmt.Println(res) 
     case err := <-errch: 
      fmt.Println(err) 
     } 
    } 
    elapsed := time.Since(start) 
    fmt.Println("\ntotal time elapsed: ", elapsed) 
} 

输出:

Url: facebook.com - - Took: 548.582107ms 
Url: wordpress.com - - Took: 548.805505ms 
Url: google.com.br - - Took: 541.491363ms 
Url: onclickads.net - - Took: 548.16544ms 
Url: bongacams.com - - Took: 543.28688ms 
Url: tianya.cn - - Took: 543.41525ms 
Url: blogger.com - - Took: 544.461005ms 
Url: alibaba.com - - Took: 543.53541ms 
Url: gmw.cn - - Took: 543.56093ms 
Url: pornhub.com - - Took: 664.297282ms 
Url: outbrain.com - - Took: 664.423217ms 
Url: ask.com - - Took: 671.557037ms 
EOF 
EOF 
EOF 
EOF 
EOF 
EOF 
EOF 
Url: t.co - - Took: 1.166130918s 
Url: youth.cn - - Took: 1.946658912s 
Url: apple.com - - Took: 2.763568935s 

...continued... 

total time elapsed: 23.703546858s 

想法,建议和帮助所有赞赏。谢谢!

+0

我的第一个想法是你超载的东西,也许速率限制为X并发请求会有所帮助? – Plato

+0

我以为同样的事情,似乎〜200查询将导致没有错误,但是,我仍然不确定为什么EOF和如何解决它。我希望能够生成请求,将它们推出,并等待响应。 –

这可能会感兴趣:https://idea.popcount.org/2013-11-28-how-to-resolve-a-million-domains/

根据这篇文章,天真的方法是通过多少UDP套接字可以同时打开限制 - 1000左右我将承担同样是真正的TCP套接字 - 您将耗尽文件描述符或其他资源。

笔者在文章的末尾提供了一个链接到他的平行DNS解析:https://github.com/majek/goplayground/blob/master/resolve/resolve.go

他使用去例程在同一UDP端口的所有通信的配置数量。我猜如果你想使用TCP,你将不得不使用TCP连接每个去程序(与例程数远低于1000)