如何在Django视图函数中使用async/await并实现请求串行执行?
Django 让视图执行完毕前不处理其他请求的实现方案
你改成异步视图没用的核心原因是:Django异步视图只是允许内部执行异步IO操作,本身依然会并发处理多个请求。你要的是同一时间只有一个请求能运行核心的结果生成逻辑,得靠加锁实现互斥。
分场景解决方案
1. 单进程部署(开发环境或单worker生产环境)
用Python自带的线程锁,保证同一进程内所有请求串行执行核心逻辑:
import threading from django.shortcuts import render # 全局锁,所有请求共用 result_process_lock = threading.Lock() def orderresult(request): if request.method == 'POST': username = request.POST["username"] order = request.POST["order"] # 加锁:这段代码同一时间只有一个请求能进入 with result_process_lock: doubleResult = ResultsFormView(order, username).resultview() result = doubleResult[0] boolresult = doubleResult[1] context = { "result": result, "boolresult": boolresult } return render(request, 'npages/result.html', context=context)
2. 多进程部署(生产环境多worker,比如Gunicorn多实例)
线程锁只在单个进程内生效,多进程得用跨进程的分布式锁,比如Redis锁:
先安装依赖:
pip install redis
然后编写代码:
import redis import time from django.shortcuts import render # 连接你的Redis服务 redis_client = redis.Redis(host='localhost', port=6379, db=0) def orderresult(request): if request.method == 'POST': username = request.POST["username"] order = request.POST["order"] # 自定义锁名,确保唯一 lock_key = "order_result_exclusive_lock" # 循环尝试获取锁,超时时间设为你的逻辑最长耗时(这里设5分钟) while not redis_client.set(lock_key, "processing", nx=True, ex=300): time.sleep(0.1) try: # 核心逻辑,同一时间只有一个进程能执行 doubleResult = ResultsFormView(order, username).resultview() result = doubleResult[0] boolresult = doubleResult[1] finally: # 不管成功失败都释放锁 redis_client.delete(lock_key) context = { "result": result, "boolresult": boolresult } return render(request, 'npages/result.html', context=context)
3. 异步视图适配
如果你的resultview()本身是异步函数,异步视图里加锁可以这么写:
import threading from django.shortcuts import render result_lock = threading.Lock() async def orderresult(request): if request.method == 'POST': username = request.POST["username"] order = request.POST["order"] with result_lock: doubleResult = await ResultsFormView(order, username).resultview() result = doubleResult[0] boolresult = doubleResult[1] context = { "result": result, "boolresult": boolresult } return render(request, 'npages/result.html', context=context)
不推荐的极端方案
直接把服务器worker数设为1,强制所有请求串行处理,但这会把服务性能压到极低,除非你的业务量特别小,否则别用。
内容的提问来源于stack exchange,提问作者brokenelfo
相关产品推荐
相关产品推荐

