Recursos HTTP

As Durable Functions tem vários recursos que facilitam a incorporação de orquestrações duráveis e entidades em fluxos de trabalho HTTP. Este artigo apresenta detalhes sobre alguns desses recursos.

Expondo APIs HTTP

Orquestrações e entidades podem ser invocadas e gerenciadas usando solicitações HTTP. A extensão Durable Functions expõe as APIs HTTP internas. Ele também fornece APIs para interagir com orquestrações e entidades de dentro das funções disparadas por HTTP.

APIs HTTP internas

A extensão Durable Functions adiciona automaticamente um conjunto de APIs HTTP ao host do Azure Functions. Com essas APIs, você pode interagir com e gerenciar orquestrações e entidades sem escrever um código.

Há suporte para as APIs HTTP internas a seguir.

Consulte o Artigo APIs HTTP para obter uma descrição completa de todas as APIs HTTP internas expostas pela extensão Durable Functions.

Descoberta de URL na API HTTP

A Associação de cliente de orquestração expõe APIs que podem gerar conteúdos de resposta HTTP convenientes. Por exemplo, ela pode criar uma resposta que contém links para APIs de gerenciamento para uma instância de orquestração específica. Os exemplos a seguir mostram uma função disparada por HTTP que demonstra como usar essa API para uma nova instância de orquestração:

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;

namespace VSSample
{
    public static class HttpStart
    {
        [FunctionName("HttpStart")]
        public static async Task<HttpResponseMessage> Run(
            [HttpTrigger(AuthorizationLevel.Function, methods: "post", Route = "orchestrators/{functionName}")] HttpRequestMessage req,
            [DurableClient] IDurableClient starter,
            string functionName,
            ILogger log)
        {
            // Function input comes from the request content.
            object eventData = await req.Content.ReadAsAsync<object>();
            string instanceId = await starter.StartNewAsync(functionName, eventData);

            log.LogInformation($"Started orchestration with ID = '{instanceId}'.");

            return starter.CreateCheckStatusResponse(req, instanceId);
        }
    }
}

Iniciar uma função de orquestrador usando as funções disparadas por HTTP mostradas anteriormente pode ser feito usando qualquer cliente HTTP. O comando de ondulação a seguir inicia uma função de orquestrador chamada DoWork:

curl -X POST https://localhost:7071/orchestrators/DoWork -H "Content-Length: 0" -i

Em seguida, há um exemplo de resposta para uma orquestração que tem abc123 como sua ID. Alguns detalhes foram removidos para fins de clareza.

HTTP/1.1 202 Accepted
Content-Type: application/json; charset=utf-8
Location: http://localhost:7071/runtime/webhooks/durabletask/instances/abc123?code=XXX
Retry-After: 10

{
    "id": "abc123",
    "purgeHistoryDeleteUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123?code=XXX",
    "sendEventPostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123/raiseEvent/{eventName}?code=XXX",
    "statusQueryGetUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123?code=XXX",
    "terminatePostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123/terminate?reason={text}&code=XXX"
}

No exemplo anterior, cada um dos campos que termina em Uri corresponde a uma API HTTP interna. Você pode usar essas APIs para gerenciar a instância de orquestração de destino.

Observação

O formato das URLs de webhook depende de qual versão do host do Azure Functions você está executando. O exemplo anterior refere-se ao host do Azure Functions 2.0.

Para obter uma descrição de todas as APIs HTTP internas, consulte a Referência da API HTTP.

Acompanhamento de operação assíncrona

A resposta HTTP mencionada anteriormente foi criada para ajudar a implementar APIs assíncronas HTTP de execução longa com as Durable Functions. Às vezes, esse padrão é chamado de Padrão de consumidor de sondagem. O fluxo de cliente/servidor funciona da seguinte maneira:

  1. O cliente emite uma solicitação HTTP para iniciar um processo de execução prolongada, como uma função de orquestrador.
  2. O gatilho HTTP de destino devolve uma resposta HTTP 202 com um cabeçalho Localização que tem o valor "statusQueryGetUri".
  3. O cliente sonda a URL no cabeçalho Localização. O cliente continua vendo respostas de HTTP 202 com um cabeçalho Localização.
  4. Quando a instância é concluída ou falha, o ponto de extremidade no cabeçalho Localização devolve HTTP 200.

Este protocolo permite a coordenação de processos de execução prolongada com clientes ou serviços externos que podem sondar um ponto de extremidade HTTP e a seguir o cabeçalho Localização. As implementações de cliente e servidor desse padrão são incorporadas às APIs HTTP do Durable Functions.

Observação

Todas as ações baseadas em HTTP fornecidas pelos Aplicativos Lógicos do Azure dão suporte ao padrão de operação assíncrona padrão. Essa capacidade possibilita inserir uma função durável de execução longa como parte de um fluxo de trabalho dos Aplicativos Lógicos. Você pode saber mais detalhes sobre o suporte dos Aplicativos Lógicos a padrões de HTTP assíncronos na Documentação de ações e gatilhos de fluxo de trabalho dos Aplicativos Lógicos do Azure.

Observação

As interações com orquestrações podem ser feitas de todo tipo de função, não apenas de funções disparadas por HTTP.

Para obter mais informações sobre como gerenciar orquestrações e entidades usando APIs de cliente, consulte o Artigo gerenciamento de instâncias.

Consumindo APIs HTTP

Conforme descrito nas restrições de código da função de orquestrador, as funções de orquestrador não podem E/S diretamente. Em vez disso, normalmente chamam funções de atividade que fazem operações de E/S.

A partir do Durable Functions 2.0, as orquestrações podem consumir nativamente APIs HTTP usando a Associação de gatilho de orquestração.

O código de exemplo a seguir mostra uma função de orquestrador que faz uma solicitação HTTP de saída:

[FunctionName("CheckSiteAvailable")]
public static async Task CheckSiteAvailable(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    Uri url = context.GetInput<Uri>();

    // Makes an HTTP GET request to the specified endpoint
    DurableHttpResponse response = 
        await context.CallHttpAsync(HttpMethod.Get, url);

    if (response.StatusCode >= 400)
    {
        // handling of error codes goes here
    }
}

Ao usar a ação "chamar HTTP", você pode executar as seguintes ações em suas funções de orquestrador:

  • Chamar APIs HTTP diretamente de funções de orquestração, com algumas limitações que são mencionadas mais tarde.
  • Suporta automaticamente padrões de sondagem de status HTTP 202 do lado do cliente.
  • Usar Identidades gerenciadas do Azure para fazer chamadas HTTP autorizadas para outros pontos de extremidade do Azure.

A capacidade de consumir APIs HTTP diretamente de funções de orquestrador é destinada a ser uma conveniência para um determinado conjunto de cenários comuns. Você pode implementar todos esses recursos por conta própria usando funções de atividade. Em muitos casos, as funções de atividade podem oferecer mais flexibilidade.

Manipulação de HTTP 202

A API "chamar HTTP" pode implementar automaticamente o lado do cliente do padrão de consumidor de sondagem. Se uma API chamada devolver uma resposta HTTP 202 com um cabeçalho Localização, a função de orquestrador sondará automaticamente o recurso Localização até receber uma resposta diferente de 202. Essa resposta será a resposta devolvida ao código de função do orquestrador.

Observação

  1. As funções do Orchestrator também dão suporte nativo ao padrão de consumidor de sondagem no lado do servidor, conforme descrito em Acompanhamento de operação assíncrona. Esse suporte significa que as orquestrações em um aplicativo de funções podem coordenar facilmente as funções de orquestrador em outros aplicativos de funções. O que é semelhante ao conceito de suborquestração, mas com suporte para comunicação entre aplicativos. Esse suporte é particularmente útil para o desenvolvimento de aplicativos no estilo de microsserviço.
  2. Devido a uma limitação temporária, o padrão de sondagem HTTP interno não está disponível no momento em JavaScript/TypeScript e no Python.

Identidades gerenciadas

O Durable Functions é nativamente compatível com chamadas às APIs que aceitam tokens do Microsoft Entra para autorização. Esse suporte usa oIdentidades gerenciadas do Azure para adquirir esses tokens.

O código a seguir é um exemplo de uma função de orquestrador. A função faz chamadas autenticadas para reiniciar uma máquina virtual usando a máquinas virtuais API REST do Azure Resource Manager.

[FunctionName("RestartVm")]
public static async Task RunOrchestrator(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    string subscriptionId = "mySubId";
    string resourceGroup = "myRG";
    string vmName = "myVM";
    string apiVersion = "2019-03-01";
    
    // Automatically fetches an Azure AD token for resource = https://management.core.windows.net/.default
    // and attaches it to the outgoing Azure Resource Manager API call.
    var restartRequest = new DurableHttpRequest(
        HttpMethod.Post, 
        new Uri($"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachines/{vmName}/restart?api-version={apiVersion}"),
        tokenSource: new ManagedIdentityTokenSource("https://management.core.windows.net/.default"));
    DurableHttpResponse restartResponse = await context.CallHttpAsync(restartRequest);
    if (restartResponse.StatusCode != HttpStatusCode.OK)
    {
        throw new ArgumentException($"Failed to restart VM: {restartResponse.StatusCode}: {restartResponse.Content}");
    }
}

No exemplo anterior, o parâmetro tokenSource é configurado para adquirir tokens do Microsoft Entra para o Azure Resource Manager. Os tokens são identificados pelo URI do recurso https://management.core.windows.net/.default. O exemplo supõe que o aplicativo de funções atual está sendo executado localmente ou foi implantado como um aplicativo de funções com uma identidade gerenciada. É pressuposto que a identidade local ou a identidade gerenciada tem permissão para gerenciar VMs no grupo de recursos especificado myRG.

No runtime, a origem do token configurado devolve automaticamente um token de acesso OAuth 2.0. Em seguida, a origem adiciona o token como um token de portador ao cabeçalho Autorização da solicitação de saída. Esse modelo é uma melhoria em relação à adição manual de cabeçalhos de autorização a solicitações HTTP pelos seguintes motivos:

  • A atualização de token é manipulada automaticamente. Você não precisa se preocupar com os tokens expirados.
  • Os tokens nunca são armazenados no estado de orquestração durável.
  • Você não precisa escrever nenhum código para gerenciar a aquisição de token.

Você pode encontrar um exemplo mais completo no exemplo de RestartVMs C# pré-compilado.

As Identidades gerenciadas não estão limitadas ao gerenciamento de recursos do Azure. Você pode usar identidades gerenciadas para acessar qualquer API que aceite tokens de portador do Microsoft Entra, incluindo serviços do Azure da Microsoft e aplicativos web de parceiros. O aplicativo Web de um parceiro pode até ser outro aplicativo de funções. Para obter uma lista dos serviços do Azure da Microsoft que dão suporte à autenticação com o Microsoft Entra ID, confira Serviços do Azure que dão suporte à autenticação do Microsoft Entra.

Limitações

O suporte interno para chamar APIs HTTP é um recurso de conveniência. Não é apropriado para todos os cenários.

As solicitações HTTP enviadas por funções de orquestrador e as respectivas respostas são serializadas e persistentes como mensagens no provedor de armazenamento do Durable Functions. Esse comportamento de enfileiramento persistente garante que as chamadas HTTP sejam confiáveis e seguras para reprodução de orquestração. No entanto, o comportamento de enfileiramento persistente também tem limitações:

  • Cada solicitação HTTP envolve latência adicional quando comparada a um cliente HTTP nativo.
  • Dependendo do provedor de armazenamento configurado, mensagens de solicitação ou resposta grandes podem prejudicar significativamente o desempenho da orquestração. Por exemplo, ao usar o Armazenamento do Azure, os conteúdos HTTP que são grandes demais para caber nas mensagens da Fila do Azure são compactados e armazenados no Armazenamento de Blobs do Azure.
  • Não há suporte para conteúdos de streaming, em partes e binários.
  • A capacidade de personalizar o comportamento do cliente HTTP é limitada.

Se uma dessas limitações puder afetar seu caso de uso, considere usar funções de atividade e bibliotecas de cliente HTTP específicas de linguagem para fazer chamadas HTTP de saída.

Observação

Se você for um desenvolvedor do .NET, pode se perguntar por que esse recurso usa os tipos DurableHttpRequest e o DurableHttpResponse em vez dos tipos .NET HttpRequestMessage e HttpResponseMessage internos.

Essa opção de design é intencional. O principal motivo é que os tipos personalizados ajudam a garantir que os usuários não tirem conclusões incorretas sobre os comportamentos com suporte do cliente HTTP interno. Os tipos específicos para o Durable Functions também possibilitam a simplificação do design da API. Eles também podem disponibilizar mais facilmente recursos especiais disponíveis como integração de identidade gerenciada e o padrão de consumidor de sondagem.

Extensibilidade (somente .NET)

É possível personalizar o comportamento do cliente HTTP interno da orquestração usando a injeção de dependência .NET do Azure Functions. Essa capacidade pode ser útil para fazer pequenas alterações comportamentais. Ela também pode ser útil para o teste de unidade do cliente HTTP injetando objetos fictícios.

O exemplo a seguir demonstra como usar a injeção de dependência para desabilitar a validação de certificado TLS/SSL para funções de orquestrador que chamam pontos de extremidade HTTP externos.

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        // Register own factory
        builder.Services.AddSingleton<
            IDurableHttpMessageHandlerFactory,
            MyDurableHttpMessageHandlerFactory>();
    }
}

public class MyDurableHttpMessageHandlerFactory : IDurableHttpMessageHandlerFactory
{
    public HttpMessageHandler CreateHttpMessageHandler()
    {
        // Disable TLS/SSL certificate validation (not recommended in production!)
        return new HttpClientHandler
        {
            ServerCertificateCustomValidationCallback =
                HttpClientHandler.DangerousAcceptAnyServerCertificateValidator,
        };
    }
}

Próximas etapas