”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 了解 Celery 中的任务、代理、工作人员和后端

了解 Celery 中的任务、代理、工作人员和后端

发布于2024-07-30
浏览:711

Understanding tasks, brokers, workers, and backends in Celery

芹菜学习起来可能令人望而生畏。虽然它的文档很全面,但它倾向于跳过基础知识。

这篇文章将定义 Celery 中的四个主要概念,讨论 Celery 和 Kombu 之间的关系,并使用一些代码示例来说明 Celery 在实际应用程序中如何有用。这些示例将使用 Django Web 框架及其 @shared_task 装饰器,但这些概念也适用于 Flask、FastAPI 等。

任务、代理、工作人员和后端

您将很难在当前的 Celery 文档中找到一个位置来清楚地说明它所认为的经纪人后端,但是通过足够的挖掘,您可以找到和推断定义。

以下是开始使用 Celery 之前您应该了解的概念。

任务

A 任务是Celery将异步执行的一些工作(在这种情况下,这是“不立即”的一个奇特词)。在 Web 应用程序中,一项任务可能是在用户提交表单后发送电子邮件。发送电子邮件可能是一个需要多秒的操作,并且强制用户在重定向之前等待电子邮件发送可能会让应用程序感觉很慢。

任务是使用 Celery 中的装饰器定义的。下面我们使用 @shared_task 装饰器将 send_thank_you_email() 转换为可在 Submit_feedback() 表单提交处理程序中使用的 Celery 任务。

from config.celery import shared_task
from django.core.mail import send_mail
from django.shortcuts import render, redirect
from feedback.forms import FeedbackForm

@shared_task
def send_thank_you_email(email_address):
    send_mail(
        "Thank you for your feedback!",
        "We appreciate your input.",
        "[email protected]",
        [email_address],
    )

def submit_feedback(request):
    if request.method == "POST":
        form = FeedbackForm(request.POST)
        if form.is_valid():
            form.save()

            # Push the task to the broker using the delay() method.
            send_thank_you_email.delay(form.cleaned_data["email"])

            return redirect("/thank-you/")
    else:
        form = FeedbackForm()

    return render(request, "feedback.html", {"form": form})

当在 Celery 中使用装饰器定义任务时,它会向任务添加一个delay() 方法。您可以看到在成功保存表单后,send_thank_you_email 任务调用了上例中的delay() 方法。当delay()被调用时,它会将send_thank_you_email任务及其数据发送到存储它的broker,稍后将由worker执行,此时用户将通过电子邮件发送。

如果您在保存表单后需要发送额外的电子邮件,那么将工作推送到 Celery 的好处就变得更加明显。例如,您可能想向客户支持团队发送电子邮件,告知他们收到了新的反馈。对于 Celery,这几乎不会增加响应时间。

Celery 任务还允许额外的高级配置。如果电子邮件发送失败,您可以对任务进行编码以自动重试并配置 max_retries、retry_backoff、retry_jitter 等设置。

经纪人

Celery 增强提案的术语表对 消息代理有以下说法:

企业集成模式将消息代理定义为一个架构构建块,它可以从多个目的地接收消息,确定正确的目的地并将消息路由到正确的通道。

为了我们使用 Celery 的目的,我们将把 broker 视为存储创建的任务的“消息传输”。经纪人实际上并不执行任务:那是工人的工作。相反,代理是计划任务在计划任务时存储到,以及在工作人员最终执行任务时从拉出的地方。代理是 Celery 工作的必需的组件,Celery 将只连接到一个代理。

Celery 的后端和代理页面列出了一些其支持的代理,并且还有其支持但未列出的其他实验性代理(例如 SQLAlchemy)。这些代理(或“消息传输”)由 Celery 维护的 Python 消息传输库(称为 Kombu)管理。当寻找有关配置代理的信息时,查阅 Kombu 的文档而不是 Celery 的文档有时会很有帮助。

一些代理具有任务扇出和优先级等高级功能,而其他代理则作为简单队列运行。

工人

A worker 是 Celery 的一个实例,它从代理中提取任务并执行 Python 应用程序中定义的任务函数。 Celery 能够在其工作线程中运行 Python 代码,因为 Celery 本身是用 Python 编写的。

许多worker可以同时运行来执行任务。当您运行 celery worker 命令时,默认情况下它会为计算机的每个核心启动一个工作进程。如果你的电脑有16核,运行celeryworker将启动16个worker。

如果没有工作人员正在运行,消息(任务)将在代理中累积,直到工作人员可以执行它们。

后端

Celery 用户指南中的任务页面有以下关于 后端的内容

如果您想跟踪任务或需要返回值,那么 Celery 必须将状态存储或发送到某处,以便以后可以检索它们。有多种内置结果后端可供选择:SQLAlchemy/Django ORM、Memcached、RabbitMQ/QPid (rpc) 和 Redis – 或者您也可以定义自己的结果后端。

TLDR:后端跟踪异步任务的结果返回结果。这实际上意味着什么,什么时候有用?

假设您正在 Django 中构建一个可以生成年度报告的会计应用程序。该报告可能需要几分钟才能生成。

为了给您的用户提供响应更快的体验,您可以使用 AJAX 请求来启动报告生成任务。该请求返回任务的 ID,它可以使用该 ID 每隔几秒轮询一次服务器以查看是否生成了报告。任务完成后,它将返回报告的 ID,客户端可以使用该 ID 通过 JavaScript 显示报告的链接。

我们可以使用 Celery 和 Django 使用以下代码来实现这一点:

from celery import shared_task
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from accounting.models import Asset
from accounting.reports import AnnualReportGenerator

@shared_task
def generate_report_task(year):
    # This could take minutes...
    report = AnnualReportGenerator().generate(year)
    asset = Asset.objects.create(
        name=f"{year} annual report",
        url=report.url,
    )
    return asset.id

@require_http_methods(["POST"])
def generate_annual_report_view(request):
    year = request.POST.get("year")
    task = generate_report_task.delay(year)
    return JsonResponse({"taskId": task.id})

def get_annual_report_generation_status_view(request, task_id):
    task = generate_report_task.AsyncResult(task_id)

    # The status is typically "PENDING", "SUCCESS", or "FAILURE"
    status = task.status
    return JsonResponse({"status": status, "assetId": task.result})

在此示例中,generate_report_task()返回的资产ID存储在后端中。后端存储结果返回结果。后端存储尚未处理的任务的状态:只有在有结果后才会添加这些状态。返回“PENDING”的任务具有完全未知的状态:关联的任务甚至可能不存在。任务通常会返回“SUCCESS”或“FAILURE”,但您可以在 Celery 状态文档中查看所有状态。

Celery 运行任务不需要后端。 但是,如果您需要检查任务的结果或返回任务的结果,则需要后端。如果您在 Celery 未配置后端时尝试检查任务的状态,则会引发异常。


我希望这篇文章可以帮助您了解 Celery 的各个部分以及您可能考虑使用它的原因。虽然官方文档很难理解,但深入学习 Celery 可以在你的 Python 应用程序中释放新的可能性。

版本声明 本文转载于:https://dev.to/tylerlwsmith/defining-tasks-brokers-workers-and-backends-in-celery-1982?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何修复\“常规错误:2006 MySQL Server在插入数据时已经消失\”?
    如何修复\“常规错误:2006 MySQL Server在插入数据时已经消失\”?
    插入记录时如何解决“一般错误:2006 MySQL 服务器已消失”介绍:将数据插入 MySQL 数据库有时会导致错误“一般错误:2006 MySQL 服务器已消失”。当与服务器的连接丢失时会出现此错误,通常是由于 MySQL 配置中的两个变量之一所致。解决方案:解决此错误的关键是调整wait_tim...
    编程 发布于2025-02-06
  • 在网络开发中保持领先地位:最新新闻,工具和见解#49
    在网络开发中保持领先地位:最新新闻,工具和见解#49
    ?阅读! 创始人模式:一般假设:一家初创公司的管理正在向经理模式变化 - 经理模式 - 在商学院管理和教授的众所周知的方式。 Founder mode is less known and understood, but may be more effective. / start...
    编程 发布于2025-02-06
  • 如何使用PHP将斑点(图像)正确插入MySQL?
    如何使用PHP将斑点(图像)正确插入MySQL?
    在尝试将image存储在mysql数据库中时,您可能会遇到一个可能会遇到问题。本指南将提供成功存储您的图像数据的解决方案。 easudy values('$ this-> image_id','file_get_contents($ tmp_image)...
    编程 发布于2025-02-06
  • 我应该在使用块内明确关闭SQLConnection吗?
    我应该在使用块内明确关闭SQLConnection吗?
    答案在于使用关键字的行为。退出使用块时,在包含的对象上调用.dispose()方法。对于sqlConnection,.dispose()自动关闭连接并发布任何关联的资源。 ]使用cn作为new System.data.sqlclient.sqlConnection() CN.OPEN ...
    编程 发布于2025-02-06
  • 为什么Microsoft Visual C ++无法正确实现两台模板的实例?
    为什么Microsoft Visual C ++无法正确实现两台模板的实例?
    [2明确担心Microsoft Visual C(MSVC)在正确实现两相模板实例化方面努力努力。该机制的哪些具体方面无法按预期运行?背景:说明:的初始Syntax检查在范围中受到限制。它未能检查是否存在声明名称的存在,导致名称缺乏正确的声明时会导致编译问题。为了说明这一点,请考虑以下示例:一个符合...
    编程 发布于2025-02-06
  • 如何从Python中的字符串中删除表情符号:固定常见错误的初学者指南?
    如何从Python中的字符串中删除表情符号:固定常见错误的初学者指南?
    从python 导入编解码器 导入 text = codecs.decode('这狗\ u0001f602'.encode('utf-8'),'utf-8') 印刷(文字)#带有表情符号 emoji_pattern = re.compile(“ [”...
    编程 发布于2025-02-06
  • 在Sqlalchemy中过滤布尔值时,如何处理Flake8警告?
    在Sqlalchemy中过滤布尔值时,如何处理Flake8警告?
    避免使用sqlalchemy滤波器中布尔比较的flake8警告在使用sqlalchemy时,在过滤器条款中使用布尔比较通常是通常的。但是,Flake8在使用“ ==”操作员进行布尔比较时可能会引起警告。 sqlalchemy filter行为,但是,在sqlalchemy filter子句中,“ ...
    编程 发布于2025-02-06
  • 如何使用PHP从XML文件中有效地检索属性值?
    如何使用PHP从XML文件中有效地检索属性值?
    从php 您的目标可能是检索“ varnum”属性值,其中提取数据的传统方法可能会使您感到困惑。 - > attributes()为$ attributeName => $ attributeValue){ echo $ attributeName,'=“',$ at...
    编程 发布于2025-02-06
  • 如何限制动态大小的父元素中元素的滚动范围?
    如何限制动态大小的父元素中元素的滚动范围?
    在交互式界面中实现垂直滚动元素的CSS高度限制 考虑一个布局,其中我们具有与可滚动的映射div一起移动的subollable map div用户的垂直滚动,同时保持其与固定侧边栏的对齐方式。但是,地图的滚动无限期扩展,超过了视口的高度,阻止用户访问页面页脚。 可以限制地图的滚动,我们可以利用CSS...
    编程 发布于2025-02-06
  • 如何处理大于INT64大的十六进制字符串?
    如何处理大于INT64大的十六进制字符串?
    如何处理非常大的hexadecimal strings 考虑hexadecimal String 0x00000000d3c21bcecceda1000000。 进口 ( “编码/JSON” “ FMT” “数学/大” ) func main(){ 六边形:=“ ...
    编程 发布于2025-02-06
  • 如何在Java列表中有效计算元素的发生?
    如何在Java列表中有效计算元素的发生?
    计数列表中的元素出现在列表 中,在java编程中,列举列表中列举元素出现的任务来自列表。为此,收集框架提供了全面的工具套件。在这种情况下,Batocurrences变量将保持值3,代表动物列表中的“ BAT”出现的数量。 &&& [此方法是简单的,可以得出准确的结果,使其成为计算列表中元素出现的理...
    编程 发布于2025-02-06
  • 如何使用Delve在Visual Studio代码中调试代码?
    如何使用Delve在Visual Studio代码中调试代码?
    在Visual Studio代码中调试GO代码,并带有delve 在Visual Studio for Go开发中设置Delve Debugger,需要以下步骤:[设置环境变量go15vendorexperiment = 1。在.vscode文件夹中打开启动.json文件。通过单击editor(f...
    编程 发布于2025-02-06
  • PHP阵列键值异常:了解07和08的好奇情况
    PHP阵列键值异常:了解07和08的好奇情况
    PHP数组键值问题,使用07&08 在给定数月的数组中,键值07和08呈现令人困惑的行为时,就会出现一个不寻常的问题。运行print_r($月份)返回意外结果:键“ 07”丢失,而键“ 08”分配给了9月的值。此问题源于PHP对领先零的解释。当一个数字带有0(例如07或08)的前缀时,PHP将...
    编程 发布于2025-02-06
  • 您应该选择哪种MySQL数据类型:文本,斑点或clob?
    您应该选择哪种MySQL数据类型:文本,斑点或clob?
    在mysql中的数据存储选项:text vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs vs clob 文...
    编程 发布于2025-02-06
  • 为什么我的GO数据库/SQL查询要比直接Postgres PSQL查询要慢?
    为什么我的GO数据库/SQL查询要比直接Postgres PSQL查询要慢?
    使用数据库/sql的查询比直接查询数据库 QUERYing明显慢,尽管使用了相同的查询,但在执行A执行一个明显的性能差异使用Postgres的PSQL实用程序直接查询,并使用GO应用程序中的数据库/SQL软件包进行查询。这种差异在PSQL中毫无疑问的查询占GO中的数十毫秒。数据库/SQL初始化了一...
    编程 发布于2025-02-06

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3