Início Rápido: Criar um fluxo de trabalho sem servidor usando Durable Functions

Neste início rápido, você usará as ferramentas de linha de comando do Desenvolvedor do Azure para criar um fluxo de trabalho sem servidor que orquestra várias tarefas em execução em paralelo. Você cria recursos no Azure, verifica o código localmente e, em seguida, o implanta em um novo aplicativo de funções sem servidor no Azure Functions, executado em um plano Flex Consumption.

O projeto usa a CLI do Desenvolvedor do Azure (azd) para simplificar a implantação do código no Azure. Essa implantação segue as práticas recomendadas atuais para implantações de Azure Functions seguras e escalonáveis. Este guia rápido demonstra o padrão fan-out/fan-in no Durable Functions, uma extensão que orquestra fluxos de trabalho com execução durável. O exemplo utiliza o Durable Task Scheduler, um backend totalmente gerenciado para Durable Functions que substitui o backend do Armazenamento do Azure. O exemplo busca títulos de artigos em paralelo — a orquestração se ramifica para várias atividades executadas simultaneamente e, em seguida, se reintegra para agregar os resultados.

Por padrão, o plano de Consumo Flexível segue um modelo de cobrança pague pelo que usar, o que significa que a conclusão deste início rápido gera um pequeno custo de alguns centavos de dólar ou menos na sua conta do Azure.

Pré-requisitos

Inicializar o projeto

Use o azd init comando para criar um projeto de código local do Durable Functions a partir de um modelo.

  1. No seu terminal ou prompt de comando local, execute esse azd init comando em uma pasta vazia:

    azd init --template durable-functions-quickstart-dotnet-azd -e dfquickstart-dotnet
    

    Esse comando extrai os arquivos de projeto do repositório template e inicializa o projeto em uma nova pasta. O sinalizador -e define um nome para o ambiente atual. Em azd, o ambiente mantém um contexto de implantação exclusivo para seu aplicativo e você pode definir mais de um. O nome do ambiente também é usado no nome do grupo de recursos que você cria no Azure.

  2. Mude para o diretório do projeto e depois navegue até a fanoutfanin pasta do app:

    cd durable-functions-quickstart-dotnet-azd/fanoutfanin
    
  1. No seu terminal ou prompt de comando local, execute esse azd init comando em uma pasta vazia:

    azd init --template durable-functions-quickstart-python-azd -e dfquickstart-python
    

    Esse comando extrai os arquivos de projeto do repositório template e inicializa o projeto em uma nova pasta. O sinalizador -e define um nome para o ambiente atual. Em azd, o ambiente mantém um contexto de implantação exclusivo para seu aplicativo e você pode definir mais de um. O nome do ambiente também é usado no nome do grupo de recursos que você cria no Azure.

  2. Mude para o diretório do projeto e depois navegue até a src pasta do app:

    cd durable-functions-quickstart-python-azd/src
    
  1. No seu terminal ou prompt de comando local, execute esse azd init comando em uma pasta vazia:

    azd init --template durable-functions-quickstart-typescript-azd -e dfquickstart-typescript
    

    Esse comando extrai os arquivos de projeto do repositório template e inicializa o projeto em uma nova pasta. O sinalizador -e define um nome para o ambiente atual. Em azd, o ambiente mantém um contexto de implantação exclusivo para seu aplicativo e você pode definir mais de um. O nome do ambiente também é usado no nome do grupo de recursos que você cria no Azure.

  2. Mude para o diretório do projeto e depois navegue até a src pasta do app:

    cd durable-functions-quickstart-typescript-azd/src
    
  1. No seu terminal ou prompt de comando local, execute esse azd init comando em uma pasta vazia:

    azd init --template durable-functions-quickstart-java-azd -e dfquickstart-java
    

    Esse comando extrai os arquivos de projeto do repositório template e inicializa o projeto em uma nova pasta. O sinalizador -e define um nome para o ambiente atual. Em azd, o ambiente mantém um contexto de implantação exclusivo para seu aplicativo e você pode definir mais de um. O nome do ambiente também é usado no nome do grupo de recursos que você cria no Azure.

  2. Mudar para o diretório do projeto:

    cd durable-functions-quickstart-java-azd
    
  1. No seu terminal ou prompt de comando local, execute esse azd init comando em uma pasta vazia:

    azd init --template durable-functions-quickstart-javascript-azd -e dfquickstart-javascript
    

    Esse comando extrai os arquivos de projeto do repositório template e inicializa o projeto em uma nova pasta. O sinalizador -e define um nome para o ambiente atual. Em azd, o ambiente mantém um contexto de implantação exclusivo para seu aplicativo e você pode definir mais de um. O nome do ambiente também é usado no nome do grupo de recursos que você cria no Azure.

  2. Mude para o diretório do projeto e depois navegue até a src pasta do app:

    cd durable-functions-quickstart-javascript-azd/src
    
  1. No seu terminal ou prompt de comando local, execute esse azd init comando em uma pasta vazia:

    azd init --template durable-functions-quickstart-powershell-azd -e dfquickstart-powershell
    

    Esse comando extrai os arquivos de projeto do repositório template e inicializa o projeto em uma nova pasta. O sinalizador -e define um nome para o ambiente atual. Em azd, o ambiente mantém um contexto de implantação exclusivo para seu aplicativo e você pode definir mais de um. O nome do ambiente também é usado no nome do grupo de recursos que você cria no Azure.

  2. Mude para o diretório do projeto e depois navegue até a src pasta do app:

    cd durable-functions-quickstart-powershell-azd/src
    

Provisionar recursos do Azure

Este projeto usa o azd provision comando para criar os recursos necessários do Azure, incluindo um novo aplicativo de funções em um plano Flex Consumption, um Agendador de Tarefas Durável e um hub de tarefas.

Tip

O projeto inclui um conjunto de arquivos Bicep (na pasta infra ) que azd utiliza ​​para criar uma implantação segura em um plano de consumo Flex que segue as melhores práticas.

  1. Volte para a pasta raiz do projeto (a pasta que contém o azure.yaml arquivo):

    cd ..
    
  1. Certifique-se de que você ainda está na pasta raiz do projeto (a pasta que contém o azure.yaml arquivo).
  1. Execute este comando para autenticar com sua conta Azure:

    azd auth login
    
  2. Execute este comando da pasta raiz do projeto para azd criar os recursos necessários do Azure:

    azd provision
    

    A pasta raiz contém o arquivo de definição azure.yaml necessário para azd.

  3. Quando solicitado, forneça estes parâmetros de implantação necessários:

    Parâmetro Description
    assinatura do Azure Assinatura na qual seus recursos serão criados. Se sua conta tiver mais de um inquilino, você deve primeiro escolher seu inquilino.
    Localização do Azure Região do Azure na qual criar o grupo de recursos que contém os novos recursos do Azure. Somente as regiões que atualmente dão suporte ao plano de consumo flex são mostradas.
    vnetEnabled Se deve ser implantado em uma rede virtual. Para este início rápido, selecione false.

    O azd provision comando usa suas respostas a esses prompts com os arquivos de configuração do Bicep para criar e configurar esses recursos necessários do Azure:

    • Plano de Consumo Flexível e aplicativo de funções
    • Armazenamento do Azure (obrigatório) e Application Insights (recomendado)
    • Agendador de Tarefas Duráveis e hub de tarefas
    • Políticas de acesso e funções para sua conta
    • Conexões de serviço a serviço usando identidades gerenciadas (em vez de cadeias de conexão armazenadas)

    Após o comando ser concluído com sucesso, você verá links para os recursos que criou.

    O provisionamento também executa um script pós-provisionamento que gera um arquivo local.settings.json na pasta do seu aplicativo. Este arquivo contém as configurações de conexão para o endpoint Durable Task Scheduler implantado, que você precisa para rodar o projeto localmente.

Iniciar o Azurite

Para rodar o projeto localmente, o runtime das Funções precisa de um emulador de armazenamento local. A "AzureWebJobsStorage": "UseDevelopmentStorage=true" configuração no arquivo local.settings.json direciona o tempo de execução para usar o Azurite para esse propósito.

Em uma nova janela de terminal, execute este comando para iniciar o Azurite:

azurite --skipApiVersionCheck --location ~/azurite-data

Mantenha o Azurite rodando nessa janela de terminal enquanto testamos localmente.

Executar no seu ambiente local

  1. No seu terminal original, vá até a pasta do app fanoutfanin e inicie o host do Functions:

    cd fanoutfanin
    func start
    

    Quando o host do Functions é iniciado na pasta do projeto local, ele grava os pontos de extremidade de URL locais das suas funções acionadas pelo HTTP na saída do terminal.

    Note

    Como a autorização da chave de acesso não é imposta ao ser executada localmente, você não precisa de uma chave de acesso para chamar sua função.

  2. No navegador, faça uma solicitação GET para o endpoint que inicia a orquestração.

    http://localhost:7071/api/FetchOrchestration_HttpStart

    Essa solicitação inicia uma nova instância de orquestração. A orquestração se expande para várias atividades a fim de buscar, em paralelo, os títulos dos artigos do Microsoft Learn. Quando as atividades terminam, a orquestração retorna e exibe os títulos como uma cadeia de caracteres formatada.

  1. No seu terminal original, vá até a src pasta do app, crie e ative um ambiente virtual, instale dependências e inicie o host Functions:

    cd src
    

    A forma como você cria e ativa seu ambiente virtual (chamado .venv) depende do seu terminal:

    python3 -m venv .venv
    source .venv/bin/activate
    pip install -r requirements.txt
    func start
    

    Quando o host do Functions é iniciado na pasta do projeto local, ele grava os pontos de extremidade de URL locais das suas funções acionadas pelo HTTP na saída do terminal.

    Note

    Como a autorização da chave de acesso não é imposta ao ser executada localmente, você não precisa de uma chave de acesso para chamar sua função.

  2. No navegador, envie uma requisição GET para o endpoint de início HTTP.

    http://localhost:7071/api/orchestrators/fetch_orchestration

    Essa solicitação inicia uma nova instância de orquestração. A orquestração se expande para várias atividades a fim de buscar, em paralelo, os títulos dos artigos do Microsoft Learn. Quando as atividades terminam, a orquestração retorna e exibe os títulos como uma cadeia de caracteres formatada.

  1. No seu terminal original, vá até a src pasta do app, instale dependências, construa o projeto e inicie o host Functions:

    cd src
    npm install
    npm run build
    func start
    

    Quando o host do Functions é iniciado na pasta do projeto local, ele grava os pontos de extremidade de URL locais das suas funções acionadas pelo HTTP na saída do terminal.

    Note

    Como a autorização da chave de acesso não é imposta ao ser executada localmente, você não precisa de uma chave de acesso para chamar sua função.

  2. No navegador, envie uma requisição GET para o endpoint de início HTTP.

    http://localhost:7071/api/orchestrators/fetchOrchestration

    Essa solicitação inicia uma nova instância de orquestração. A orquestração se expande para várias atividades a fim de buscar, em paralelo, os títulos dos artigos do Microsoft Learn. Quando as atividades terminam, a orquestração retorna e exibe os títulos como uma cadeia de caracteres formatada.

  1. No seu terminal original, construa o projeto e então inicie o host Functions a partir da pasta de saída da build:

    mvn clean package
    cd target/azure-functions/durable-functions-quickstart
    func start
    

    Quando o host do Functions é iniciado na pasta do projeto local, ele grava os pontos de extremidade de URL locais das suas funções acionadas pelo HTTP na saída do terminal.

    Note

    Como a autorização da chave de acesso não é imposta ao ser executada localmente, você não precisa de uma chave de acesso para chamar sua função.

  2. No navegador, faça uma solicitação GET para o endpoint que inicia a orquestração.

    http://localhost:7071/api/FetchOrchestration_HttpStart

    Essa solicitação inicia uma nova instância de orquestração. A orquestração se expande para várias atividades a fim de buscar, em paralelo, os títulos dos artigos do Microsoft Learn. Quando as atividades terminam, a orquestração retorna e exibe os títulos como uma cadeia de caracteres formatada.

  1. No seu terminal original, vá até a src pasta do app, instale dependências e inicie o host de Funções:

    cd src
    npm install
    func start
    

    Quando o host do Functions é iniciado na pasta do projeto local, ele grava os pontos de extremidade de URL locais das suas funções acionadas pelo HTTP na saída do terminal.

    Note

    Como a autorização da chave de acesso não é imposta ao ser executada localmente, você não precisa de uma chave de acesso para chamar sua função.

  2. No navegador, faça uma solicitação GET para o endpoint que inicia a orquestração.

    http://localhost:7071/api/FetchOrchestration_HttpStart

    Essa solicitação inicia uma nova instância de orquestração. A orquestração se expande para várias atividades a fim de buscar, em paralelo, os títulos dos artigos do Microsoft Learn. Quando as atividades terminam, a orquestração retorna e exibe os títulos como uma cadeia de caracteres formatada.

  1. No seu terminal original, vá até a pasta do app src e inicie o host do Functions:

    cd src
    func start
    

    Quando o host do Functions é iniciado na pasta do projeto local, ele grava os pontos de extremidade de URL locais das suas funções acionadas pelo HTTP na saída do terminal.

    Note

    Como a autorização da chave de acesso não é imposta ao ser executada localmente, você não precisa de uma chave de acesso para chamar sua função.

  2. No navegador, faça uma solicitação GET para o endpoint que inicia a orquestração.

    http://localhost:7071/api/FetchOrchestration_HttpStart

    Essa solicitação inicia uma nova instância de orquestração. A orquestração se expande para várias atividades a fim de buscar, em paralelo, os títulos dos artigos do Microsoft Learn. Quando as atividades terminam, a orquestração retorna e exibe os títulos como uma cadeia de caracteres formatada.

  1. O endpoint HTTP retorna uma resposta JSON com várias URLs. O statusQueryGetUri endpoint fornece o estado de orquestração.

  2. Copie o valor statusQueryGetUri e cole-o no navegador ou na ferramenta de teste HTTP para verificar o status da orquestração. Quando a orquestração for concluída, você verá os títulos de artigo buscados na resposta.

  3. Quando terminar, pressione Ctrl+C na janela do terminal para interromper o processo do host func.

  1. Execute deactivate para desligar o ambiente virtual.

Examinar o código (opcional)

Você pode examinar o código que implementa o padrão fan-out/fan-in:

As atividades de busca de título são controladas usando uma lista de tarefas dinâmicas. A linha await Task.WhenAll(parallelTasks); aguarda a conclusão de todas as atividades chamadas, que são executadas simultaneamente. Quando terminar, todas as saídas serão agregadas como uma cadeia de caracteres formatada.

[Function(nameof(FetchOrchestration))]
public static async Task<string> RunOrchestrator(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    ILogger logger = context.CreateReplaySafeLogger(nameof(FetchOrchestration));
    logger.LogInformation("Fetching data.");
    var parallelTasks = new List<Task<string>>();
    
    // List of URLs to fetch titles from
    var urls = new List<string>
    {
        "https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview",
        "https://learn.microsoft.com/azure/azure-functions/durable/durable-task-scheduler/durable-task-scheduler",
        "https://learn.microsoft.com/azure/azure-functions/functions-scenarios",
        "https://learn.microsoft.com/azure/azure-functions/functions-create-ai-enabled-apps",
    };

    // Run fetching tasks in parallel
    foreach (var url in urls)
    {
        Task<string> task = context.CallActivityAsync<string>(nameof(FetchTitleAsync), url);
        parallelTasks.Add(task);
    }
    
    // Wait for all the parallel tasks to complete before continuing
    await Task.WhenAll(parallelTasks);
   
    // Return fetched titles as a formatted string
    return string.Join("; ", parallelTasks.Select(t => t.Result));
}

Você pode examinar o projeto de modelo completo a.

As atividades de busca de título são controladas usando uma lista de tarefas dinâmicas. A linha yield context.task_all(tasks) aguarda a conclusão de todas as atividades chamadas, que são executadas simultaneamente. Quando terminar, todas as saídas serão agregadas como uma cadeia de caracteres formatada.

    # List of URLs to fetch titles from
    urls = [
        "https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview",
        "https://learn.microsoft.com/azure/azure-functions/durable/durable-task-scheduler/durable-task-scheduler",
        "https://learn.microsoft.com/azure/azure-functions/functions-scenarios",
        "https://learn.microsoft.com/azure/azure-functions/functions-create-ai-enabled-apps",
    ]
    
    # Run fetching tasks in parallel
    tasks = []
    for url in urls:
        task = context.call_activity("fetch_title", url)
        tasks.append(task)
    
    # Wait for all the parallel tasks to complete before continuing
    results = yield context.task_all(tasks)
    
    # Return fetched titles as a formatted string
    return "; ".join(results)


@myApp.activity_trigger(input_name="url")
async def fetch_title(url: str):
    """Activity function that fetches the title from a URL."""
    logger = logging.getLogger("FetchTitle")
    logger.info(f"Fetching from url {url}.")
    
    try:
        async with ClientSession() as session:

Você pode examinar o projeto de modelo completo a.

As atividades de busca de título são controladas usando uma lista de tarefas dinâmicas. A linha yield context.df.Task.all(parallelTasks) aguarda a conclusão de todas as atividades chamadas, que são executadas simultaneamente. Quando terminar, todas as saídas serão agregadas como uma cadeia de caracteres formatada.

    const urls = [
        "https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview",
        "https://learn.microsoft.com/azure/azure-functions/durable/durable-task-scheduler/durable-task-scheduler",
        "https://learn.microsoft.com/azure/azure-functions/functions-scenarios",
        "https://learn.microsoft.com/azure/azure-functions/functions-create-ai-enabled-apps",
    ];

    // Run fetching tasks in parallel
    const parallelTasks = [];
    for (const url of urls) {
        const task = context.df.callActivity(fetchTitleActivityName, url);
        parallelTasks.push(task);
    }

    // Wait for all the parallel tasks to complete before continuing
    const results: string[] = yield context.df.Task.all(parallelTasks);

    // Return fetched titles as a formatted string
    return results.join("; ");
};
df.app.orchestration("fetchOrchestration", fetchOrchestration);

const fetchTitleAsync: ActivityHandler = async function (
    url: string,
    context: InvocationContext

Você pode examinar o projeto de modelo completo a.

As atividades de busca de título são controladas usando uma lista de tarefas dinâmicas. A linha ctx.allOf(parallelTasks).await() aguarda a conclusão de todas as atividades chamadas, que são executadas simultaneamente. Quando terminar, todas as saídas serão agregadas como uma cadeia de caracteres formatada.

@FunctionName("FetchOrchestration")
public String runOrchestrator(
        @DurableOrchestrationTrigger(name = "taskOrchestrationContext") TaskOrchestrationContext ctx) {

    List<String> urls = List.of(
        "https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview",
        "https://learn.microsoft.com/azure/azure-functions/durable/durable-task-scheduler/durable-task-scheduler",
        "https://learn.microsoft.com/azure/azure-functions/functions-scenarios",
        "https://learn.microsoft.com/azure/azure-functions/functions-create-ai-enabled-apps"
    );

    // Fan out: run fetching tasks in parallel
    List<Task<String>> parallelTasks = urls.stream()
        .map(url -> ctx.callActivity("FetchTitle", url, String.class))
        .collect(Collectors.toList());

    // Fan in: wait for all parallel tasks to complete
    List<String> results = ctx.allOf(parallelTasks).await();

    // Return fetched titles as a formatted string
    return String.join("; ", results);
}

Você pode examinar o projeto de modelo completo a.

As atividades de busca de título são controladas usando uma lista de tarefas dinâmicas. A linha yield context.df.Task.all(parallelTasks) aguarda a conclusão de todas as atividades chamadas, que são executadas simultaneamente. Quando terminar, todas as saídas serão agregadas como uma cadeia de caracteres formatada.

df.app.orchestration('fetchOrchestration', function* (context) {
    context.log("Fetching data.");

    const urls = [
        "https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview",
        "https://learn.microsoft.com/azure/azure-functions/durable/durable-task-scheduler/durable-task-scheduler",
        "https://learn.microsoft.com/azure/azure-functions/functions-scenarios",
        "https://learn.microsoft.com/azure/azure-functions/functions-create-ai-enabled-apps",
    ];

    // Fan out: run fetching tasks in parallel
    const parallelTasks = urls.map(url => context.df.callActivity(activityName, url));

    // Fan in: wait for all parallel tasks to complete
    const results = yield context.df.Task.all(parallelTasks);

    // Return fetched titles as a formatted string
    return results.join("; ");
});

Você pode examinar o projeto de modelo completo a.

As atividades de busca de título são controladas usando uma lista de tarefas dinâmicas. A linha Wait-ActivityFunction -Task $parallelTasks aguarda a conclusão de todas as atividades chamadas, que são executadas simultaneamente. Quando terminar, todas as saídas serão agregadas como uma cadeia de caracteres formatada.

param($Context)

$urls = @(
    "https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview",
    "https://learn.microsoft.com/azure/azure-functions/durable/durable-task-scheduler/durable-task-scheduler",
    "https://learn.microsoft.com/azure/azure-functions/functions-scenarios",
    "https://learn.microsoft.com/azure/azure-functions/functions-create-ai-enabled-apps"
)

# Fan out: run fetching tasks in parallel
$parallelTasks = @()
foreach ($url in $urls) {
    $parallelTasks += Invoke-DurableActivity -FunctionName 'FetchTitle' -Input $url -NoWait
}

# Fan in: wait for all parallel tasks to complete
$results = Wait-ActivityFunction -Task $parallelTasks

# Return fetched titles as a formatted string
$output = $results -join "; "
$output

Você pode examinar o projeto de modelo completo a.

Depois de verificar suas funções localmente, é hora de implantá-las no Azure.

Publicar no Azure

Execute este comando da pasta raiz do projeto para implantar seu projeto de código no aplicativo de funções no Azure:

azd deploy

O azd deploy comando empacota e implanta seu código no aplicativo de função criado durante o provisionamento. Após o comando ser concluído, o app inicia e roda no pacote implantado.

Invocar a função no Azure

Agora você pode invocar seu endereço de orquestração no Azure fazendo uma solicitação HTTP para o respectivo URL. Quando suas funções são executadas em Azure, a autorização de chave de acesso é imposta e você deve fornecer uma chave de acesso à função com sua solicitação.

Você pode usar as Ferramentas do Core para obter o ponto de extremidade de URL do gatilho HTTP que inicia a orquestração no Azure.

  1. No seu terminal ou prompt de comando local, execute estes comandos para obter os valores dos ponto de extremidades de URL:

    APP_NAME=$(azd env get-value AZURE_FUNCTION_NAME)
    func azure functionapp list-functions $APP_NAME --show-keys
    

    O comando azd env get-value obtém o nome do seu aplicativo de funções do ambiente local. Ao usar a opção --show-keys com func azure functionapp list-functions, o valor de URL de invocação retornado para cada ponto de extremidade inclui uma chave de acesso em nível de função.

  2. Use um navegador ou ferramenta de teste HTTP para fazer uma requisição GET no endpoint HTTP start para iniciar a orquestração no seu aplicativo de funções rodando no Azure.

Reimplantar seu código

Execute azd deploy quantas vezes precisar para implantar atualizações de código no seu app de funções. Se precisar atualizar os recursos do Azure, execute azd provision novamente.

Note

O pacote de implantação mais recente sempre substitui arquivos de código que já foram implantados.

Suas respostas iniciais aos prompts azd e quaisquer variáveis de ambiente geradas por azd são armazenadas localmente no seu ambiente nomeado. Use o comando azd env get-values para examinar todas as variáveis em seu ambiente usadas ao criar recursos Azure.

Limpar os recursos

Quando terminar de trabalhar com seu aplicativo de funções e recursos relacionados, use este comando para excluir o aplicativo de funções e seus recursos relacionados do Azure e evitar incorrer em custos adicionais:

azd down --no-prompt

Note

A opção --no-prompt instrui azd a excluir seu grupo de recursos sem uma confirmação sua.

Este comando não afeta seu projeto de código local.