"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Noções básicas sobre tarefas, corretores, trabalhadores e back-ends no Celery

Noções básicas sobre tarefas, corretores, trabalhadores e back-ends no Celery

Publicado em 30/07/2024
Navegar:502

Understanding tasks, brokers, workers, and backends in Celery

O aipo pode ser difícil de aprender. Embora sua documentação seja abrangente, ela tende a ignorar o básico.

Esta postagem definirá quatro dos principais conceitos do Celery, discutirá a relação entre o Celery e o Kombu e usará alguns exemplos de código para ilustrar como o Celery pode ser útil em aplicações reais. Os exemplos usarão o framework web Django e seu decorador @shared_task, mas os conceitos também são aplicáveis ​​a Flask, FastAPI e outros.

Tarefas, corretores, trabalhadores e back-ends

Você terá dificuldade em encontrar um lugar na documentação atual do Celery que descreva claramente o que ele considera um corretor ou backend, mas com pesquisa suficiente você pode encontrar e inferir definições.

Abaixo estão os conceitos que você deve saber antes de começar a usar o Celery.

Tarefa

Uma tarefa é algum trabalho que o Celery executará de forma assíncrona (neste contexto, essa é uma palavra chique para "não imediatamente"). Em um aplicativo da web, uma tarefa pode ser enviar um email depois que um usuário envia um formulário. Enviar um e-mail pode ser uma operação de vários segundos, e forçar um usuário a esperar o envio de um e-mail antes de redirecionar pode fazer com que o aplicativo pareça lento.

As tarefas são definidas usando decoradores no Celery. Abaixo, usamos o decorador @shared_task para transformar send_thank_you_email() em uma tarefa do Celery que pode ser usada no manipulador de envio de formulário submit_feedback().

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})

Quando uma tarefa é definida usando um decorador no Celery, ele adiciona um método delay() à tarefa. Você pode ver a tarefa send_thank_you_email chamando o método delay() no exemplo acima após o formulário ser salvo com sucesso. Quando delay() é chamado, ele enviará a tarefa send_thank_you_email e seus dados para o broker onde está armazenado e posteriormente será executado por um worker, momento em que o usuário irá ser enviado por e-mail.

O benefício de enviar o trabalho para o Celery se torna mais óbvio se você precisar enviar e-mails adicionais após salvar o formulário. Por exemplo, você pode enviar um e-mail à equipe de suporte ao cliente informando que eles receberam novos comentários. Com o Celery, isso quase não acrescenta tempo adicional à resposta.

As tarefas do Celery também permitem configurações avançadas adicionais. Caso um e-mail não seja enviado, você pode codificar sua tarefa para tentar novamente automaticamente e definir configurações como max_retries, retry_backoff, retry_jitter, etc.

Corretor

O glossário de propostas de aprimoramento do aipo tem o seguinte a dizer sobre Message Brokers:

Enterprise Integration Patterns define um Message Broker como um bloco de construção arquitetônico que pode receber mensagens de vários destinos, determinar o destino correto e rotear a mensagem para o canal correto.

Para nossos propósitos com o Celery, consideraremos um broker um "transporte de mensagens" onde as tarefas criadas são armazenadas. Na verdade, os corretores não executam a tarefa: esse é o trabalho de um trabalhador. Em vez disso, os corretores são o local onde as tarefas agendadas são armazenadas quando uma tarefa é agendada e retiradas de quando um trabalhador eventualmente executa uma tarefa. Um corretor é um componente obrigatório para que o Celery funcione, e o Celery se conectará a exatamente um corretor.

A página Backends e Brokers do Celery lista alguns de seus corretores suportados, e há outros corretores experimentais que ele suporta e que não estão listados (como SQLAlchemy). Esses corretores (ou "transportes de mensagens") são gerenciados por uma biblioteca Python mantida pelo Celery para transportes de mensagens chamada Kombu. Ao procurar informações sobre como configurar corretores, às vezes é útil consultar a documentação do Kombu em vez da do Celery.

Alguns corretores possuem recursos avançados como distribuição e prioridade de tarefas, enquanto outros operam como filas simples.

Trabalhador

Um worker é uma instância do Celery que extrai tarefas do corretor e executa as funções de tarefa definidas em seu aplicativo Python. O Celery é capaz de executar código Python em seus trabalhadores porque o próprio Celery é escrito em Python.

Muitos trabalhadores podem correr simultaneamente para executar tarefas. Quando você executa o comando celery trabalhador, ele irá ativar um trabalhador para cada núcleo do seu computador por padrão. Se o seu computador tiver 16 núcleos, a execução do celery trabalhador iniciará 16 trabalhadores.

Se nenhum trabalhador estiver em execução, as mensagens (tarefas) serão acumuladas no corretor até que os trabalhadores estejam disponíveis para executá-las.

Processo interno

A página de tarefas no Guia do usuário do Celery tem o seguinte a dizer sobre backends:

Se você deseja acompanhar as tarefas ou precisar dos valores de retorno, o Celery deve armazenar ou enviar os estados para algum lugar para que possam ser recuperados posteriormente. Existem vários back-ends de resultados integrados para escolher: SQLAlchemy/Django ORM, Memcached, RabbitMQ/QPid (rpc) e Redis – ou você pode definir o seu próprio.

TLDR: um backend rastreia os resultados e os resultados retornados de tarefas assíncronas. O que isso realmente significa e quando poderia ser útil?

Imagine que você está construindo um aplicativo de contabilidade em Django que pode gerar um relatório anual. O relatório pode levar alguns minutos para ser gerado.

Para oferecer aos seus usuários uma experiência mais responsiva, você usa uma solicitação AJAX para iniciar uma tarefa de geração de relatório. Essa solicitação retorna um ID da tarefa, que pode ser usado para pesquisar o servidor a cada poucos segundos para ver se o relatório foi gerado. Assim que a tarefa for concluída, ela retornará o ID do relatório, que o cliente pode usar para exibir um link para o relatório via JavaScript.

Podemos implementar isso com Celery e Django usando o seguinte código:

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})

Neste exemplo, o ID do ativo retornado por generate_report_task() é armazenado em um backend. O back-end armazena o resultado e o resultado retornado. O backend não armazena o status das tarefas ainda a serem processadas: elas só serão adicionadas quando houver um resultado. Uma tarefa que retorna "PENDENTE" tem um status completamente desconhecido: uma tarefa associada pode nem existir. As tarefas normalmente retornarão "SUCESSO" ou "FALHA", mas você pode ver todos os status nos documentos de status do Celery.

Não é necessário ter um back-end para o Celery executar tarefas. No entanto, é necessário se você precisar verificar o resultado de uma tarefa ou retornar o resultado de uma tarefa. Se você tentar verificar o status de uma tarefa quando o Celery não tiver um back-end configurado, uma exceção será gerada.


Espero que esta postagem ajude você a entender as peças individuais do aipo e por que você pode considerar usá-lo. Embora a documentação oficial seja um desafio para entender, aprender profundamente o Celery pode desbloquear novas possibilidades em seus aplicativos Python.

Declaração de lançamento Este artigo foi reproduzido em: https://dev.to/tylerlwsmith/defining-tasks-brokers-workers-and-backends-in-celery-1982?1 Se houver alguma violação, entre em contato com [email protected] para excluir isto
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3