Ale*_*nov 7 python-asyncio aiohttp
我无法理解 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 上的文档说“调度程序隐含了并发作业数量的限制(默认为 100)。......它通过同时运行十亿个作业来防止程序溢出”。而且,我们仍然可以愉快地产生“十亿”(好吧,直到我们用完资源)aiohttp 处理程序。
所以问题是,为什么它会以这样的方式实施?我错过了一些重要的细节吗?我认为我们可以使用 Semafor 以某种方式暂停请求处理程序,但与 nginx 相比,aiohttp 仍然接受套接字并生成协程。同样在 nginx 后面部署时,worker_connections 和 aiohttp 所需的限制数量肯定会有所不同。(因为 nginx 也可能提供静态文件)
根据开发者对链接问题的评论,做出这种选择的原因如下:
如果应用程序检测到连接数大于它可以合理处理的数量,它可以返回 4xx 或 5xx 响应。(这与Semaphore习惯用法不同,后者会有效地将连接排队。)
限制服务器连接的数量比仅仅指定一个数字更复杂,因为限制很可能取决于您的协程正在做什么,即它至少应该是基于路径的。Andrew Svetlov 链接到有关连接限制的NGINX文档以支持这一点。
无论如何,建议将 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 ...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2533 次 |
| 最近记录: |