如何在Django(Daphne作为ASGI服务器)中异步并行运行任务?
解决Django+Daphne下异步任务并行的问题
你的asyncio.gather写法本身是正确的,出现请求挂起被杀死的问题,大概率是以下原因导致,对应解决方式如下:
1. 确保异步函数无未处理的同步阻塞代码
如果foo1/foo2/foo3内部包含同步阻塞操作(比如未用@sync_to_async包裹的ORM查询、本地文件IO、第三方同步SDK调用),会直接阻塞整个事件循环,导致请求超时被Daphne终止。
解决:所有同步代码必须用Django提供的@sync_to_async装饰,处理数据库操作时还需注意关闭旧连接:
from django.db import close_old_connections from asgiref.sync import sync_to_async # 封装适配数据库操作的同步转异步装饰器 def sync_to_async_db(func): @sync_to_async(thread_sensitive=True, executor="threadpool") def wrapper(*args, **kwargs): try: return func(*args, **kwargs) finally: close_old_connections() return wrapper # 示例:将同步ORM查询转为异步 @sync_to_async_db def fetch_model_data(param): from myapp.models import TargetModel return TargetModel.objects.filter(condition=param).values_list('field', flat=True) # 确保foo类函数是纯异步逻辑,或正确包裹同步操作 async def foo1(p1): db_data = await fetch_model_data(p1) # 其他异步处理逻辑 return db_data
2. 调整Daphne的请求超时参数
如果三个并行任务确实需要较长时间执行,Daphne默认的超时限制会杀死未完成的连接。启动Daphne时可以手动指定超时时间:
daphne --timeout 60 myproject.asgi:application
将60替换为你需要的超时秒数(如120、300)。
3. 确认异步视图的规范写法
确保你的API视图本身是异步视图,且正确调用并行任务:
from django.http import JsonResponse import asyncio async def my_api_view(request): p1 = request.GET.get('p1') p2 = request.GET.get('p2') p3 = request.GET.get('p3') r1, r2, r3 = await service_of_mine(p1, p2, p3) return JsonResponse({'r1': r1, 'r2': r2, 'r3': r3}) async def service_of_mine(p1, p2, p3): # 正确的并行执行写法 return await asyncio.gather(foo1(p1), foo2(p2), foo3(p3))
4. 避免手动创建事件循环
如果代码中手动创建了新的事件循环(如asyncio.new_event_loop()),会和Daphne管理的全局事件循环冲突,导致任务无法正常调度。必须使用当前线程的默认事件循环,直接用await asyncio.gather(...)即可,不要手动创建或切换循环。
内容的提问来源于stack exchange,提问作者gabriel119435
相关产品推荐
相关产品推荐

