Клиент HTTP Python с конвейерной обработкой запросов
Проблема: мне нужно отправить много 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()
Ответы
Ответ 1
Dugong является клиентом только для HTTP/1.1, который утверждает, что поддерживает реальную конвейерную обработку HTTP/1.1. В учебнике есть несколько примеров того, как его использовать, в том числе using темы и еще один с помощью asyncio.
Обязательно убедитесь, что сервер, с которым вы общаетесь, фактически поддерживает конвейерную обработку HTTP/1.1, некоторые серверы утверждают, что поддерживают HTTP/1.1, но не реализуют конвейерную обработку.
Ответ 2
Это не ответ на вопрос вашей библиотеки, но не могли бы вы использовать что-то в качестве селена и их selenium.webdriver.support.ui import WebDriverWait
дождаться, когда ваши запросы будут обработаны в течение некоторого времени, а затем сделайте следующий шаг: сохраните ответ для последующего использования или отправьте следующий запрос, если у вас нет соответствующего ответа?
Использование этого интерфейса также позволит использовать прокси для обхода (разумно, в зависимости от вашего приложения и потребностей) лимит сервера (либо 3, либо 5 - большая скорость), если для этого соединения не требуется аутентификация.
Ответ 3
Кажется, вы используете python2.
Для python3 >= 3.5
вы можете использовать цикл async/wait
См. asyncio
Кроме того, есть библиотека, построенная сверху для лучшего, более простого использования
называемый Trio, доступный по адресу.
Еще одна вещь, о которой я могу думать, - это несколько потоков с замками.
Я буду думать о том, как лучше объяснить это, или он может даже работать.