1

分散型クロール メカニズムを構築していて、サーバーに対して 1 分間に 30 件を超えるリクエストが行われないようにしたいと考えています。エンキューされた各タスクがリクエストを行います。

すべてのタスクは redis でキューに入れられ、python-rqによって提供される API を使用してキューから取り出されます。

アプローチは、送信されたリクエストの数を保持するために、毎分有効期限が切れるキーを redis に設定することです。

作業が利用可能になるたびに、送信されたリクエストが 30 未満かどうかを確認します - いいえの場合は、1 分間だけスリープします - はいの場合は、作業します


以下は私のカスタムワーカーです:

#!/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()関数はループを開始し、タスクを継続的にデキューします。

このプロセスはワーカー クラスを書き直さないと制御できないため、次善の方法はエンキュー プロセスを制御することです。最後の 1 分間に 30 を超えるタスクが追加された場合は、キューに入れません。

これが私が思いついた解決策です: https://gist.github.com/shivekkhurana/7201e5cd2ec9d51af31c8b96eeb8fcf7

フラグを渡すだけRequestAwareWorkerです。-w

于 2016-08-11T05:57:11.663 に答える