1

に移行したいのですがndb、非同期urlfetch タスクレットを使用するかどうか迷っています。ドキュメントがやや貧弱であるため、それがどのように機能するかを完全に理解しているかどうかはわかりませんが、この特定のユースケースでは非常に有望なようです.

現在、私はこのように非同期を使用urlfetchしています。実際のスレッド化や並列コードにはほど遠いですが、シーケンシャル リクエストと比較すると、パフォーマンスは大幅に向上しています。

def http_get(url):
    rpc = urlfetch.create_rpc(deadline=3)
    urlfetch.make_fetch_call(rpc,url)
    return rpc

rpcs = []
urls = [...] # hundreds of urls

while rpcs < 10:
    rpcs.append(http_get(urls.pop()))

while rpcs:
    rpc = rpcs.pop(0)
    result = rpc.get_result()
    if result.status_code == 200:
        # append another item to rpcs
        # process result
    else:
        # re-append same item to rpcs

このコードは単純化されていることに注意してください。実際のコードは例外をキャッチし、追加のチェックを行い、同じ項目を数回追加しようとします。この場合は違いはありません。

結果の処理には操作が含まれていないことを付け加えておきますdb

4

1 に答える 1

0

実際には、ここで async urlfetch を使用することをお勧めします。仕組み (大まかな説明): - コードは非同期呼び出しのポイントに到達します。長いバックグラウンド タスクをトリガーし、その結果を待たずに実行を続けます。- タスクはバックグラウンドで動作し、結果の準備が整うと、要求されるまで結果をどこかに保存します。

簡単な例:

def get_fetch_all():
    urls = ["http://www.example.com/", "http://mirror.example.com/"]
    ctx = ndb.get_context()
    futures = [ctx.urlfetch(url) for url in urls]
    results = ndb.Future.wait_all(futures)
    # do something with results here

結果を ndb に保存し、より最適化する場合は、このためのカスタム タスクレットを作成することをお勧めします。

@ndb.tasklet
def get_data_and_store(url):
    ctx = ndb.get_context()
    # until we don't receive result here, this function is "paused", allowing other 
    # parallel tasks to work. when data will be fetched, control will be returned
    result = yield ctx.urlfetch("http://www.google.com/") 
    if result.status_code == 200:
        store = Storage(data=result.content)
        # async job to put data
        yield store.put_async()
        raise ndb.Return(True)
    else:
        raise ndb.Return(False)

そして、このタスクレットを最初のサンプルのループと組み合わせて使用​​できます。フェッチの成功を示す、r/false 値のリストを取得する必要があります。

これが全体的な生産性をどれだけ向上させるかはわかりませんが(Google側に依存します)、そうすべきです。

于 2012-11-27T09:53:04.717 に答える