20

問題: サーバーに多数の HTTP リクエストを送信する必要があります。使用できる接続は 1 つだけです (交渉不可のサーバー制限)。サーバーの応答時間にネットワーク遅延を加えた時間が長すぎます。遅れをとっています。

通常、リクエストはサーバーの状態を変更せず、前のリクエストのレスポンスに依存しません。したがって、私の考えは、単純にそれらを重ねて送信し、応答オブジェクトをキューに入れ、受信応答の Content-Length: に依存して、受信応答を次の待機中の応答オブジェクトにフィードすることです。つまり、リクエストをサーバーにパイプラインします。

もちろん、これは完全に安全というわけではありません (Content-Length: のない応答は問題を意味します) が、私は気にしません。その場合、キューに入れられた要求をいつでも再試行できます。(安全な方法は、次のビットを送信する前にヘッダーを待つことです。それで十分かもしれません。事前にテストする方法はありません。)

したがって、理想的には、次のクライアント コード (クライアント遅延を使用してネットワーク遅延を模倣する) を 3 秒で実行したいと考えています。

64000 ドルの質問ですが、既にこれを行っている Python ライブラリはありますか、それとも自分で作成する必要がありますか? 私のコードは gevent を使用しています。必要に応じて Twisted を使用することもできますが、Twisted の標準接続プールはパイプライン化されたリクエストをサポートしていません。必要に応じて C ライブラリのラッパーを作成することもできますが、ネイティブ コードの方が好みです。

#!/usr/bin/python

import gevent.pool
from gevent import sleep
from time import time

from geventhttpclient import HTTPClient

url = 'http://local_server/100k_of_lorem_ipsum.txt'
http = HTTPClient.from_url(url, concurrency=1)

def get_it(http):
    print time(),"Queueing request"
    response = http.get(url)
    print time(),"Expect header data"
    # Do something with the header, just to make sure that it has arrived
    # (the greenlet should block until then)
    assert response.status_code == 200
    assert response["content-length"] > 0
    for h in response.items():
        pass

    print time(),"Wait before reading body data"
    # Now I can read the body. The library should send at
    # least one new HTTP request during this time.
    sleep(2)
    print time(),"Reading body data"
    while response.read(10000):
        pass
    print time(),"Processing my response"
    # The next request should definitely be transmitted NOW.
    sleep(1)
    print time(),"Done"

# Run parallel requests
pool = gevent.pool.Pool(3)
for i in range(3):
    pool.spawn(get_it, http)

pool.join()
http.close()
4

3 に答える 3