FastAPI 源码阅读==浏览器一次请求到 uvicorn/FastAPI 的底层流程(含 epoll/FD)

浏览器一次请求到 uvicorn/FastAPI 的底层流程(含 epoll/FD)

  1. 浏览器发起 HTTP 请求 → 建立 TCP 连接

浏览器向服务器的:

IP:PORT(例如 1.2.3.4:8080)

发起三次握手,建立 TCP 连接。

  1. uvicorn 在服务器上监听端口

uvicorn(Python 级别)做:

sock = socket()

sock.bind(('0.0.0.0', 8080))

sock.listen()

这一步创建了:

监听 socket(FD),比如 fd=7

随后 uvicorn 会将这个 socket 加入事件循环:

loop.add_reader(fd=7, callback=on_accept)

如果使用 uvloop,该操作最终会变成:

libuv 调用 epoll_ctl(ADD fd=7)

  1. uvloop(libuv)使用 epoll 监听这些 FD

libuv 在 Linux 下:

为事件循环创建一个 epoll 实例

调用 epoll_ctl() 注册 fd=7

进入循环,不停执行:

epoll_wait()

这是关键点:

🔥 内核不会主动"调用回调"

而是:

✔ 内核只是在 epoll 实例里标记:

"某个 FD 已经准备好读/写了"

然后等用户空间 epoll_wait() 返回。

  1. 浏览器发来第一个 HTTP 报文 → FD 可读(EPOLLIN)

当客户端发送 HTTP 请求报文,到达服务器的 fd=9(已 accept 的连接):

内核将 fd 标记为"可读"

放入 epoll 的 ready-list

然后 epoll_wait() 被唤醒并返回

没有任何"内核调用回调"的行为

只有 epoll_wait 主动返回就绪 FD 列表

  1. uvloop 的事件循环得到事件 → 调用对应回调

uvloop 的事件循环不断运行:

epoll_wait() → ready FDs → 调用 Python 层对应回调

例如:

fd=7(监听端口)有 EPOLLIN → on_accept 被调用

fd=9(某个客户端连接)有 EPOLLIN → on_read 被调用

这些回调函数最终进入 uvicorn 的 HTTP 解析逻辑。

  1. HTTP/1.1 Keep-Alive → 同一个 FD 多次进入 ready list

浏览器下一次发请求(仍在同一 TCP 连接上):

内核再次检测到 fd=9 可读

再次将 fd=9 放入 epoll ready-list

uvloop 再次从 epoll_wait 得到它

uvicorn 再次处理(这一次就是第二个 HTTP 请求)

FD 不会关闭

FD 会反复进入 ready-list

直到浏览器或服务器主动关闭连接

⭐ 最终整理后的版本(推荐你保存)

下面是一版简洁 + 完全准确的表述:

✅ 从浏览器发起 HTTP 请求到 uvicorn/FastAPI 的底层机制(含 FD / epoll / uvloop)

浏览器发起 HTTP 请求 → 建立 TCP 连接

浏览器与服务器的监听端口(例如 8080)建立 TCP 连接。

uvicorn 监听端口,创建监听 FD

uvicorn 创建 socket FD(如 fd=7)并调用事件循环注册监听。

uvloop(基于 libuv)将 FD 注册到 epoll

libuv 调用 epoll_ctl(EPOLL_CTL_ADD),将监听 FD 加入 epoll。

事件循环执行 epoll_wait() 等待就绪 FD

内核不会主动调用回调,只会在 epoll 实例中标记就绪 FD。

浏览器发送 HTTP 报文 → FD 可读

内核将该 FD 标记为 EPOLLIN,epoll_wait 被唤醒并返回该 FD。

uvloop 拿到 ready FD → 调用对应的回调函数

对监听 FD → accept 回调

对连接 FD → read 回调(进入 uvicorn HTTP parser)

FastAPI 处理请求并返回响应

Keep-Alive 下:同一个 FD 持续复用

当浏览器再次发起请求,FD 再次可读,被 epoll 标记,再次被 uvloop 回调处理。

连接关闭时,FD 被 epoll 删除并关闭

当浏览器或服务器关闭连接,FD 才真正关闭和消失。

🎯 最终一句话

一次 HTTP 请求不会导致 FD 消失,只要 Keep-Alive 存在,同一个 FD 会多次进入 epoll 的 ready list;只有 TCP 连接断开时 FD 才会被关闭。

相关推荐
别催小唐敲代码13 小时前
FastAPI 从零开始完整学习教程
学习·fastapi
05大叔15 小时前
FastAPI框架 路径,查询,请求体参数,JSON,文本,HTML响应类型,异常
fastapi
小陈工1 天前
FastAPI性能优化实战:从每秒100请求到1000的踩坑记录
python·性能优化·django·flask·numpy·pandas·fastapi
带娃的IT创业者1 天前
WeClaw 日志分析实战:如何从海量日志中快速定位根因?
运维·python·websocket·jenkins·fastapi·架构设计·实时通信
天下无贼!1 天前
【Python】2026版——FastAPI 框架快速搭建后端服务
开发语言·前端·后端·python·aigc·fastapi
带娃的IT创业者2 天前
Weclaw 混合通讯架构实战:HTTP+SSE+WebSocket的三元融合如何支撑起整个 AI 助手的实时对话?
websocket·http·fastapi·sse·流式响应·实时通讯·混合架构
紫丁香2 天前
Dify源码深度剖析3
后端·python·ai·flask·fastapi
沐硕2 天前
《基于改进协同过滤与多目标优化的健康饮食推荐系统设计与实现》
java·python·算法·fastapi·多目标优化·饮食推荐·改进协同过滤
带娃的IT创业者2 天前
WeClaw 架构演进史:从 0 到 1 构建跨平台 AI 助手的完整历程
人工智能·python·websocket·架构·fastapi·架构设计·实时通信
沐硕3 天前
Dietify 智能饮食推荐系统全解析 —— 当协同过滤遇上营养科学,构建你的私人饮食管家
spring boot·python·fastapi·多目标优化·饮食推荐·改进协同过滤