Задержка между возвращением пакетов и их получением асинхронным кодом python?

#python #asynchronous #tcp #python-asyncio #httpx

Вопрос:

У меня около 130 асинхронных запросов GET, отправляемых с использованием httpx и asyncio в python, через прокси-сервер, который я сам создал на AWS.

В скрипте python я напечатал время непосредственно перед отправкой каждого запроса и вижу, что все они отправляются менее чем за 70 мс. Тем не менее, я рассчитал продолжительность запросов, получив текущее время сразу после этого, и некоторые запросы занимают до 30 секунд! Распределение кажется довольно ровным за это время, поэтому я получаю примерно 3-5 запросов каждую секунду в течение 30 секунд.

Я использовал tcpdump и wireshark, чтобы посмотреть на возвращающиеся пакеты, и кажется, что все данные приложения возвращаются в течение 4 секунд (включая tcp-рукопожатия), поэтому я не понимаю причину задержки в python.

Разрывы tcp происходят до 35 секунд спустя, так что, возможно, это может быть причиной задержки? Ожидает ли httpx закрытия соединения (FIN и ACK), прежде чем httpx.get() будет разблокирован и запрос можно будет прочитать?

Что я могу сделать, чтобы ускорить это?

Вот упрощенная версия моего кода:

 import asyncio import datetime  import httpx  from utils import store_data, get_proxy_addr   CLIENT = None  async def get_and_store_thing_data(thing):  t0 = datetime.now()  res = await CLIENT.get('https://www.placetogetdata.com', params={'thing': thing})  t1 = datetime.now()  # It's this line that shows the time is anywhere from 0-30 seconds for the  # request to return  print(f'time taken: {t1-t0}')  data = res.json()  store_data(data)  return data   def get_tasks(things):  tasks = []  for thing in things:  tasks = get_and_store_thing_data(thing)  tasks.append(tasks)   return tasks   async def run_tasks(tasks):  global CLIENT  CLIENT = httpx.AsyncClient(proxies={'https://': proxy_addr})  try:  await asyncio.wait(tasks)  finally:  await CLIENT.aclose()   def run():  proxy_addr = get_proxy_addr()  tasks = get_tasks  asyncio.run(run_tasks(tasks, proxy_addr))  

Комментарии:

1. Все эти запросы выполняются в одном цикле событий? Может ли быть так, что обработка всех предыдущих ответов занимает 30 секунд? Можете ли вы добавить какой-нибудь код

2. Отправляется ли каждый запрос в уникальный домен или все они отправляются в один и тот же домен? Если последнее, то есть большая вероятность, что сервер вас задушит.

3. @IainShelvington Пожалуйста, посмотрите пример кода, который я добавил. Все они выполняются с помощью одного asyncio.run()

4. @dirn Да, все переходят в один и тот же домен….однако они не регулируются, так как я создал 26 прокси-серверов на всех серверах AWS с помощью одного балансировщика сетевой нагрузки, и я каждый раз получаю все данные для всех запросов…. когда я не использую прокси, я получаю сообщение об ошибке от домена и забанен на 5 минут. Кроме того, я посмотрел на возвращаемые пакеты с помощью wireshark, и все данные приложения возвращаются через несколько секунд. Похоже, локально возникает задержка между возвращением пакетов и кодом python, разблокирующим ожидаемую сопрограмму httpx.get

5. @JonnyShanahan если вы удалите все, кроме запроса и печати времени, затраченного на вашу функцию, значительно ли сократится затраченное время? У меня есть предчувствие, что 130 звонков store_data займет 30 секунд