首页 > 解决方案 > Requests / Asyncio:使用 Python 请求会话使 pool_maxsize=1000 有缺点吗?

问题描述

我正在使用以下代码通过请求增加池 maxsize:

import requests
session = requests.Session()
session.mount("https://", requests.adapters.HTTPAdapter(pool_maxsize=50))
session.mount("http://", requests.adapters.HTTPAdapter(pool_maxsize=50))

设置有缺点pool_maxsize=1000吗?

我有时需要 50 - 1000 个连接,但大多数时候我只需要 1 个连接。

或者,有没有办法允许动态调整池大小?

哪种解决方案最好:

  1. pool_maxsize = 1000
  2. 创建 2 个会话,1 个使用pool_maxsize = 1,另一个使用pool_maxsize=1000.
  3. 当我需要不同数量的连接时动态改变 pool_maxsize 。(如果可能的话)

速度最重要!

编辑:大部分时间我都在做正常的请求:

session.get(....)

但有时我会使用 asyncio 来执行大量请求:

import asyncio
async def perform_async_calls(self, session, urls):
    loop = asyncio.get_event_loop()
    futures = []
    for url in urls:
        futures.append(loop.run_in_executor(None, session.get, url)

    results = []
    for future in futures:
        result = await future
        results.append(result.json())

    return results

标签: pythonasynchronousparallel-processingpython-requestspython-asyncio

解决方案


在 HTTP 1.1 中,客户端可以通过设置 Keep-Alive 标头通过同一连接发送多个请求。否则,您必须为每个请求打开一个新连接。使用 Keep-Alive 设置,可以通过同一连接发送多个请求。

打开连接的时间成本很高,因为它需要额外的 TCP 握手往返,然后才能发出下一个请求,因此重用已经存在的连接会更快。

连接池的作用是,在您发出请求后,该连接会为您可能发出的后续请求保持打开状态,并保留在池中。Requests 设置 keep alive 标头并在后台管理池,因此您通常无需担心它。

如果您使用多线程,则池会同步对连接的访问​​,以便每个连接一次仅由一个线程使用。让多个线程同时发出请求需要池中的多个连接。

拥有比线程更多的连接根本不会提高性能,因为请求包在发出请求时会阻塞线程,因此线程不可能一次使用多个连接。要从附加连接中获得更多性能,需要增加线程数。

像这样添加连接只有在您不受网络速度瓶颈时才有帮助,打开更多连接并不会使互联网更快。因此,只需添加更多线程+连接,直到性能停止增加。

我不确定动态调整大小是什么意思。池在需要时打开新连接,并尽可能重用旧连接。一旦达到最大值,它就会停止打开连接。从某种意义上说,池大小是动态的,只要它低于最大大小。


推荐阅读