The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
TheCure

爬虫: Goroutine 如何并行抓取网页

  •  
  •   TheCure · Oct 5, 2016 · 2021 views
    This topic created in 3531 days ago, the information mentioned may be changed or developed.

    在写一道公司的题目,完成一个爬虫,题目要求之一是

    要求支持多 routine 并行抓取(注意:这里并不是指简单设置 GOMAXPROCS>1)
    

    然后我就懵了,怎么样才是并行抓取?我现在只知道设置 runtime.GOMAXPROCS=N

    设置 GOMAXPROCS 是并行抓取吗,为什么?

    不是很明白出题人的意思...

    18 replies    2016-10-06 09:49:09 +08:00
    lujiajing1126
        1
    lujiajing1126  
       Oct 5, 2016 via iPhone
    就是写个任务调度框架吧😂
    magicdawn
        3
    magicdawn  
       Oct 5, 2016
    1. 这个 IO 密集型, 像 Node.js 这样单进程也可以完成的很好, Promise.map + concurrency
    2. golang: https://github.com/magicdawn/go-co/tree/master 用 task.map
    https://github.com/magicdawn/go-co/blob/master/task/map.go#L11
    magicdawn
        4
    magicdawn  
       Oct 5, 2016   ❤️ 1
    你的意思是: 可以提交很多个 routine, 然后设置 runtime.GOMAXPROCS=cpu 核心数, 但是这样是不行的, 会导致所有的 routine 都进行了 request
    题目意思可能是: 只有那么几个 concurrency routine 在跑, 一个结束了, 开始处理新的
    magicdawn
        5
    magicdawn  
       Oct 5, 2016
    前面那一种是相当于 concurrency = Infinity
    miyuki
        6
    miyuki  
       Oct 5, 2016 via Android
    http://jmoiron.net/blog/limiting-concurrency-in-go/

    楼上提到 limit concurrency 的一种方法
    janxin
        7
    janxin  
       Oct 5, 2016
    应该是想说 worker pool 吧?

    https://gobyexample.com/worker-pools
    TheCure
        8
    TheCure  
    OP
       Oct 5, 2016
    @magicdawn
    我是这么想的 我只开 8 个 routine,不停的从 channel/queue 里面读抓取的网址然后去爬它.

    但是如果我不开 GOMAXPROCS,那么每一个瞬间,都最多只有一个 routine 在跑,这只是利用异步 IO 在并发.

    但是只要我设置了 GOMAXPROCS,这些 routine 就会被调度到不同的线程->不同的 CPU,这样才是并行

    所以这里并行的关键是设置 GOMAXPROCS 对吧,那题目说的不是简单设置 GOMAXPROCS,这才是让我困惑的地方,我以为有什么其他的方法来实现并行
    reus
        9
    reus  
       Oct 5, 2016
    开 N 个 gorutine ,读 chan 里的任务,就这么简单,什么第三方库都不用。
    这么基础的东西还要来 V2EX 问?贵司心略宽啊。
    reus
        10
    reus  
       Oct 5, 2016
    @callofmx 不用管 GOMAXPROCS 的事,默认是 cpu 核数,会用上所有核心的了
    magicdawn
        11
    magicdawn  
       Oct 5, 2016
    对于有限长度的队列, 如 []int{ 1, 2, 3, 4 }
    job 为 sleep i 秒, 使用并发为 2 的时候, 耗时为 6s(2 + 4)
    https://github.com/magicdawn/go-co/blob/master/demo/map/main.go

    长度变化的队列, 工作中碰到的都是
    while true
    拿出 1000 个
    等待 1000 个以某个并发完成
    continue
    再不行, 将 async.parallelLimit 代码抄下来写一点

    啊, 这种还是 nodejs 来的简单...
    TheCure
        12
    TheCure  
    OP
       Oct 5, 2016
    @reus
    关于 GOMAXPROCS,版本不到 1.5

    我厂有国内流量最大的 Go 项目
    reus
        13
    reus  
       Oct 6, 2016
    @callofmx 百度吧?

    我的意思是,为什么你这都不会写还……
    buckethead1
        14
    buckethead1  
       Oct 6, 2016 via iPhone
    @reus lz 的意思是,并行的关键就是简单设置 GOMAXPROCS ,你怎么看出来不会写
    reus
        15
    reus  
       Oct 6, 2016
    @buckethead1
    “爬虫: Goroutine 如何并行抓取网页”
    “然后我就懵了,怎么样才是并行抓取?我现在只知道设置 runtime.GOMAXPROCS=N ”
    我现在只知道设置
    我现在只知道设置
    我现在只知道设置

    我是这样看出来不会写的。
    reus
        16
    reus  
       Oct 6, 2016
    @buckethead1 就爬虫这个例子,不论 GOMAXPROCS 是 1 还是几,都能写出并行抓取的爬虫,因为主要工作都是 net poller 做的, goroutine 并不需要多少 cpu 时间片。
    主要工作是网络 io 的场景, GOMAXPROCS 和并行没有关系。
    p2p
        17
    p2p  
       Oct 6, 2016 via iPhone
    楼主还不知道并发并行的区别
    wweir
        18
    wweir  
       Oct 6, 2016 via Android
    一年多前自己的实现是 buffer chan
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2576 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 58ms · UTC 11:02 · PVG 19:02 · LAX 04:02 · JFK 07:02
    ♥ Do have faith in what you're doing.