在使用 Apache Benchmark (ab) 对 Django 应用程序进行负载测试时,我遇到了意外错误(apr_socket_recv:连接由对等方重置 (54))。当我将负载增加到 50 个并发请求时,会出现此错误。令人惊讶的是,即使有 20 个并发请求,非阻塞也没有显着的性能提升(可以看到与阻塞相同的吞吐量)
该应用程序由两种实现组成:一种使用默认 WSGI 开发服务器的阻塞方法,另一种使用 ASGI 和 Daphne 服务器的非阻塞异步方法。阻塞实现依赖于 requests 库的同步请求,而非阻塞方法则在异步视图函数中利用 aiohttp。两种实现都旨在向外部 API 端点发出 POST 请求并返回响应。 尽管期望异步方法有更好的性能,但错误仍然存在并且性能仍然停滞不前。
我正在寻求深入了解此错误的根本原因以及提高重负载下性能的潜在解决方案。此外,任何有关优化异步实现的建议或更好的负载测试策略的建议将不胜感激 我使用 ab 作为基准测试工具。我用于基准测试的命令:
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):
# logger.info(f"is async: {iscoroutinefunction(index)}")
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)}")
runserver
开发服务器进行基准测试;它不适合重负载。如果您需要对 WSGI 应用程序进行基准测试,请使用例如gunicorn
或 uwsgi
来为应用程序提供服务。async
对每个请求的吞吐量没有太大帮助。async
具有异步 Web 服务器的代码确实意味着单个异步工作线程可以同时处理多个请求(当请求正在等待例如上述远程调用时)。