首页 文章

python3.6使用aiohttp和asyncio启动100万个请求

提问于
浏览
0

我试图用aiohttp和asyncio连续10次发出100万次请求,每次10k次 . 当我打印每个请求的开始时间时,我发现100万个请求不是在非常封闭的时间开始,而是在serval分钟内 . 根据我的理解,100万个请求将在没有任何等待的情况下发送(或者只是以微秒为单位)?希望有人可以帮我提出如何更改代码的建议,我的代码如下所示 . 提前致谢!

import asyncio
import requests
import json
import pymysql
from aiohttp import ClientSession
from datetime import datetime
import uvloop


# login config
URL_LOGIN = "https://test.com/user/login"
APP_ID = "sample_app_id"
APP_SECRET = "sample_secret"


async def login_user(phone, password, session, i):
    start_time = datetime.now()
    h = {
        "Content-Type": "application/json"
    }
    data = {
        "phone": phone,
        "password": password,
        "appid": APP_ID,
        "appsecret": APP_SECRET
            }
    try:
        async with session.post(url=URL_LOGIN, data=json.dumps(data), headers=h) as response:
            r = await response.read()
            end_time = datetime.now()
            cost = (end_time-start_time).seconds
            msg = "number %d request,start_time:%s, cost_time: %d, response: %s\n" % (i, start_time, cost, r.decode())
            print("running %d" % i, datetime.now())
    except Exception as e:
        print("running %d" % i)
        msg = "number %d request raise error" % i+str(e)+"\n"
    with open("log", "a+") as f:
        f.write(msg)


async def bound_login(sem, phone, password, session, i):
    async with sem:
        await login_user(phone, password, session, i)


async def run_login(num):
    tasks = []
    sem = asyncio.Semaphore(10000)
    async with ClientSession() as session:
        for i in range(num):
            task = asyncio.ensure_future(bound_login(sem, str(18300000000+i), "123456", session, i))
            tasks.append(task)
        responses = asyncio.gather(*tasks)
        await responses

start = datetime.now()
number = 100000
loop = uvloop.new_event_loop()
asyncio.set_event_loop(loop)
future = asyncio.ensure_future(run_login(number))

1 回答

  • 4

    当我打印每个请求的开始时间时,我发现100万个请求不是在非常封闭的时间开始,而是在serval分钟内 .

    您的代码确实发出了总共100万个请求,但是在约束条件下,在任何给定时间不超过10,000个请求并行运行 . 这就像拥有10k请求插槽一样 - 前10,000个请求将立即启动,但是10,001st将不得不等待先前的请求完成,以便它可以获得一个空闲插槽 .

    这就是为什么100万个请求无法立即或接近即时启动的原因,大多数请求必须等待一些下载完成,这需要时间 .

    根据我的理解,100万个请求将毫无等待地发送

    当前代码显式地使请求等待,以防止超过10k的请求并行运行 . 如果您真的想(尝试)发出一百万个并行请求,请删除信号量并使用connector创建 ClientSession ,并将 limit 设置为 None .

    但是,请注意,由于操作系统和硬件的限制,维护一百万个打开的连接可能不起作用 . (你应该仍然可以在瞬间启动连接,但是我希望它们中的大多数在不久之后以异常方式退出 . )

相关问题