我正在尝试在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核心的服务器。
答案 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")
}