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

Django服务压力测试异常:超4000请求后随机Socket超时求助

嘿,我来帮你一步步揪出这个问题的根源!从你描述的现象——单条请求正常,但批量跑到4000条左右就变慢甚至Socket超时——来看,大概率是资源泄漏或者请求堆积搞的鬼,咱们从代码到运行环境逐一排查:

先修复代码里的低级bug(别让小问题干扰排查)

先看你的服务端handle函数,有两个明显的错误,先改掉:

  1. 判断了"vid" in request.GET,但后面却取了request.GET["id"],这明显是笔误,应该取vid;
  2. 解码title后又用原请求值覆盖了,会导致中文乱码(虽然这可能不是性能问题,但先修正避免其他干扰)。

修正后的代码:

def handle(request) :
    sys.stderr.write( "[info]request come in {} \n".format(sys._getframe().f_code.co_name))
    ret_dict = dict()
    ret_str = ""
    if ("vid" in request.GET) and ("title" in request.GET):
        # 修正:取vid而非id
        vid = request.GET["vid"]
        # 保留解码后的title,不要覆盖
        title = urllib.parse.unquote(request.GET["title"], encoding='utf-8')
        req_video = {"vid": vid, "title": title}
        tags = handle_function(req_video)
        ret_dict["vid"] = vid
        ret_dict["tags"] = tags
        ret_str = json.dumps(ret_dict)
    return HttpResponse(ret_str)

核心排查方向:资源泄漏

批量请求到一定量出问题,最常见的就是资源没释放,越积越多,导致服务崩溃:

  • 数据库连接泄漏:如果handle_function里用到了数据库,检查是否每次请求后都关闭了连接,或者连接池配置不合理(比如最大连接数不够)。可以用数据库自带的工具看连接数变化——比如PostgreSQL用ps aux | grep postgres,如果连接数随着请求持续上涨不回落,那就是泄漏了。
  • 文件句柄泄漏:用lsof -p <你的Django进程PID>查看进程打开的文件/网络句柄数量,每处理一批请求后看数值是不是一直涨。如果超过系统限制(用ulimit -n查看),会导致无法创建新Socket,直接触发超时。
  • 外部请求未设超时:如果handle_function调用了外部API,一定要加超时时间!比如用requests.get(url, timeout=5),不然外部服务偶尔响应慢,请求会一直挂着占用Django工作进程,导致后续请求排队,越拖越慢最后超时。

检查Django的运行模式(别用开发服务器跑批量请求!)

如果你是用python manage.py runserver启动的Django,这是开发专用服务器,默认单进程单线程(或低并发配置),批量请求很容易被阻塞导致请求堆积。生产/压测环境必须用Gunicorn、uWSGI这类WSGI服务器,配置足够的进程和线程:
比如用Gunicorn启动(根据服务器CPU核心数调整,一般workers设为CPU核心数*2+1):

gunicorn --workers 4 --threads 2 your_project.wsgi:application

监控请求处理细节,定位瓶颈

给handle函数加日志,记录每个请求的处理时间,看看从第4000条开始是不是处理时间突然飙升:

import time

def handle(request) :
    start_time = time.time()
    sys.stderr.write( "[info]request come in {} \n".format(sys._getframe().f_code.co_name))
    ret_dict = dict()
    ret_str = ""
    vid = ""  # 提前定义避免日志报错
    if ("vid" in request.GET) and ("title" in request.GET):
        vid = request.GET["vid"]
        title = urllib.parse.unquote(request.GET["title"], encoding='utf-8')
        req_video = {"vid": vid, "title": title}
        tags = handle_function(req_video)
        ret_dict["vid"] = vid
        ret_dict["tags"] = tags
        ret_str = json.dumps(ret_dict)
    # 记录单请求处理时间
    process_time = time.time() - start_time
    sys.stderr.write(f"[info]vid:{vid} 处理耗时 {process_time:.2f}s\n")
    return HttpResponse(ret_str)

同时用top/htop监控Django进程的CPU、内存占用——如果处理到4000条后CPU跑满或内存飙升,那就是资源耗尽导致的超时。

排查客户端连接问题

客户端是顺序发送请求,检查get_rec_mingqiang函数里的连接是否正确关闭:
比如用requests的话,最好用Session复用连接,或者确保每次请求后释放连接:

def get_rec_mingqiang(server_ip_mq, server_port_mq, web_page_mq, page_params_mq):
    url = f"http://{server_ip_mq}:{server_port_mq}{web_page_mq}"
    # 用with语句自动关闭会话,避免连接泄漏
    with requests.Session() as s:
        # 给客户端请求也加超时,避免一直等服务器响应
        response = s.get(url, params=page_params_mq, timeout=10)
        response.raise_for_status()
        return response.json()

如果客户端没正确关闭连接,服务器端会有大量TIME_WAIT状态的连接,占满端口。可以用netstat -an | grep TIME_WAIT查看,如果数量很多,可调整系统TCP参数(比如echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse)。

单独压测handle_function

既然单条请求没问题,批量出问题,那handle_function可能有累积性性能问题(比如内存泄漏、缓存缺失)。单独写个脚本压测它:

import time
import tracemalloc

# 导入你的handle_function
from your_module import handle_function

tracemalloc.start()
start_time = time.time()

# 模拟批量调用
with open('test_data', 'r') as f:
    for line in f:
        line = line.rstrip('\n')
        fields = line.split("\t")
        vid = fields[0]
        title = fields[1]
        req_video = {"vid": vid, "title": title}
        tags = handle_function(req_video)

end_time = time.time()
current, peak = tracemalloc.get_traced_memory()
tracemalloc.stop()

print(f"总耗时: {end_time - start_time:.2f}s")
print(f"峰值内存: {peak / 1024 / 1024:.2f}MB")

如果这个测试里时间越来越长,或内存持续上涨,那问题就出在handle_function里——比如内部有全局变量累积数据、数据库查询没加索引、没释放临时资源等,针对性优化即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:58:18