没有外部依赖关系的高性能网络蜘蛛

时间:2015-12-17 16:16:41

标签: performance go

我正在尝试在Golang中编写我的第一个网络蜘蛛。它的任务是从提供的数据库查询中抓取域(并检查它们的html)。这个想法是没有第三方依赖(例如,msg队列),或者尽可能少,但它必须具有足够的性能,每天可以抓取500万个域。我每个月都需要检查大约1.5亿个域名。

下面的基本版本 - 它在“无限循环”中运行,理论上爬行过程将是无穷无尽的。

func crawl(n time.Duration) {
    var wg sync.WaitGroup
    runtime.GOMAXPROCS(runtime.NumCPU())

    for _ = range time.Tick(n * time.Second) {
        wg.Add(1)

        go func() {
            defer wg.Done()

            // do the expensive work here - query db, crawl domain, inspect html
        }()
    }
    wg.Wait()
}

func main() {
    go crawl(1)

    select{}
}

此时在4个CPU内核上运行此代码意味着它可以在24小时内((60 * 60 * 24)* 4)执行最大345600次请求,并且给定的阈值为1秒。至少这是我的理解:-)如果我的想法是正确的,那么我需要提出解决方案,以满足日常需求快14倍。

我很感激您就使爬虫更快的建议,但没有解决复杂的堆栈设置或购买具有更多CPU核心的服务器。

1 个答案:

答案 0 :(得分:2)

为什么要有计时组件?

只需创建一个您向其提供网址的频道,然后生成循环播放该频道的N个goroutines并开展工作。

然后调整N的值直到你的CPU /内存上限〜利用率达到90%(以适应站点响应时间的波动)

类似这样的事情(on Play):

package main

import "fmt"
import "sync"

var numWorkers = 10

func crawler(urls chan string, wg *sync.WaitGroup) {
    defer wg.Done()
    for u := range urls {
        fmt.Println(u)
    }
}
func main() {
    ch := make(chan string)
    var wg sync.WaitGroup
    for i := 0; i < numWorkers; i++ {
        wg.Add(1)
        go crawler(ch, &wg)
    }
    ch <- "http://ibm.com"
    ch <- "http://google.com"
    close(ch)
    wg.Wait()
    fmt.Println("All Done")
}