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

Django应用性能优化:阻塞与非阻塞实现问题排查

Django应用AB负载测试问题排查与优化

问题描述

使用Apache Benchmark(ab)对Django应用做负载测试时,并发提升至50出现错误:apr_socket_recv: Connection reset by peer (54);且20并发下,基于ASGI+Daphne的异步实现吞吐量与WSGI阻塞实现持平,未达预期性能提升。

应用包含两种实现:

  • 阻塞方案:基于默认WSGI开发服务器,使用requests库发起同步请求调用外部API
  • 异步方案:基于ASGI+Daphne服务器,在异步视图中使用aiohttp调用外部API
    两种实现均需向外部API端点发送POST请求并返回响应。

负载测试命令:

ab -c 50 -n 600 -s 800007 -T application/json "http://127.0.0.1:8001/test"

阻塞实现代码

from rest_framework.decorators import api_view
import requests as requests
from rest_framework.response import Response

@api_view(['GET'])
def index(request):
    res = make_api_request("http://{host}/v1/completions")
    print("blocking response is ---->", res)
    return Response(res, status=200)

def make_api_request(url, method="POST", headers=None, params=None, json_data=None, timeout=None):
    try:
        json_data =  {'prompt': 'Hi, How are you?', 'max_new_tokens': 700, 'temperature': 0.1, 'top_p': 1, 'max_tokens': 700, 'model': 'meta-llama/Llama-2-7b-chat-hf'}

        response = requests.request(method, url, headers=headers, params=params, json=json_data, timeout=timeout)
        return response
    except requests.exceptions.Timeout as e:
        raise TimeoutError(f"Request timed out. The server did not respond within the specified timeout period.")
    except requests.exceptions.RequestException as e:
        raise ConnectionError(f"Request error: {str(e)}")
    except Exception as e:
        raise Exception(f"Exception error: {str(e)}")

异步实现代码

import asyncio
import aiohttp
import logging
from rest_framework.response import Response
from adrf.decorators import api_view
import json

logger = logging.getLogger(__name__)

@api_view(['GET'])
async def index(request):
    res = await make_api_request("http://{{host}}/v1/completions")
    logger.info("res is ----> %s", res)
    return Response(res, status=200)

async def make_api_request(url, method="POST", headers=None, params=None, json_data=None, timeout=None):
    try:
        json_data =  {'prompt': 'Hi, How are you?', 'max_new_tokens': 700, 'temperature': 0.1, 'top_p': 1, 'max_tokens': 700, 'model': 'meta-llama/Llama-2-7b-chat-hf'}

        async with aiohttp.ClientSession() as session:
            async with session.request(method, url, headers=headers, params=params, json=json_data,
                                       timeout=timeout, ssl=False) as response:
                content = await response.read()
                if 'json' in response.headers.get('Content-Type', ''):
                    content = json.loads(content)
                return content
    except asyncio.TimeoutError:
        raise TimeoutError("Request timed out. The server did not respond within the specified timeout period.")
    except aiohttp.ClientError as e:
        raise ConnectionError(f"Request error: {str(e)}")
    except Exception as e:
        raise Exception(f"Exception error: {str(e)}")

一、apr_socket_recv: Connection reset by peer (54)错误原因

  • 服务器资源耗尽:并发50时,Django服务器或外部API的连接数、进程/线程池被耗尽,触发主动连接重置
  • 外部API限流:被调用的LLaMA API存在并发连接限制,超过阈值后主动断开连接
  • 超时配置不匹配:尽管ab设置了超长超时,但Django或外部API的内部超时更短,导致连接被提前重置
  • 系统资源限制:操作系统文件描述符上限过低,无法支撑大量并发连接,触发内核层面的连接重置

二、异步方案性能未达预期的核心原因

  • 异步资源复用缺失:每次请求都创建新的aiohttp.ClientSession,频繁的会话创建销毁抵消了异步IO的性能优势
  • 外部API成为瓶颈:无论同步还是异步实现,最终都依赖外部LLaMA API的响应速度,若外部API本身处理缓慢,异步无法突破该瓶颈
  • ASGI服务器配置不足:Daphne默认配置未充分利用异步特性,如worker数量、并发连接数设置不合理
  • 低并发下同步优势:WSGI开发服务器在20并发下有足够的进程/线程处理请求,外部API的响应时间掩盖了同步阻塞的劣势

三、高负载性能优化方案

通用优化(同步/异步均适用)

  • 提升系统资源限制:临时调整Linux文件描述符上限:ulimit -n 65535,修改/etc/security/limits.conf实现永久生效
  • 外部API优化:
    • 扩展LLaMA服务实例数,提升其并发处理能力
    • 对相同prompt的请求启用缓存,直接返回缓存结果
  • Django基础优化:
    • 禁用DEBUG模式(生产环境强制要求),减少不必要的日志和调试检查
    • 使用Redis等缓存框架,缓存视图响应或外部API返回数据

异步实现专属优化

  1. 复用aiohttp.ClientSession:全局初始化一个会话实例,避免每次请求重复创建,修改示例:
# 模块级别初始化ClientSession
import aiohttp
session = aiohttp.ClientSession()

async def make_api_request(url, method="POST", headers=None, params=None, json_data=None, timeout=None):
    try:
        json_data = {'prompt': 'Hi, How are you?', 'max_new_tokens': 700, 'temperature': 0.1, 'top_p': 1, 'max_tokens': 700, 'model': 'meta-llama/Llama-2-7b-chat-hf'}
        async with session.request(method, url, headers=headers, params=params, json=json_data, timeout=timeout, ssl=False) as response:
            content = await response.read()
            if 'json' in response.headers.get('Content-Type', ''):
                content = json.loads(content)
            return content
    # 异常处理逻辑保持不变

注意:需通过Django信号在应用关闭时调用await session.close()释放资源。

  1. 优化Daphne配置:

    • 启动时增加worker数量:daphne -p 8001 --workers 4 myproject.asgi:application
    • 调整--http-timeout等参数,匹配外部API的响应时间
  2. 全链路异步化:确保异步视图中无同步阻塞操作,避免混合调用同步ORM、同步第三方库等代码

四、负载测试策略调整

  • 分步梯度测试:从10、20并发逐步提升至50、100,观察每个并发级别下的错误率和吞吐量,定位性能阈值
  • 增加监控维度:测试时监控服务器CPU、内存、网络连接数、文件描述符使用情况,以及外部API的响应时间和错误率
  • 替换测试工具:ab对异步支持有限,改用wrk或locust进行更精准的异步负载测试,示例wrk命令:
wrk -t4 -c50 -d30s -s post.lua http://127.0.0.1:8001/test

(post.lua为包含POST请求体的自定义脚本)

  • 合理设置超时:ab的-s参数应设置为外部API最大响应时间+缓冲时间,避免超时误判

内容的提问来源于stack exchange,提问作者D.Sunil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 17:28:11