一个并发查询 A 记录的工具导致 cpu 大量占用的问题

yulinsec · · 664 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

如题,最近在写一个高并发查询大量域名A记录的工具,使用的是github.com/miekg/dns这个包,基本思路是给定一个域名列表和dns服务器列表,将dns服务器做成循环链表,将dns服务器与域名一一对应存入map然后交给worker解析,当域名大约在10万以上的,goroutine在2000左右就会出现大量占用cpu的情况。请问各位有没有写过类似程序的经验,请教一下应该是哪里出问题了。代码如下。用pprof查看显示是 lookup占用了大量cpu。也测试过和并发map应该没关系。 ``` package main import ( "bufio" "container/ring" "errors" "fmt" "github.com/miekg/dns" cmap "github.com/orcaman/concurrent-map" "log" "os" "time" ) var ( client = new(dns.Client) ) var ( signalsnum = 0 ) func init() { client.Timeout = time.Duration(500*time.Millisecond) } func lookupA(fqdn, serverAddr string) ([]string, error) { var ips []string m1 := new(dns.Msg) m1.Id = dns.Id() m1.RecursionDesired = true m1.Question = make([]dns.Question, 1) m1.Question[0] = dns.Question{dns.Fqdn(fqdn), dns.TypeA, dns.ClassINET} in, _, err := client.Exchange(m1, serverAddr+":53") if err != nil { return ips,err } if len(in.Answer) < 1 { return ips, errors.New("no answer") } for _, answer := range in.Answer { if a, ok := answer.(*dns.A); ok { ips = append(ips, a.A.String()) return ips,nil } } return ips, nil } func worker(dnsmapkey chan string,gather chan string,m cmap.ConcurrentMap) { for { select { case name := <-dnsmapkey: dnskey, _ := m.Get(name) dnserver := fmt.Sprintf("%s", dnskey) //fmt.Println(name,"========",dnserver) result, err := lookupA(name+".lenovo.com", dnserver) if err != nil { //有err就认为解析失败,加入失败队列。 } if len(result) > 0 { signalsnum++ gather <- name + "===" + result[0] + "===" + dnserver } m.Remove(name) } } } func filelines(name string) int { line := 0 file,err := os.Open(name) if err != nil{ log.Fatal(err) } defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan(){ line++ } return line } var ( hashMapSize = 3000 ) func main() { //profile.Start().Stop() r := ring.New(filelines("../dns.txt")) //var results []string dnsmapkey := make(chan string, hashMapSize) m := cmap.New() gather := make(chan string) fh, err := os.Open("./hostname.txt") if err != nil { panic(err) } defer fh.Close() dnsfile, err := os.Open("../dns.txt") if err != nil { panic(err) } defer dnsfile.Close() namescanner := bufio.NewScanner(fh) dnscanner := bufio.NewScanner(dnsfile) for dnscanner.Scan(){ r.Value = dnscanner.Text() r = r.Next() } for i := 0; i < hashMapSize; i++ { go worker(dnsmapkey,gather,m) } for namescanner.Scan() { name := namescanner.Text() dns := fmt.Sprintf("%s",r.Value) m.Set(name,dns) dnsmapkey <- name r = r.Next() } close(dnsmapkey) for i:=0;i<signalsnum;i++{ fmt.Println(<-gather) } } ```

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

664 次点击  
加入收藏 微博
2 回复  |  直到 2020-02-23 17:44:35
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传