1

RapGenius 发布了这篇文章,介绍了他们如何使用 Ruby 库 Typhoeus 通过并行化 Heroku 上的工作人员测功机上的抓取任务来检查指向它们的所有 170k url。

我一直在从事一个涉及抓取(获取源代码)150 万个 URL 的项目,并且我一直在努力加快速度。为了更适应 Python,我设法使用 redis 和 python 多处理创建了一个在我的桌面上并行运行的刮板。我感到困惑的是如何修改它以在 Heroku 上工作。

这是我的程序现在的设计方式:

1) 初始化脚本运行,将所有 URL 提前存储在 Redis 队列中

2) 运行一个脚本 run_workers.py,它启动所有进程,如下所示:

workers = []
q = get_redis_queue(name)
for i in xrange(num_workers):
    p = multiprocessing.Process(target=worker.scraper_worker, args=(i, q))
    p.start()
    workers.append(p)

for w in workers:
    w.join()

3)worker.py中的workers执行这样的抓取任务:

def scraper_worker(worker_id, queue):
    #consumes URL from redis queue, visits using python requests
    #stores result into MySQL
  • 我当前的程序结构可以直接移植到 Heroku 上吗?我会在 Procfile 中放什么?我的第一个猜测是

    scrape: python init_scrape.py
    

    init_scrape.py 首先初始化队列,然后运行工人。但我没有实际在云上分发 python 任务的经验,我想避免代价高昂的错误。

  • 在本地运行它,我发现将结果直接存储到数据库中(每个 URL 有 150 万行,以及缓存将去哪里的空白空间),每个 UPDATE 查询都很慢(需要几分钟)。将结果存储在临时表中,然后合并两个表是否更好?

  • 我不应该使用哪些技术?例如,我看到 Celery 和 Twisted 都被提及为适合此类事情的候选人。我对任何一个都不熟悉,但我已经将两者都视为外围谷歌搜索中的建议替代方案。

4

1 回答 1

2

首先,如果这个“项目”是短暂的,或者通常不会在生产中运行,我建议你在真正看到需要之前不要开始研究“更好的技术”。如果你只打算运行 3 次,那是浪费时间。

对于您的最后一个问题:Twisted 是一个异步框架,很像“节点”,它将允许在单台机器上实现更高的并发因子。Celery 是分布式任务,很酷,两者都值得学习,适合你。(除非规模很大,否则我不会打扰 Twisted )。而不是 celery,对于您的简单情况,您可能会考虑“RedisQ”,这是一个 Python 模块,它在 Redis 中执行类似的操作(并且具有非常简洁的文档)。

对于您的 MySQL 问题:不应该是这样。150 万行的表并不小,但插入和更新绝对不会花费几分钟。通过关闭您拥有的任何键、索引和主键来开始调查。

对于您的 Heroku 架构问题:您将有 2 种类型的进程:一个“网络”进程(这是您的init_scrape.py),您将拥有 1 个heroku ps:scale web=1( 'd like,这会增加你的规模)。

您的 procfile 将类似于:

web: python init_scrape.py
worker: python worker.py

请注意,如果您想与您的 init_scrape.py 进程通信,您必须在 Procfile 中将其命名为“web”。另请注意,在这种情况下,您必须将 TCP 侦听器(基本上:启动一个简单的 http 服务器)绑定到 port os.environ['PORT']。只有“web”进程从 Heroku 的“外部”获取路由 HTTP 请求。

另外,请注意,您的所有进程都不应真正“退出”(否则 Heroku 将简单地重新旋转它们)。当他们无事可做时,他们应该简单地等待/轮询任务。然后,您可以使用 增加或减少工作人员的数量heroku ps:scale

关于您所写的内容,这里的主要问题是您的主人不会启动工人。工作进程将处于完全不同的测功机中。工作人员将简单地初始化 redis 队列(正如您所提到的),并可能启动一个简单的 http 服务器进行通信,然后坐视不管。

需要向工作人员传递 redis 队列名称,并且每个工作人员都将处于自己的 dyno 中。

祝你好运!

于 2014-02-05T10:10:49.427 回答