Django - 如何在 celery 和 redis 中使用异步任务队列

Posted

技术标签:

【中文标题】Django - 如何在 celery 和 redis 中使用异步任务队列【英文标题】:Django - How to use asynchronous task queue with celery and redis 【发布时间】:2015-11-14 13:47:54 【问题描述】:
#In my views.py file
pi1 = None
pis1 = None
def my_func():
    #Essentially this function sets a random integer to pi1 and pis1
    global pi1, pis1
    pi1 = randint(0,9)
    pis1 = randint(0,9)
    return        

def index(request):

    my_func()

    context = 
        "pi1" : pi1,
        "pis1" : pis1,
    

    return render(request, "index.html", context)

#In the index.html file
<h1> pi1 </h1>
<h1> pis1 </h1>

为了简单起见,我删除了很多代码,但这就是它的要点。尽管我为 my_func 发布了代码,但它是一个耗时的函数,它会导致 index.html 在被访问时加载一段时间。如何使用 celery 和 redis 在后台运行 my_func 以便 index.html 加载更快?

我已阅读 celery 文档,但我仍然无法设置 celery 和 redis。谢谢。

【问题讨论】:

这样:context = "pi1" : pi1, "pis1" : pis1, 工作吗? 一切正常,只是速度很慢。 【参考方案1】:

如前所述,您可能不需要芹菜。这是从案例 2 派生的示例:https://zapier.com/blog/async-celery-example-why-and-how/。它完全适合我:

from time import sleep
import json
from django.http import HttpResponse
from django.shortcuts import render

def main_view(request):
    return render(request, 'index.html')

def ajax_view(request):
    sleep(10) #This is whatever work you need
    pi1 = "This is pi1" #I just made pi1/pis1 random values
    pis1 = "This is pis1"
    context = 
        "pi1" : pi1,
        "pis1" : pis1,
    
    data = json.dumps(context)

    return HttpResponse(data, content_type='application/json')

我的 index.html 包含:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Main View</title>
    <script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
    <script>
    $(document).ready(function()
        $.ajax(
            url: "/test_ajax/",
        ).done(function( data) 
            $("#pi1").text(data.pi1);
            $("#pis1").text(data.pis1); 
        );
    );
</script>
  </head>
  <body>
      <h1 id = "pi1">Loading</h1>
      <h1 id = "pis1">Loading</h1>
  </body>
</html>

我的 urls.py 包含:

from django.conf.urls import include, url
from django.contrib import admin
from testDjango.test import main_view, ajax_view

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^test/', main_view),
    url(r'^test_ajax/', ajax_view)
]

当我访问 localhost:8000/test/ 时会发生什么我立即看到:

大约 10 秒后,我看到了:

这个想法是您立即返回您的页面并使用 jquery 在完成时获取操作结果并相应地更新您的页面。您可以添加更多内容,例如进度条/加载图像等。例如,您可以在后台对pi1pis 进行处理,并在完成后将其加载到 HTML 中。

【讨论】:

谢谢你的想法,但你能解释一下javascript部分吗?我不明白你在那里做什么。 另外,在阅读了您链接的页面后,我的印象是这不会更快地加载我的页面,但它只会让我在页面上添加一个加载栏。 让我们为此添加一些数字。如果您的 pi1pis1 需要大约 10 秒的时间来计算。您必须在某个时间点花费 10 秒的时间来计算。除非您已经有缓存值,否则您无法真正避免这种情况。从我展示的链接中,如果你不使用任何异步的东西,用户必须提前等待这 10 秒。当他们看到一个空白页面时,他们必须等待 10 秒。 async 的作用是让您显示某些内容,并在用户等待 10 秒时将页面控制权交还给用户。这意味着不再有空白页,这使它变得更好。 Celery 不会让你避免等待这 10 秒,而不是使用这样的东西。芹菜的好处来自于你需要做很多工作的时候。如果你只是偶尔需要一件东西,那真的不需要。无论如何,在我的示例中,javascript 所做的是,当页面加载时,它使用 AJAX 发送请求以获取 pis 和 pi1s` 的信息,然后用 @ 的值填充

s 987654335@ 和 pis1 在你进行了 10 秒的计算之后。这样,用户将获得他们想要的信息,而无需一直看着空白屏幕。

JSON 是一种数据格式。它不是特定于javascript的。我把它放到 JSON 中,因为它相当容易阅读并且是可移植的。 jQuery 是一个方便的 javascript 包。它有一个名为.ajax 的函数,这是我用过的。您可以在这里阅读有关 ajax 的基本概念:learn.jquery.com/ajax【参考方案2】:

这里不需要芹菜。您可以使用 AJAX 请求在页面上加载这些值。您应该创建一个单独的视图来计算这些值,并在加载 index.html 后使用 javascript 调用它。

【讨论】:

我很困惑,你能给我举个例子吗?谢谢。

以上是关于Django - 如何在 celery 和 redis 中使用异步任务队列的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django 中使用 Celery 上传和处理大型 excel 文件?

如何使用 Django 配置 Celery 守护进程

如何在 Django 中运行和查看 celery 任务?

如何在任务中获取芹菜结果模型(使用 django-celery-results)

Django - 如何在 celery 和 redis 中使用异步任务队列

django + celery - 如何在我的 django 应用程序中为 celery 设置 crontab 计划?