单Worker的Uvicorn(Linux)被CPU密集任务阻塞时的请求处理疑问
单Worker Uvicorn(Linux)被CPU密集任务阻塞时的请求处理逻辑
新请求的处理状态:单Worker的Uvicorn依赖事件循环处理IO和请求调度,一旦被CPU密集型任务阻塞,事件循环无法响应新的请求事件。此时新请求不会被Uvicorn的应用层处理,而是先停留在Linux内核的TCP相关队列/缓冲区中。
请求是否在TCP连接内排队:
- 对于已建立的长连接:客户端发送的请求数据会暂存在服务器的TCP接收缓冲区中排队,等待Uvicorn事件循环读取处理。
- 对于新连接请求(SYN包):会先进入Linux内核的SYN队列,完成三次握手后进入accept队列,等待Uvicorn调用
accept()取出连接。
阻塞解除后的处理顺序:会严格按请求的发送顺序处理。
顺序保障的负责组件:
- 核心是Linux内核的TCP协议栈:TCP是面向字节流的可靠协议,会保证客户端发送的字节按序到达服务器的TCP接收缓冲区。
- 辅助是Uvicorn的事件循环:它从TCP缓冲区读取数据时,会按字节流顺序解析HTTP请求,自然维持请求的发送顺序。
除客户端超时/连接丢失外的请求丢失场景:
- 内核SYN队列或accept队列被占满:新的SYN连接请求会被内核直接丢弃,无法建立连接。
- TCP接收缓冲区满:服务器的TCP接收缓冲区耗尽时,内核会丢弃后续收到的数据包,若TCP重传失败,请求数据会丢失。
- Uvicorn进程意外崩溃:所有积压在队列/缓冲区中未被处理的请求都会丢失。
除内存外的耗尽资源:
- 文件描述符:每个TCP连接对应一个文件描述符,系统对进程可用的文件描述符数量有上限(可通过
ulimit -n查看/调整),请求涌入导致连接数过多时会耗尽。 - 内核TCP连接状态资源:内核维护每个TCP连接的状态信息(如TCP控制块),大量连接会耗尽这类内存外的状态资源。
- 网络带宽:大量请求数据包同时涌入,可能占满服务器的网络带宽,导致后续请求的数据包延迟、丢包,甚至无法建立连接。
- 文件描述符:每个TCP连接对应一个文件描述符,系统对进程可用的文件描述符数量有上限(可通过
内容的提问来源于stack exchange,提问作者Martin Kroll
相关产品推荐
相关产品推荐

