簡體   English   中英

最大化並行請求數 (aiohttp)

[英]Maximize number of parallel requests (aiohttp)

tl;dr :如何最大限度地增加可以並行發送的 http 請求數?

我正在使用aiohttp庫從多個 url 獲取數據。 我正在測試它的性能,我觀察到在這個過程中的某個地方存在瓶頸,一次運行更多的 url 無濟於事。

我正在使用此代碼:

import asyncio
import aiohttp

async def fetch(url, session):
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0'}
    try:
        async with session.get(
            url, headers=headers, 
            ssl = False, 
            timeout = aiohttp.ClientTimeout(
                total=None, 
                sock_connect = 10, 
                sock_read = 10
            )
        ) as response:
            content = await response.read()
            return (url, 'OK', content)
    except Exception as e:
        print(e)
        return (url, 'ERROR', str(e))

async def run(url_list):
    tasks = []
    async with aiohttp.ClientSession() as session:
        for url in url_list:
            task = asyncio.ensure_future(fetch(url, session))
            tasks.append(task)
        responses = asyncio.gather(*tasks)
        await responses
    return responses

loop = asyncio.get_event_loop()
asyncio.set_event_loop(loop)
task = asyncio.ensure_future(run(url_list))
loop.run_until_complete(task)
result = task.result().result()

使用不同長度的url_list運行這個(針對https://httpbin.org/delay/2 的測試)我看到添加更多的 url 一次運行最多只能幫助 100 個 url,然后總時間開始與數字成比例增長網址(或者換句話說,每個網址的時間不會減少)。 這表明在嘗試立即處理這些時會出現問題。 此外,在“一批”中有更多網址時,我偶爾會收到連接超時錯誤。

在此處輸入圖片說明

  • 為什么會發生? 究竟是什么限制了這里的速度
  • 如何檢查在給定計算機上可以發送的最大並行請求數是多少? (我的意思是一個確切的數字 - 不是如上所述的“反復試驗”)
  • 我可以做些什么來增加一次處理的請求數量?

我在 Windows 上運行這個。

編輯以回應評論:

這是限制設置為None的相同數據。 最后只有輕微的改進,並且一次發送了 400 個 url 的連接超時錯誤很多。 我最終在我的實際數據上使用了limit = 200

在此處輸入圖片說明

默認情況下, aiohttp將同時連接數限制為100 它通過為ClientSession使用的TCPConnector 對象設置默認limit來實現。 您可以通過創建自定義連接器並將其傳遞給會話來繞過它:

connector = aiohttp.TCPConnector(limit=None)
async with aiohttp.ClientSession(connector=connector) as session:
    # ...

但是請注意,您可能不想將此數字設置得太高:您的網絡容量、CPU、RAM 和目標服務器都有自己的限制,嘗試進行大量連接可能會導致故障增加。

可能只有通過在混凝土機器上的實驗才能找到最佳數量。


無關:

您不必無故創建任務。 大多數 asyncio api 接受常規協程。 例如,您的最后幾行代碼可以這樣修改:

loop = asyncio.get_event_loop()
loop.run_until_complete(run(url_list))

或者甚至只是asyncio.run(run(url_list)) (doc ) 如果您使用的是 Python 3.7

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM