【问题标题】:Why aiohttp works slower than requests wrapped by run_in_executor?为什么 aiohttp 比 run_in_executor 包裹的请求慢?
【发布时间】:2020-03-18 15:55:25
【问题描述】:

全部!

我需要向 Web 服务发出大约 10,000 个请求,并且我期望 JSON 作为响应。由于请求彼此独立,我想并行运行它们。我认为aiohttp 可以帮助我。我写了以下代码:

import asyncio
import aiohttp


async def execute_module(session: aiohttp.ClientSession, module_id: str,
                         post_body: dict) -> dict:
    headers = {
        'Content-Type': r'application/json',
        'Authorization': fr'Bearer {TOKEN}',
    }

    async with session.post(
            fr'{URL}/{module_id}/steps/execute',
            headers=headers,
            json=post_body,
    ) as response:
        return await response.json()


async def execute_all(campaign_ids, post_body):
    async with aiohttp.ClientSession() as session:
        return await asyncio.gather(*[
            execute_module(session, campaign_id, post_body)
            for campaign_id in campaign_ids
        ])

campaign_ids = ['101', '102', '103'] * 400
post_body = {'inputs': [{"name": "one", "value": 1}]}

print(asyncio.run(execute_all(campaign_ids, post_body)))

P.S.我提出了 1,200 个测试请求。

解决它的另一种方法 - 将 requests.post 包装在 run_in_executor 函数中。我知道在异步函数中使用阻塞代码是错误的,但它运行得更快(~ 7 秒 vs. ~ 10 秒 aiohttp)

import requests
import asyncio


def execute_module(module_id, post_body):
    headers = {
        'Content-Type': r'application/json',
        'Authorization': fr'Bearer {TOKEN}',
    }

    return requests.post(
        fr'{URL}/{module_id}/steps/execute',
        headers=headers,
        json=post_body,
    ).json()

async def execute_all(campaign_ids, post_body):
    loop = asyncio.get_running_loop()
    return await asyncio.gather(*[
        loop.run_in_executor(None, execute_module, campaign_id, post_body)
        for campaign_id in campaign_ids
    ])

campaign_ids = ['101', '102', '103'] * 400
post_body = {'inputs': [{"name": "one", "value": 1}]}

print(asyncio.run(execute_all(campaign_ids, post_body)))

我做错了什么?

【问题讨论】:

    标签: python python-requests aiohttp python-asyncio


    【解决方案1】:

    loop.run_in_executor(None, ...) 在线程池(多线程)中运行同步代码。事件循环在一个线程中运行代码。
    我的猜测是等待 IO 应该没什么区别,但是处理响应(即 json 解码)会。

    【讨论】:

      【解决方案2】:

      你试过 uvloop - https://github.com/MagicStack/uvloop 吗?这应该会提高 aiohttp 请求的速度

      【讨论】:

      • 这决不能解决问题
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-21
      • 2013-07-12
      • 1970-01-01
      • 2012-02-17
      • 1970-01-01
      相关资源
      最近更新 更多