速率限制 aiohttp.ClientSession() 每秒发出 N 个请求

时间:2021-05-03 01:41:18

标签: python-asyncio aiohttp

我想使用 aiohttp 客户端为我们的服务创建一个异步 SDK。我一直无法弄清楚如何限制 ClientSession() 以每秒仅发出 N 个请求。

class AsyncHTTPClient:
    def __init__(self, api_token, per_second_limit=10):
        self._client = aiohttp.ClienSession(
            headers = {"Authorization": "Bearer f{api_token}"}
        )
        self._throttler = asyncio.Semaphore(per_second_limit)
    
   async def _make_request(self, method, url, **kwargs):
       async with self._throttler:
           return await self._client.request(method, url, **kwargs)
   
   async def get(self, url, **params):
       return await self._make_request("GET", url, **params)

   async def close(self):
       await self._client.close()

我有一个带有 get, post, patch, put, delete 方法的类,作为对 _make_request 的调用实现。

#As a user of the SDK I run the following code. 
async def main():
   try:
       urls = [some_url * 100]
       client = AsyncHTTPClient(my_token, per_second_limit=20)
       await asyncio.gather(*[client.get(url) for url in urls])
   finally:
       await client.close()

asyncio.run(main())

asyncio.Semaphore 限制并发。也就是说,当调用 main() 函数时,async with self._throttler 中使用的 client._make_request 将并发限制为 20 个请求。但是,如果 20 个请求在 1 秒内完成,则将继续发出请求。我想要做的是确保在一秒钟内只发出 N 个请求(即 20 个)。如果所有 20 个请求在 0.8 秒内完成,则休眠 0.2 秒,然后再次处理请求。

我使用 asyncio.Queue 示例查找了一些 workers 示例,但我不确定如何在我的 SDK 中实现它,因为创建 workers 必须由用户使用这个 SDK,我想避免这种情况,我希望 AsyncHTTPClient 处理每秒请求数限制。

任何建议/建议/样品将不胜感激。

0 个答案:

没有答案