1

我正在构建一个分布式爬虫机制,并希望确保一分钟内向服务器发出的请求不超过 30 个。每个入队的任务都会发出一个请求。

所有任务都在 redis 中入队,并使用python-rq提供的 api 出队。

方法是在redis中设置一个每分钟过期的key,用来保存发送的请求数。

每次有工作可用时,检查发送的请求是否 < 30 - 如果没有,则只需休眠一分钟 - 如果是,则工作


以下是我的自定义工作者:

#!/usr/bin/env python
import sys
import time
from rq import Connection, Worker
from redis import Redis

redis = Redis()

def should_i_work():
    r = redis.get('app:requests_sent_in_last_minute')
    if r == None:
        redis.setex('app:requests_sent_in_last_minute', 1, 60)
    return  r == None or int(r) < 30

def increment_requests():
    r = int(redis.get('app:requests_sent_in_last_minute'))
    redis.set('app:requests_sent_in_last_minute', r+1)

def main(qs):
    with Connection():
        try:
            while True:
                if should_i_work():
                    increment_requests()
                    w = Worker(qs)
                    w.work()
                else:
                    time.sleep(60)
        except KeyboardInterrupt:
            pass

if __name__ == '__main__':
    qs = sys.argv[1:] or ['default']
    main(qs)

这似乎不起作用,因为尽管工作人员以通常的速度执行任务,而且设置的键的值也不会更新超过 3。

我有一种强烈的感觉,我的思维过程是有缺陷的。我在这里做错了什么?

谢谢

4

1 回答 1

0

在查看worker.py源代码后,我的思维过程中的错误很明显。该w.work()函数启动一个循环并不断地使任务出队。

因为这个过程是无法控制的,不重写worker类,下一个最好的办法就是控制入队过程。如果在最后一分钟添加了超过 30 个任务,则不要排队。

这是我想出的解决方案:https ://gist.github.com/shivekkhurana/7201e5cd2ec9d51af31c8b96eeb8fcf7

只需传入flag即可RequestAwareWorker-w

于 2016-08-11T05:57:11.663 回答