You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

uWSGI部署Django应用时requests.post响应过慢问题排查

问题分析与解决方案

首先直接回应你的疑问:确实有可能和进程级资源竞争有关,但更常见的是requests的连接池在uWSGI多进程模型下的冲突,以及同步IO阻塞导致worker耗尽的问题。下面详细拆解原因和解决办法:

核心原因

1. requests连接池在fork后的状态冲突

requests底层依赖urllib3的连接池复用HTTP连接,而uWSGI的master=true+workers=16模式是先启动master进程、初始化部分资源后,再fork出16个worker进程。这会导致所有worker共享同一个连接池的初始状态,当多个worker同时发起请求时,会出现连接池资源竞争、连接状态异常,进而引发请求阻塞、超时。

而manage.py runserver是单进程(或默认多线程)模式,不存在fork后的资源共享问题,所以连接池能正常工作。

2. 同步IO阻塞导致worker耗尽

uWSGI默认是同步worker模式,每个worker同一时间只能处理一个请求。如果你的requests.post调用的外部接口响应较慢,16个worker很快都会被阻塞在等待外部接口返回的状态,后续请求只能排队等待空闲worker,最终表现为整个应用响应极慢。注释掉requests.post后,worker不再被阻塞,自然恢复正常。

针对性解决方案

方案1:重置/禁用requests连接池

避免worker共享连接池,每个请求使用独立的连接或重新初始化连接池:

import requests
from requests.adapters import HTTPAdapter

def call_external_api():
    # 为每个请求创建独立的Session和适配器
    session = requests.Session()
    # 限制连接池大小,或直接禁用复用
    adapter = HTTPAdapter(pool_connections=1, pool_maxsize=1)
    session.mount('http://', adapter)
    session.mount('https://', adapter)
    
    try:
        # 加上timeout避免无限等待
        response = session.post("https://your-external-api.com", timeout=10)
        response.raise_for_status()
        return response.json()
    finally:
        # 确保关闭会话,释放连接
        session.close()

或者更简单的方式,在请求时强制关闭连接:

requests.post("https://your-external-api.com", close=True)

方案2:改用异步请求(推荐)

使用异步HTTP客户端(如aiohttp)配合Django的异步视图,让worker不被阻塞,能同时处理更多请求:

  1. 先安装依赖:pip install aiohttp
  2. 修改Django视图为异步模式:
import aiohttp
from django.http import JsonResponse

async def your_view(request):
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://your-external-api.com",
            timeout=aiohttp.ClientTimeout(total=10)
        ) as response:
            data = await response.json()
            return JsonResponse(data)
  1. 确保Django配置文件中设置了ASGI应用:
# settings.py
ASGI_APPLICATION = "project.asgi.application"

方案3:调整uWSGI配置缓解阻塞

如果暂时无法修改代码,可以调整uWSGI配置增加并发能力:

[uwsgi]
env = DJANGO_SETTINGS_MODULE=project.settings
harakiri = 1200
max-requests = 5000
daemonize = ./backoffice.log
master = true
workers=16
# 启用线程,每个worker可处理多个请求
enable-threads=true
threads=4
# 启用DNS缓存,避免解析延迟
dns-cache=true
vacuum=true

这个方案只是缓解,不能从根本解决阻塞问题,适合临时过渡。

方案4:排查DNS解析问题

有时候uWSGI运行环境的DNS配置和开发环境不同,导致域名解析缓慢。可以尝试直接使用外部接口的IP地址发起请求,或者在uWSGI配置中开启DNS缓存(如上面的dns-cache=true)。

总结

优先尝试方案1或方案2,方案1改动小适合快速验证,方案2是长期优化的方向,能彻底解决同步阻塞带来的worker耗尽问题。

内容的提问来源于stack exchange,提问作者ave

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:28:23