【问题标题】:Django Asyncronous task running syncronously with asgirefDjango 异步任务与 asgiref 同步运行
【发布时间】:2021-10-28 17:40:36
【问题描述】:

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

主要观点

在此视图中,我会收到通知。我设置了 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)

次要视图

收到通知后,我调用辅助视图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 代码将在 主线程。

欢迎提供任何线索。提前致谢。

【问题讨论】:

    标签: django asynchronous


    【解决方案1】:

    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.x 及更高版本并创建 asgi.py 文件。见How to generate asgi.py for existent project?

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

    【讨论】:

    • 谢谢@aaron 刚刚能够授予奖励。最好的!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-07
    • 2021-10-20
    • 2010-10-25
    • 2018-09-12
    • 2023-03-19
    相关资源
    最近更新 更多