Проблема: мне нужно отправить много HTTP-запросов на сервер. Я могу использовать только одно соединение (ограничение для неограниченного сервера). Время отклика сервера и латентность сети слишком высоки - я отстаю.
Обычно запросы не изменяют состояние сервера и не зависят от предыдущего запроса ответа. Поэтому моя идея состоит в том, чтобы просто отправить их друг на друга, выделить объекты ответа и зависеть от Content-Length: входящих ответов для подачи входящих ответов на объект ожидания следующего ожидания. Другими словами: Pipeline - запросы на сервер.
Это, конечно, не совсем безопасно (любой ответ без Content-Length: означает проблему), но мне все равно - в этом случае я всегда могу повторить любые запросы в очереди. (Безопасный способ состоял бы в том, чтобы дождаться заголовка перед отправкой следующего бита.Это могло бы помочь мне достаточно. Нет способа проверить заранее.)
Итак, в идеале я хочу, чтобы следующий клиентский код (который использует задержки клиентов для имитации латентности сети) запускается через три секунды.
Теперь для вопроса $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()