用 django-debug-toolbar 可直接分层查看请求耗时分布,需满足 debug=true、internal_ips 包含请求 ip,并确保 debugtoolbarmiddleware 位置正确(commonmiddleware 后、gzipmiddleware 前);异步视图或流式响应可能导致工具栏不显示。

查 Django 请求耗时分布用 django-debug-toolbar
直接装上 django-debug-toolbar 是定位延迟来源最快的方式。它能分层显示每个请求中模板渲染、数据库查询、缓存读写、信号触发等环节的耗时,不用猜哪块拖慢了响应。
注意三点:
- 只在
DEBUG=True且请求来自本地 IP(如INTERNAL_IPS = ['127.0.0.1'])时才显示,生产环境不能用 - 如果页面加载后没看到工具栏,检查中间件顺序——
DebugToolbarMiddleware必须放在CommonMiddleware之后、但不能在GZipMiddleware之后(否则压缩会干扰注入) - 某些异步视图或流式响应(如
StreamingHttpResponse)会导致工具栏不出现,这时得换别的手段
看数据库慢查询用 django.db.connection.queries 和 EXPLAIN
很多延迟实际来自没加索引的 filter() 或嵌套 select_related() 漏掉的 N+1 查询。光看 connection.queries 列表只能知道“有多少条”,看不出“为什么慢”。
更有效的做法是:
- 在 shell 或视图里手动执行
print(connection.queries[-1]['sql'])抽出最慢那条 SQL - 把 SQL 粘到数据库命令行里跑
EXPLAIN ANALYZE(PostgreSQL)或EXPLAIN FORMAT=JSON(MySQL),重点看是否走索引、是否触发 filesort 或临时表 - 对
order_by()字段、filter()常用字段、外键字段补索引,但别盲目加——复合索引顺序必须匹配查询条件顺序
识别中间件和信号里的隐藏耗时
Django 中间件和模型信号(如 post_save)容易被当成“轻量逻辑”,但一旦在里面做 HTTP 调用、同步写文件、或调用未缓存的复杂函数,延迟就会悄悄累积。
排查方法很直接:
- 临时注释掉自定义中间件,在
MIDDLEWARE配置里逐个禁用,观察响应时间变化 - 在关键信号回调开头加
import time; start = time.time(),结尾打日志,确认是否真在信号里卡住 - 特别警惕
pre_save里调用外部 API、或post_delete里同步清理大量关联数据——这些该移到 Celery 异步任务里
确认是否是 Gunicorn/Uvicorn 进程配置不当
有时候所有 Python 层代码都正常,但整体吞吐下降、平均延迟升高,问题其实在 WSGI/ASGI 服务器配置上。
常见坑点:
-
gunicorn --workers设得太少(比如单核机器配 4 个 sync worker),CPU 没跑满但请求排队;设太多又导致内存溢出、上下文切换开销上升 - 用
geventworker 时没改--worker-connections,或没 patch 标准库(漏掉gevent.monkey.patch_all()),结果协程没真正并发 - Uvicorn 的
--workers对 ASGI 应用意义不大,应该优先调--workers 1+--http 1.1或--http h11,再通过反向代理(如 Nginx)做负载分发
延迟不是线性叠加的,某个环节多花 50ms,可能让整条链路的 P95 延迟翻倍。尤其是数据库锁等待、Redis 连接池耗尽、或 DNS 解析阻塞这类底层问题,日志里往往只显示“超时”,得靠 strace 或 tcpdump 往下挖。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











