Django异步任务与asgiref同步运行



我通过API在我的Django应用程序中收到通知,我应该在500毫秒之前返回HTTP 200。要实现这一点,我应该异步运行相关任务。我使用asgiref库,一切运行正常,但我认为实际上不是异步运行。

主要viev

在这个视图中,我接收通知。我设置了2个打印点来检查服务器日志中的时间。

@csrf_exempt
@api_view(('POST',))
@renderer_classes((TemplateHTMLRenderer, JSONRenderer))
def IncomingMeliNotifications(request):
print('--------------------------- Received ---------------------')
notificacion = json.loads(request.body)
call_resource = async_to_sync(CallResource(notificacion))
print('--------------------------- Answered ---------------------')
return Response({}, template_name='assessments.html', status=status.HTTP_200_OK)
<<p>

二级视图/strong>收到通知后,我调用二级视图CallResource,我希望它异步运行。

def CallResource(notificacion):
do things inside....
print('--------------------------- Secondary view ---------------------')
return 'ok'

当我检查日志时,我总是按照以下顺序得到打印:

print('--------------------------- Received ---------------------')
print('--------------------------- Secondary view ---------------------')
print('--------------------------- Answered ---------------------')

但我认为Secondary view应该是最后打印的,如:

print('--------------------------- Received ---------------------')
print('--------------------------- Answered ---------------------')
print('--------------------------- Secondary view ---------------------')

我在这里错过了什么?

我正在阅读文档github.com/django/asgiref,据我所知,这应该是我正在研究的范式:

如果程序的最外层是同步的,那么所有的都是异步的通过AsyncToSync运行的代码将在每个调用事件循环中运行任意子线程,而所有thread_sensitive代码将在主线程。

欢迎任何提示。提前谢谢。

async_to_sync允许同步线程停止并等待异步函数,而不是异步运行同步函数。

正在运行异步任务

  1. 既然你没有提到ASGI服务器,看起来你正在运行同步开发服务器python manage.py runserver.
    如果是这样,安装并运行Daphne(从Django)代替。
pip install daphne
daphne myproject.asgi:application

如果你使用的是Django 3。X及以上版本,在与wsgi.py文件相同的目录中应该已经有一个asgi.py文件。看到docs.djangoproject.com/en/3.2/howto/deployment/asgi/。

如果你使用的是Django 2。x及以下版本,升级到Django 3。并创建asgi.py文件。

  1. 可以在运行ASGI服务器时创建异步任务
# call_resource = async_to_sync(CallResource(notificacion))
loop = asyncio.get_event_loop()
task = loop.create_task(CallResource(notificacion))
  1. async函数应该用async def定义
# def CallResource(notificacion):
async def CallResource(notificacion):

最新更新