Я использую библиотеку httpx
и asyncio
, чтобы попытаться отправить около 100 000 запросов на получение.
Я запустил код и получил httpx.ConnectError
, поэтому я открыл wireshark
и увидел, что получаю много сообщений, говорящих TCP Retransmission TCP Port numbers reused
когда я увидел данные в wireshark
и ошибку httpx.ConnectError
, я добавил limits = httpx.Limits(max_connections=10000)
, чтобы ограничить количество активных подключений до 10 000, но я все еще получаю эту ошибку.
мой код:
import asyncio
import json
import httpx
SOME_URL = "some url"
ANOTHER_URL = "another url"
MAX = 10000
async def search():
guids = [guid for guid in range(688001, 800000)] # 688001 - 838611
timeout = httpx.Timeout(None)
limits = httpx.Limits(max_connections=MAX)
async with httpx.AsyncClient(timeout=timeout, limits=limits) as client:
tasks = [client.get(f"{SOME_URL}{guid}", timeout=timeout) for guid in guids]
blob_list = await asyncio.gather(*tasks) # <---- error from here !!!!!
blob_list = [(res, guid) for res, guid in zip(blob_list, guids)]
guids = [guid for res, guid in blob_list]
blob_list = [json.loads(res.text)["blob_name"] for res, guid in blob_list]
async with httpx.AsyncClient(timeout=timeout, limits=limits) as client:
tasks = [client.get(f"{ANOTHER_URL}{blob}", timeout=timeout) for blob in blob_list]
game_results = await asyncio.gather(*tasks) # <---- error from here !!!!!
game_results = [(res, guid) for res, guid in zip(game_results, guids)]
game_results = [guid for res, guid in game_results]
print(game_results)
def main():
asyncio.run(search())
if __name__ == '__main__':
main()
это минимальная версия моего кода там какие-то шаги между запросами которые я удалил, но я не трогал код который наделал беду, есть комментарии к строкам что я получаю ошибки (# <---- ошибка отсюда!!!!!).
Кто-нибудь знает, как это решить? или другой способ быстро отправить около 100 000 запросов на получение?
да сервер справится с нагрузкой @nullsteph
Знаете ли вы другой способ быстрой отправки большого количества запросов на получение?
Это на винде? Я вижу эту ошибку также в Windows, но не в Linux.
да, это на окнах @Damien
Мне удалось решить мою проблему с помощью следующего кода:
(это не весь код, только части, необходимые для отправки запросов, между ними есть кое-что)
import asyncio
from aiohttp import ClientSession
SOME_URL = "some url"
ANOTHER_URL = "another url"
MAX_SIM_CONNS = 50
worker_responses = []
async def fetch(url, session):
async with session.get(url) as response:
return await response.read()
async def fetch_worker(url_queue: asyncio.Queue):
global worker_responses
async with ClientSession() as session:
while True:
url = await url_queue.get()
try:
if url is None:
return
response = await fetch(url, session)
worker_responses.append(response)
finally:
url_queue.task_done()
# calling task_done() is necessary for the url_queue.join() to work correctly
async def fetch_all(base_url: str, range_: range):
url_queue = asyncio.Queue(maxsize=10000)
worker_tasks = []
for i in range(MAX_SIM_CONNS):
wt = asyncio.create_task(fetch_worker(url_queue))
worker_tasks.append(wt)
for i in range_:
await url_queue.put(f"{base_url}{i}")
for i in range(MAX_SIM_CONNS):
# tell the workers that the work is done
await url_queue.put(None)
await url_queue.join()
await asyncio.gather(*worker_tasks)
if __name__ == '__main__':
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(fetch_all(SOME_URL, range(680_842, 840_423)))
print(worker_responses)
Я использовал aiohttp
вместо httpx
и использовал asyncio.Queue
, чтобы уменьшить использование оперативной памяти, и это сработало для меня.
Вы уверены, что сервер выдержит нагрузку?