本文记录了一次 Django 接口性能排查过程,从 ORM 优化入手,最终发现真正瓶颈是 StreamingHttpResponse 对字符串的逐字符迭代,仅用一对方括号将响应时间从 13.6 秒降至 1.7 秒。
📝 详细摘要
文章详细复盘了某直播业务监控系统接口 get_svr_info 的性能优化过程。该接口在外部模块扩容后出现严重抖动,返回全量数据时响应体约 7MB,耗时 13.6 秒。作者最初判断瓶颈是 Django ORM 的 model 对象构造与 dict 转换开销,将代码改为 values() 直出 dict 并裁剪字段,但仅获得 1.12 倍提升。随后尝试 ujson 替换 json.dumps(1.23x)和 nginx gzip 压缩(反而更慢),均未解决根本问题。通过 TTFB 分析和本机回环测试,发现 TTFB 仅 1 秒而 Total 长达 13 秒,说明瓶颈不在数据生成而在数据输出。最终定位到真凶:StreamingHttpResponse(json.dumps(big_data)) 将完整字符串作为可迭代对象,导致 Django 逐字符输出约 700 万次。修复方案是将字符串包裹在列表中(或直接使用 HttpResponse),使输出变为一次完成。最终全量场景从 13.6 秒降至 1.7 秒,最大提升 8.21 倍。文章总结了 TTFB 作为性能排查关键指标的价值,以及老代码中「看起来没错」的隐藏陷阱。
💡 主要观点
- StreamingHttpResponse 接收字符串时会逐字符迭代,导致巨大性能开销。 Python 字符串是可迭代对象,StreamingHttpResponse(big_string) 会将 7MB JSON 拆成约 700 万个单字符 chunk 逐个输出,造成 12 秒的额外耗时。
💬 文章金句
- 在掌握数据之前就下结论,是最大的错误。
- 这不是流式输出,这是把一个大字符串交给 Django,让 Django 按字符串的迭代规则逐字符输出。
- 性能问题不能靠资历投票,也不能靠直觉结案。
- 拍胸脯之前,先跑 curl -w。
📊 文章信息
AI 初评:89
来源:腾讯云开发者
作者:腾讯云开发者
分类:软件编程
语言:中文
阅读时间:24 分钟
字数:5779
标签: 后端开发, Django, 性能优化, Python, Web 开发