我无法理解aiohttp(通常是asyncio)服务器实现没有提供限制最大并发连接数限制(接受的套接字数或正在运行的请求处理程序数)的原因。 (https://github.com/aio-libs/aiohttp/issues/675)。没有此限制,很容易耗尽内存和/或文件描述符。
同时,默认情况下,aiohttp客户端将并发请求数限制为100(https://docs.aiohttp.org/en/stable/client_advanced.html#limiting-connection-pool-size),aiojobs限制了正在运行的任务数和未决任务列表的大小,nginx具有worker_connections限制,任何同步框架都受到限制根据设计的工作线程数。
虽然aiohttp可以处理许多并发请求,但此数量仍然有限。关于aiojobs的文档说:“ Scheduler暗含了对并发作业数量的限制(默认为100个)。...它通过同时运行十亿个作业来防止程序溢出。”而且,我们仍然可以愉快地产生aiohttp处理程序“十亿”(好,直到我们用尽资源)。
问题是,为什么要按原样实施?我是否缺少一些重要的细节?我认为我们可以使用Semafor暂停请求处理程序,但是与nginx相比,套接字仍然被aiohttp接受并且生成了协程。同样,在nginx后面进行部署时,worker_connections的数量和aiohttp所需的限制肯定会有所不同。(因为nginx也可以提供静态文件)
答案 0 :(得分:1)
基于开发者对linked issue的评论,选择该选项的原因如下:
如果应用程序检测到连接数大于其合理处理的数量,则可以返回4xx或5xx响应。 (这与Semaphore
惯用语不同,后者会有效地排队连接。)
限制服务器连接数比仅指定一个数要复杂得多,因为限制可能完全取决于协程的作用,即,它至少应基于路径。安德鲁·斯维特洛夫(Andrew Svetlov)链接到NGINX documentation,以了解支持连接的限制。
无论如何,建议将aiohttp放在专门的前端服务器(如NGINX)后面。
仅由已知读取此标签的开发人员才能提供比这更多的详细信息。
这时,似乎推荐的解决方案是使用反向代理进行限制,或使用基于应用程序的限制(例如此装饰器)(未测试):
REQUEST_LIMIT = 100
def throttle_handle(real_handle):
_nrequests = 0
async def handle(request):
nonlocal _nrequests
if _nrequests >= REQUEST_LIMIT:
return aiohttp.web.Response(
status=429, text="Too many connections")
_nrequests += 1
try:
return await real_handle(request)
finally:
_nrequests -= 1
return handle
@throttle_handle
async def handle(request):
... your handler here ...
答案 1 :(得分:1)
要限制并发连接,您可以使用 aiohttp.TCPConnector
或 aiohttp.ProxyConnector
(如果您使用代理)。只需在会话中创建它,而不是使用默认值。
aiohttp.ClientSession(
connector=aiohttp.TCPConnector(limit=1)
)
aiohttp.ClientSession(
connector=aiohttp.ProxyConnector.from_url(proxy_url, limit=1)
)