V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
TheCure
V2EX  ›  Go 编程语言

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

  •  
  •   TheCure · 2016-10-05 00:05:07 +08:00 · 1481 次点击
    这是一个创建于 3001 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

    18 条回复    2016-10-06 09:49:09 +08:00
    lujiajing1126
        1
    lujiajing1126  
       2016-10-05 00:32:16 +08:00 via iPhone
    就是写个任务调度框架吧😂
    magicdawn
        3
    magicdawn  
       2016-10-05 00:49:11 +08:00
    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  
       2016-10-05 00:55:08 +08:00   ❤️ 1
    你的意思是: 可以提交很多个 routine, 然后设置 runtime.GOMAXPROCS=cpu 核心数, 但是这样是不行的, 会导致所有的 routine 都进行了 request
    题目意思可能是: 只有那么几个 concurrency routine 在跑, 一个结束了, 开始处理新的
    magicdawn
        5
    magicdawn  
       2016-10-05 00:55:51 +08:00
    前面那一种是相当于 concurrency = Infinity
    miyuki
        6
    miyuki  
       2016-10-05 01:16:46 +08:00 via Android
    http://jmoiron.net/blog/limiting-concurrency-in-go/

    楼上提到 limit concurrency 的一种方法
    janxin
        7
    janxin  
       2016-10-05 10:39:13 +08:00
    应该是想说 worker pool 吧?

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

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

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

    所以这里并行的关键是设置 GOMAXPROCS 对吧,那题目说的不是简单设置 GOMAXPROCS,这才是让我困惑的地方,我以为有什么其他的方法来实现并行
    reus
        9
    reus  
       2016-10-05 15:59:05 +08:00
    开 N 个 gorutine ,读 chan 里的任务,就这么简单,什么第三方库都不用。
    这么基础的东西还要来 V2EX 问?贵司心略宽啊。
    reus
        10
    reus  
       2016-10-05 15:59:49 +08:00
    @callofmx 不用管 GOMAXPROCS 的事,默认是 cpu 核数,会用上所有核心的了
    magicdawn
        11
    magicdawn  
       2016-10-05 17:45:01 +08:00
    对于有限长度的队列, 如 []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
       2016-10-05 22:22:04 +08:00
    @reus
    关于 GOMAXPROCS,版本不到 1.5

    我厂有国内流量最大的 Go 项目
    reus
        13
    reus  
       2016-10-06 00:04:45 +08:00
    @callofmx 百度吧?

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

    我是这样看出来不会写的。
    reus
        16
    reus  
       2016-10-06 01:19:30 +08:00
    @buckethead1 就爬虫这个例子,不论 GOMAXPROCS 是 1 还是几,都能写出并行抓取的爬虫,因为主要工作都是 net poller 做的, goroutine 并不需要多少 cpu 时间片。
    主要工作是网络 io 的场景, GOMAXPROCS 和并行没有关系。
    p2p
        17
    p2p  
       2016-10-06 07:31:39 +08:00 via iPhone
    楼主还不知道并发并行的区别
    wweir
        18
    wweir  
       2016-10-06 09:49:09 +08:00 via Android
    一年多前自己的实现是 buffer chan
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1264 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 17:37 · PVG 01:37 · LAX 09:37 · JFK 12:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.