文章目录一个请求从浏览器到数据库的完整旅程——Django 全链路拆解导入语1 ~ 整体链路图——一步到位2 ~ 第一步WSGI Server——TCP 连接变 Python 字典3 ~ 第二步中间件链——洋葱模型4 ~ 第三步到第六步路由 → View → ORM → 响应4.1 URL 路由匹配4.2 View 执行4.3 ORM 生成 SQL4.4 响应返回5 ~ 排查中间件性能问题——真实案例思考 总结结尾一个请求从浏览器到数据库的完整旅程——Django 全链路拆解文章简介你点了浏览器的刷新按钮0.5 秒后页面渲染完毕。这 0.5 秒里发生了什么本文把 Django 处理一个 HTTP 请求的完整链路拆为六个步骤WSGI Server 接收 TCP 连接 → 中间件栈的洋葱模型逐层处理 → URL 路由匹配 → View 执行业务逻辑 → ORM 生成 SQL 并发送到数据库 → Template 渲染或 JSON 序列化返回响应。每一步都配有对应的源码位置和关键代码片段读完你能对一个请求的全生命周期建立起清晰的空间模型。穿插真实调试经历——一个中间件错误导致所有 API 请求多耗 200ms 的排查过程。 个人主页源码骑士❄专栏传送门《Android开发基础》《python基础课程》⭐️热衷从源码视角拆解技术底层原理将复杂架构讲得通俗易懂 源码骑士的简介5年Android Framework系统开发经验曾主导多项系统级性能优化专项技术栈覆盖Android系统全链路Binder/Handler/AMS/WMS/启动流程及Java后端全家桶Spring MyBatis Redis Oracle累计产出原创技术文章100篇文章以源码拆解为特色被读者评价为看一篇胜过啃一周文档导入语2022 年我排查过一个有趣的性能问题。系统所有 API 接口的响应时间长了约 200ms但 DBA 说数据库正常、运维说网络正常。最后发现是一个中间件里有一段同步调用外部服务获取当前用户权限阻塞 200ms——而这 200ms 在每个请求里都要重复一遍。这个排查过程让我意识到——如果不把一个请求走过的每一步连成一条完整的链路你很难单独定位每一步在哪出了问题。本文拆解 Django 请求的全链路——从浏览器发出到数据库返回六个步骤步步相连。1 ~ 整体链路图——一步到位浏览器 WSGI Server Django 数据库 │ │ │ │ ├─① HTTP Request ─────→│ │ │ │ ├─② 解析为 environ │ │ │ ├─③ get_response()─→│ │ │ │ ├─④ 中间件链 │ │ │ ├─⑤ URL 路由 │ │ │ ├─⑥ View 执行 │ │ │ ├─⑦ ORM ───────→│ │ │ │←──── ⑧ 结果 ──┤ │ │ ├─⑨ 渲染/序列化 │ │ │←─⑩ HTTP Response─┤ │ │←──── ⑪ 响应 ─────────┤ │ │2 ~ 第一步WSGI Server——TCP 连接变 Python 字典浏览器发出 HTTP 请求后由 WSGI ServerGunicorn / uWSGI / Django 自带runserver接收 TCP 数据。WSGI Server 把 HTTP 请求解析成一个 Python 字典——environenviron{REQUEST_METHOD:GET,PATH_INFO:/api/v1/users/,QUERY_STRING:page2,HTTP_HOST:example.com,HTTP_AUTHORIZATION:Bearer xxx,wsgi.input:...,# 请求体流}然后调用application(environ, start_response)——这是 WSGI 协议的核心。Django 中的入口是这个函数# django/core/handlers/wsgi.pyclassWSGIHandler(base.BaseHandler):def__call__(self,environ,start_response):requestself.request_class(environ)# 把 environ 包装成 HttpRequestresponseself.get_response(request)# ← 核心入口从这行起开始请求进入 Django 核心。3 ~ 第二步中间件链——洋葱模型# django/core/handlers/base.pydefget_response(self,request):# 把中间件列表从外到内包装handlerself._get_response# 核心处理函数formiddlewareinreversed(self._middleware_chain):handlermiddleware(handler)# 每个中间件包裹内层returnhandler(request)中间件链的执行顺序是洋葱模型请求进 → 中间件1(前)→ 中间件2(前)→ 中间件3(前)→ View ↓ 响应出 ← 中间件1(后)← 中间件2(后)← 中间件3(后)←──┘一个典型的自定义中间件结构classTimingMiddleware:def__init__(self,get_response):self.get_responseget_responsedef__call__(self,request):# 前置处理starttime.time()responseself.get_response(request)# 调用内层可能是下一个中间件或 View# 后置处理durationtime.time()-start response[X-Request-Duration]str(duration)returnresponse4 ~ 第三步到第六步路由 → View → ORM → 响应4.1 URL 路由匹配# django/urls/resolvers.pyresolverget_resolver()matchresolver.resolve(request.path_info)# match.func → View 函数或 View 类# match.kwargs → URL 中捕获的参数 {pk: 42}4.2 View 执行View 从请求中提取参数调业务逻辑。典型的 FBVdefuser_list(request):usersUser.objects.select_related(department).all()returnrender(request,users.html,{users:users})4.3 ORM 生成 SQLDjango ORM 的 QuerySet 在被迭代或切片时触发实际的数据库查询# 还没查数据库——QuerySet 是惰性的usersUser.objects.filter(activeTrue)# 现在才查——QuerySet 被 list() 或 for 循环迭代foruserinusers:# ← 这里才执行 SQLprint(user.name)4.4 响应返回Django 把响应包装为HttpResponse对象。WSGI Server 取出response.content和response.status_code按 HTTP 协议发回浏览器。从 WSGI 入口到出口一个请求在 Django 内部走完全链路。5 ~ 排查中间件性能问题——真实案例2022 年的那个问题。所有接口慢了 200msclassPermissionMiddleware:def__call__(self,request):# 每个请求都调外部权限服务resprequests.get(fhttp://auth-service/check?user{request.user.id})request.permissionsresp.json()returnself.get_response(request)外部 Auth 服务响应 200ms。每个请求——不管是静态文件还是 API 调用——都要经过中间件的权限检查。即使用户已经缓存了中间件每次都调一次外部服务。优化方案权限查询结果缓存到 Redis缓存周期 5 分钟。200ms 降到大约 0.5ms。思考 总结Django 请求全链路六个步骤WSGI Server把 HTTP 请求包装为environ字典中间件链以洋葱模型从外到内层层处理再从内到外层层返回URL 路由按urlpatterns顺序匹配 → 找到对应的 ViewView解析请求参数 → 调用业务逻辑ORM惰性生成 SQL → 向数据库发起查询响应经过中间件链反向输出 → 返回浏览器结尾请求全链路拆解完毕感谢阅读源码骑士 — 源码级拆解从底层看透技术关注跟博主一起从源码视角深耕底层原理❤️点赞让优质内容被更多人看见⭐收藏核心知识点存好随用随查评论分享你的经验或疑问一起交流一键四连别忘了给博主一键四连️寄语把请求走过的路走一遍才知每一步哪里可能出问题。结语Django 请求的六个步骤是你排查所有性能问题的基准线。下篇讲数据库连接池——它不是为了让连接更快。一键四连