我无法理解 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 也可能提供静态文件)
我想在许多进程中重用 imaplib.IMAP4_SSL 实例,这样我就不必多次登录。这是一些代码:
import imaplib
from multiprocessing import Process
def fetch(mail_client):
mail_client.uid('fetch', b'1', 'BODY[TEXT]')
def main():
c = imaplib.IMAP4_SSL('imap.gmail.com')
c.login(user='**', password='***')
c.select('inbox')
procs = [Process(target=fetch, args=(c,)) for _ in range(100)]
for p in procs:
p.start()
for p in procs:
p.join()
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
但我收到与套接字相关的错误:
imaplib.IMAP4.abort:套接字错误:[Errno 32] 管道损坏
我认为这是因为进程正在写入 imaplib.IMAP4_SSL 所具有的同一个套接字,所以我尝试添加 multiprocessing.Lock 以防止同时访问:
import imaplib
from multiprocessing import Process, Lock
def fetch(mail_client, lock):
with lock:
mail_client.uid('fetch', b'1', 'BODY[TEXT]')
def main():
c = imaplib.IMAP4_SSL('imap.gmail.com')
c.login(user='engineering@epallet.com', password='Qwe=1dSAzxc+%')
c.select('inbox')
lock = Lock() …
Run Code Online (Sandbox Code Playgroud)