問題: サーバーに多数の 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()