有没有最简单的方法来异步运行多个python请求?

时间:2019-11-04 11:27:59

标签: django python-3.x django-rest-framework python-requests python-asyncio

有一个API localhost:8000/api/postdatetime/,用于更改驱动程序的在线状态。每次驱动程序访问API时,如果发送回响应,则驱动程序状态将为联机,否则驱动程序状态将为脱机。

Drivers need to give the response within every 10 seconds.如果驾驶员没有回应,则他/她将被自动标记为脱机。

当前我正在做的是获取所有已登录的驱动程序,并一次点击上述API。

出于仿真目的,我填充了数千个驱动程序。使用我的方法来维持成千上万的驱动程序的离线,几乎所有的驱动程序都将保持离线状态。

我的方法的代码如下所述:

online-offline.py

import requests
import random
import math
from rest_framework.authtoken.models import Token

from ** import get_logged_in_driver_ids
from ** import Driver


def post_date_time():
    url = 'localhost:8000/api/postdatetime/'

    while True:
        # getting all logged in driver ids 
        logged_in_driver_ids = get_logged_in_driver_ids() 

        # filtering the driver who are logged in and storing their user id in the driver_query variable
        driver_query = Driver.objects.only('id', 'user_id').filter(id__in=logged_in_driver_ids).values('user_id')

        # storing the user id of driver in list
        driver_user_ids = [driver['user_id'] for driver in driver_query]

        # getting number of drivers who are supposed to hit the API
        drivers_subset_count = math.ceil(len(driver_user_ids)*(random.randint(75, 85)/100))

        # shuffle the driver ids list to randomize the driver id order
        random.shuffle(driver_user_ids)

        # getting the driver list of length drivers_subset_count
        required_drivers = driver_user_ids[:drivers_subset_count]

        for driver in required_drivers:
            token = Token.objects.only('key', 'user_id').get(user_id=driver)
            req_headers = {
                'Content-Type': 'application/json',
                'Accept': 'application/json',
                'Authorization': 'Token' + ' ' + str(token)
            }
            response = requests.post(url=url, headers=req_headers)
            print(response.text)



if __name == '__main__':
    post_date_time()

有没有想法可以异步发布localhost:8000/api/postdatetime/ API并可以在10秒内处理大约2-3000个驱动程序?

我在实现异步代码方面真的很陌生。我已经阅读了aiohttp库上的一些文章,但是在实现它时感到困惑。

online-offline.py将在整个模拟过程中运行。

任何帮助将不胜感激。谢谢:)

1 个答案:

答案 0 :(得分:1)

在使用非本地API的情况下,asyncio可以为您提供帮助。要异步发出请求,您必须:

  • 使用特殊语法(有关详细信息,请使用async defawait-read here
  • 以非阻塞方式进行请求(因此您可以等待它们)
  • 使用类似的方法asyncio.gather()并行发出多个请求”
  • 开始事件循环

使用线程使requests库与asyncio一起使用possible时,使用aiohttp这样已经异步兼容的库更容易,更好。

看看code snippets here *:它们包含发出多个并发请求的示例。用相同的方式重写代码,如下所示:

import asyncio


async def driver_request(driver):
    # ...
    # use aiohttp to make request with custom headers:
    # https://docs.aiohttp.org/en/stable/client_advanced.html#custom-request-headers


async def post_date_time():
    # ...

    await asyncio.gather(*[
        driver_request(driver) 
        for driver 
        in required_drivers
    ])


asyncio.run(post_date_time())

默认情况下,本地不会显示任何效果,因此要在本地进行测试,您必须使localhost延迟发送响应以模拟实际的网络延迟。


*在最新的Python版本中,事件循环仅需运行asyncio.run()