Django并发模型

Django并发模型测试

测试场景,10线程测试100请求的并发性能。

压测代码:

import requests
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
from statistics import mean

URL = "http://127.0.0.1:8000/api/test/"
TOTAL_REQUESTS = 100      # 总请求数
THREADS = 10             # 线程数
TIMEOUT = 20             # 超时(秒)

session = requests.Session()

def request_once():
    start = time.perf_counter()
    try:
        r = session.get(URL, timeout=TIMEOUT)
        cost = time.perf_counter() - start
        return r.status_code, cost
    except Exception:
        return "ERROR", None

def main():
    results = []
    start_time = time.perf_counter()
    
    with ThreadPoolExecutor(max_workers=THREADS) as executor:
        futures = [executor.submit(request_once) for _ in range(TOTAL_REQUESTS)]
        for f in as_completed(futures):
            results.append(f.result())
    
    total_time = time.perf_counter() - start_time
    success = [r for r in results if r[0] == 200]
    failed = TOTAL_REQUESTS - len(success)
    latencies = [r[1] for r in success]
    
    print("====== 压测结果 ======")
    print(f"URL: {URL}")
    print(f"总请求数: {TOTAL_REQUESTS}")
    print(f"线程数: {THREADS}")
    print(f"成功请求: {len(success)}")
    print(f"失败请求: {failed}")
    print(f"总耗时: {total_time:.2f}s")
    print(f"QPS: {TOTAL_REQUESTS / total_time:.2f}")
    
    if latencies:
        print(f"平均响应时间: {mean(latencies)*1000:.2f} ms")
        print(f"最大响应时间: {max(latencies)*1000:.2f} ms")

if __name__ == "__main__":
    main()
    


测试结果


启动组合并发模型测试结果
runserver + time.sleep()Runserver为单进程+多线程的并发模型。未控制线程数量,有资源爆炸的风险。====== 压测结果 ====== URL: http://127.0.0.1:8000/api/test/ 总请求数: 100 线程数: 10 成功请求: 100 失败请求: 0 总耗时: 10.52s QPS: 9.51 平均响应时间: 1050.62 ms 最大响应时间: 1071.22 ms
gunicorn+time.sleep(10)单进程+单线程。gunicorn djangoproject1.wsgi:application --bind 0.0.0.0:8000 --workers 1 --threads 1完全阻塞。====== 压测结果 ====== URL: http://127.0.0.1:8000/api/test/ 总请求数: 100 线程数: 10 成功请求: 100 失败请求: 0 总耗时: 100.89s QPS: 0.99 平均响应时间: 9634.97 ms 最大响应时间: 10106.47 ms
gunicorn+time.sleep(1)多进程+多线程。测试并发能力=进程数量*线程数量 如果thread=1,则只有一个主线程处理HTTP请求。要注意的是,thread=1的时候每个进程中仍然可能有多个线程(日志线程等其他线程)。 测试命令:gunicorn djangoproject1.wsgi:application --bind 0.0.0.0:8000 --workers 2 --threads 2====== 压测结果 ====== URL: http://127.0.0.1:8000/api/test/ 总请求数: 100 线程数: 10 成功请求: 100 失败请求: 0 总耗时: 26.25s QPS: 3.81 平均响应时间: 2463.76 ms 最大响应时间: 3041.64 ms
gunicorn+time.sleep(1)+async def不会出现明显的性能差别,符合理论
uvicorn+time.sleep(1) + 同步试图相当于unicorn + worker=n +thread=1的并发模型。 测试命令:uvicorn djangoproject1.asgi:application --host 0.0.0.0 --port 8000 --workers 1Total Time : 101.12s QPS : 0.99 Success : 100 Failed : 0 Avg Latency : 10.010s P85 Latency : 10.124s P95 Latency : 11.125s Max Latency : 12.107s
uvicorn+await asyncio.sleep(1) + 异步试图结果是n个worker+单线程+多协程,性能显著增高。 风险:警惕阻塞(同步/cpu密集)+高并发带来的资源爆炸情况。 命令: uvicorn djangoproject1.asgi:application --host 0.0.0.0 --port 8000 --workers 1。====== 压测结果 ====== URL: http://127.0.0.1:8000/api/test/ 总请求数: 100 线程数: 10 成功请求: 100 失败请求: 0 总耗时: 10.65s QPS: 9.39 平均响应时间: 1061.49 ms 最大响应时间: 1093.43 ms
gunicorn+uvicorn worker + asyncio.sleep(1) + 异步试图URL: http://127.0.0.1:8000/api/test/ 总请求数: 100 线程数: 10 成功请求: 100 失败请求: 0 总耗时: 0.51s QPS: 196.92 平均响应时间: 49.05 ms 最大响应时间: 75.67 ms


文章标签:

评论(0)