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 + Vue 前后端分离实战:我的项目结构“避坑指南”
前端·vue.js·fastapi
Aric_Jones21 小时前
从实战理解异步、并发并行与GIL:FastAPI vs SpringBoot
java·spring boot·fastapi
不是株1 天前
FastAPI
python·fastapi
星星也在雾里1 天前
Dify + FastAPI + 讯飞WebSocket实现方言识别
人工智能·fastapi
Ares-Wang2 天前
FastAPI 数据验证 Pydantic Flask 用 WTForms
python·flask·fastapi
曲幽2 天前
FastAPI自动生成的API文档太丑?我花了一晚上把它改成了客户愿意付费的样子
python·fastapi·web·swagger·openapi·scalar·docs
PieroPc3 天前
一个功能强大的 Web 端标签设计和打印工具,支持服务器端直接打印到局域网打印机。Fastapi + html
前端·html·fastapi
别抢我的锅包肉3 天前
FastAPI + Vue3 + Vite 跨域报错全解:从 `Access-Control-Allow-Origin missing` 到彻底修复
中间件·状态模式·fastapi
Chase_______3 天前
【FastAPI】内网/离线环境docs文档无法显示的解决方案
fastapi
小李云雾3 天前
FastAPI 后端开发:文件上传 + 表单提交
开发语言·python·lua·postman·fastapi