Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
O Durable Functions é uma extensão do Azure Functions que oferece uma forma de executar funções com estado num ambiente de computação serverless. Numa aplicação de funções duráveis, pode usar uma função de orquestração para coordenar a execução de outras funções duráveis. As funções de orquestrador têm as seguintes características:
- Definem fluxos de trabalho funcionais utilizando código procedural. Não são necessários esquemas declarativos ou designers.
- Eles podem chamar outras funções duradouras de forma síncrona e assíncrona. A saída das funções chamadas pode ser guardada em variáveis locais.
- São desenhadas para serem duráveis e fiáveis. O progresso da execução é automaticamente guardado como ponto de controlo quando a função chama os operadores
awaitouyield. O estado local não se perde quando o processo é reciclado ou a máquina virtual reinicia. - Podem ser de longa duração. A vida útil total de uma instância de orquestração pode ser de segundos, dias ou meses, ou a instância pode ser configurada para nunca terminar.
Este artigo fornece uma visão geral das funções do orquestrador e como elas podem ajudá-lo a resolver vários desafios de desenvolvimento de aplicativos. Para informações sobre os tipos de funções disponíveis numa aplicação de Funções Duradouras, consulte Tipos e características de Funções Duradouras.
Identidade de orquestração
Cada instância de orquestração tem um identificador de instância, também conhecido como ID de instância. Por defeito, cada ID de instância é um identificador globalmente único (GUID) gerado automaticamente. No entanto, os IDs de instância também podem ser qualquer valor de cadeia de caracteres gerado pelo usuário. Cada ID de instância de orquestração deve ser exclusivo dentro de um hub de tarefas.
As seguintes regras aplicam-se aos IDs de instância:
- Devem ter entre 1 e 100 caracteres.
- Não devem começar com
@. - Não devem conter
/,\,#, ou?caracteres. - Não devem conter caracteres de controlo.
Observação
Geralmente recomendamos que utilize IDs de instância gerados automaticamente sempre que possível. Os IDs de instância gerados pelo utilizador destinam-se a cenários onde existe um mapeamento um-para-um entre uma instância de orquestração e uma entidade externa específica de uma aplicação, como uma ordem de compra ou um documento.
Além disso, a aplicação real das regras de restrição de caracteres pode variar consoante o fornecedor de armazenamento que a aplicação utiliza. Para ajudar a garantir o comportamento correto e a compatibilidade, recomendamos vivamente que siga as regras de ID de instância anteriores.
O ID da instância de uma orquestração é um parâmetro necessário para a maioria das operações de gerenciamento de instâncias. Os identificadores de instância também são importantes para os diagnósticos. Por exemplo, usa-os quando pesquisa dados de rastreamento de orquestração no Application Insights para resolução de problemas ou análise. Por esta razão, recomendamos que guarde os IDs de instância gerados numa localização externa que facilite a sua referência mais tarde. Exemplos de localizações incluem bases de dados ou registos de aplicações.
Reliability
As funções do orquestrador utilizam o padrão de event sourcing para ajudar a manter o seu estado de execução de forma fiável. Em vez de armazenar diretamente o estado atual de uma orquestração, o Durable Task Framework usa um armazenamento de acrescentar apenas para registrar toda a série de ações realizadas pela orquestração de funções. Um armazenamento apenas aditivo tem muitas vantagens em vez de exportar o estado de execução completo. Os benefícios incluem maior desempenho, escalabilidade e capacidade de resposta. Você também obtém a consistência eventual para dados transacionais e registos e histórico de auditoria completos. As pistas de auditoria apoiam ações compensatórias fiáveis.
O Durable Functions usa o fornecimento de eventos de forma transparente. Nos bastidores, uma função de orquestrador utiliza um await operador em C# e um yield operador em JavaScript e Python. Estes operadores devolvem o controle do thread orquestrador ao despachante do Durable Task Framework. Nas funções Java, não existe uma palavra-chave especial para a linguagem. Em vez disso, ao chamar .await() numa tarefa, devolve-se o controlo ao despachante através de uma instância personalizada de Throwable. O despachante então regista no armazenamento quaisquer novas ações agendadas pela função do orquestrador. Exemplos de ações incluem chamar uma ou mais funções filhas ou agendar um temporizador persistente. A ação de confirmação transparente atualiza o histórico de execução da instância de orquestração anexando todos os novos eventos ao armazenamento, de forma muito semelhante a um log somente de acréscimo. Da mesma forma, a ação de confirmação cria mensagens no armazenamento para agendar o trabalho real. Neste ponto, a função orchestrator pode ser descarregada da memória. Por padrão, o Durable Functions usa o Armazenamento do Azure como seu armazenamento de estado de tempo de execução, mas outros provedores de armazenamento também são suportados.
Quando uma função de orquestração recebe mais trabalho para fazer (por exemplo, uma mensagem de resposta é recebida ou um temporizador durável expira), o orquestrador acorda e reexecuta toda a função desde o início para reconstruir o estado local. Durante a reprodução, se o código tentar chamar uma função (ou realizar qualquer outro trabalho assíncrono), o Durable Task Framework consulta o histórico de execução da orquestração atual. Se descobrir que a função de atividade já foi executada e gerou um resultado, reproduz o resultado dessa função, e o código do orquestrador continua a correr. A repetição continua até que o código da função seja concluído ou até que novos trabalhos assíncronos sejam agendados.
Observação
Para ajudar o padrão de repetição a funcionar corretamente e de forma fiável, o código da função do orquestrador deve ser determinístico. O código de orquestrador não determinístico pode resultar em erros de execução ou outros comportamentos inesperados. Para mais informações sobre restrições de código para funções de orquestrador, veja restrições de código de funções Orchestrator.
Observação
Se uma função de orquestrador emitir mensagens de log, o comportamento de reprodução pode causar a emissão de mensagens de log duplicadas. Para mais informações sobre porque este comportamento ocorre e como contorná-lo, consulte Registo de aplicações.
História da orquestração
O comportamento de fornecimento de eventos do Durable Task Framework está intimamente ligado ao código de função do orquestrador que você escreve. Suponha que você tem uma função orquestradora de encadeamento de atividades, como a seguinte.
Observação
A versão 4 do modelo de programação Node.js para o Azure Functions está geralmente disponível. O modelo v4 foi concebido para proporcionar uma experiência mais flexível e intuitiva para programadores JavaScript e TypeScript. Para mais informações sobre as diferenças entre v3 e v4, consulte o guia de migração.
Nos seguintes excertos de código, o JavaScript (PM4) denota o modelo de programação v4, a nova experiência.
[FunctionName("HelloCities")]
public static async Task<List<string>> Run(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var outputs = new List<string>();
outputs.Add(await context.CallActivityAsync<string>("SayHello", "Tokyo"));
outputs.Add(await context.CallActivityAsync<string>("SayHello", "Seattle"));
outputs.Add(await context.CallActivityAsync<string>("SayHello", "London"));
// Return ["Hello Tokyo!", "Hello Seattle!", "Hello London!"].
return outputs;
}
Sempre que uma função de atividade é agendada, o Durable Task Framework guarda o estado de execução da função em vários checkpoints. Em cada checkpoint, o framework guarda o estado num backend de armazenamento duradouro, que é o Azure Table Storage por defeito. Este estado é referido como a história da orquestração.
Tabela de histórico
De um modo geral, o Durable Task Framework faz o seguinte em cada ponto de verificação:
- Guarda o histórico de execução num armazenamento duradouro.
- Enfileira mensagens destinadas às funções que o orquestrador deseja invocar.
- Enqueuea mensagens para o próprio orquestrador, como mensagens temporizadoras duradouras.
Quando o checkpoint está concluído, a função de orquestrador pode ser removida da memória até haver mais trabalho para fazer.
Observação
O Azure Storage não oferece quaisquer garantias transacionais sobre consistência de dados entre o armazenamento de tabelas e as filas quando os dados são guardados. Para lidar com falhas, o provedor Durable Functions do Armazenamento do Azure usa padrões de consistência eventual. Estes padrões ajudam a garantir que nenhum dado se perde caso haja um crash ou perda de conectividade no meio de um posto de controlo. Fornecedores de armazenamento alternativos, como o Durable Functions Microsoft SQL Server (MSSQL), podem fornecer garantias de consistência mais fortes.
Quando a função mostrada anteriormente termina, o seu histórico assemelha-se aos dados da tabela seguinte no Armazenamento de Tabelas. As entradas são abreviadas para fins ilustrativos.
| PartitionKey (InstanceId) | Tipo de Evento | Data e Hora | Entrada | Nome | Result | Situação |
|---|---|---|---|---|---|---|
| EAEE885B | Execução Iniciada | 2021-05-05T18:45:28.852Z | null | OláCidades | ||
| EAEE885B | OrchestratorIniciado | 2021-05-05T18:45:32.362Z | ||||
| EAEE885B | TarefaAgendada | 2021-05-05T18:45:32.670Z | DigaOlá | |||
| EAEE885B | OrchestratorConcluído | 2021-05-05T18:45:32.670Z | ||||
| EAEE885B | TarefaConcluída | 2021-05-05T18:45:34.201Z | ""Olá Tóquio!""" | |||
| EAEE885B | OrchestratorIniciado | 2021-05-05T18:45:34.232Z | ||||
| EAEE885B | TarefaAgendada | 2021-05-05T18:45:34.435Z | DigaOlá | |||
| EAEE885B | OrchestratorConcluído | 2021-05-05T18:45:34.435Z | ||||
| EAEE885B | TarefaConcluída | 2021-05-05T18:45:34.763Z | ""Olá Seattle!""" | |||
| EAEE885B | OrchestratorIniciado | 2021-05-05T18:45:34.857Z | ||||
| EAEE885B | TarefaAgendada | 2021-05-05T18:45:34.857Z | DigaOlá | |||
| EAEE885B | OrchestratorConcluído | 2021-05-05T18:45:34.857Z | ||||
| EAEE885B | TarefaConcluída | 2021-05-05T18:45:34.919Z | ""Olá Londres!""" | |||
| EAEE885B | OrchestratorIniciado | 2021-05-05T18:45:35.032Z | ||||
| EAEE885B | OrchestratorConcluído | 2021-05-05T18:45:35.044Z | ||||
| EAEE885B | ExecuçãoConcluída | 2021-05-05T18:45:35.044Z | "["Olá Tóquio!"",""Olá Seattle!"","Olá Londres!""]" | Concluído |
As colunas da tabela contêm os seguintes valores:
- PartitionKey: O ID da instância da orquestração.
- EventType: O tipo do evento. Para descrições detalhadas de todos os tipos de eventos históricos, consulte Eventos Históricos do Quadro de Tarefas Duradouras.
- Timestamp: O carimbo temporal universal coordenado do evento histórico.
- Entrada: A entrada formatada em JSON da função.
- Nome: O nome da função invocada.
- Resultado: A saída da função, especificamente, o seu valor de retorno.
Advertência
Esta tabela pode ser útil como ferramenta de debugging. Mas tenha em mente que o seu formato e conteúdo podem mudar à medida que a extensão Durable Functions evolui.
Sempre que a função é retomada depois de aguardar a conclusão de uma tarefa, o Durable Task Framework reinicia a função do orquestrador do zero. Em cada repetição, consulta o histórico de execução para determinar se a tarefa assíncrona atual está concluída. Se o histórico de execução mostrar que a tarefa já está completa, o framework repete a saída dessa tarefa e passa para a tarefa seguinte. Este processo continua até que todo o histórico de execução tenha sido reproduzido. Assim que o histórico de execução atual for reproduzido, as variáveis locais terão sido restauradas aos seus valores anteriores.
Características e padrões
As secções seguintes descrevem as características e padrões das funções do orquestrador.
Sub-orquestrações
As funções do orquestrador podem chamar funções de atividade, mas também outras funções do orquestrador. Por exemplo, você pode criar uma orquestração maior a partir de uma biblioteca de funções de orquestrador. Ou, você pode executar várias instâncias de uma função orquestradora em paralelo.
Para mais informações e exemplos, veja Suborquestrações em Funções Duradouras (Azure Functions).
Temporizadores duráveis
As orquestrações podem agendar temporizadores persistentes para implementar atrasos ou para configurar o manuseio de tempos limite em ações assíncronas. Use temporizadores duráveis nas funções do orquestrador em vez de APIs nativas sleep da linguagem.
Para mais informações e exemplos, veja Temporizadores em Funções Duráveis (Azure Functions).
Eventos externos
As funções do Orchestrator podem aguardar eventos externos para atualizar uma instância de orquestração. Esta funcionalidade de Funções Duráveis é frequentemente útil para lidar com interações humanas ou outros callbacks externos.
Para mais informações e exemplos, consulte Gestão de eventos externos em Funções Duradouras (Azure Functions).
Tratamento de erros
As funções do Orchestrator podem usar os recursos de tratamento de erros da linguagem de programação. Padrões existentes como try/catch são suportados no código de orquestração.
As funções de orquestrador também podem adicionar políticas de repetição à atividade ou às funções de suborquestrador que elas chamam. Se uma atividade ou função suborquestradora falhar com uma exceção, a política de repetição de tentativas especificada pode atrasar e repetir automaticamente a execução até ao número especificado de vezes.
Observação
Se houver uma exceção não tratada numa função de orquestrador, a instância de orquestração termina num Failed estado. Uma instância de orquestração não pode ser tentada novamente depois de falhar.
Para mais informações e exemplos, veja Gestão de erros em Funções Duráveis (Azure Functions).
Seções críticas (Durable Functions 2.x, atualmente somente .NET)
As instâncias de orquestração são single-threaded, portanto, as condições de corrida não são um problema dentro de uma orquestração. No entanto, as condições de corrida são possíveis quando as orquestrações interagem com sistemas externos. Para mitigar as condições de corrida ao interagir com sistemas externos, as funções do orquestrador podem definir secções críticas utilizando um método em .NET.
O código de exemplo a seguir mostra uma função orchestrator que define uma seção crítica. Utiliza o LockAsync método para entrar na secção crítica. Este método requer passar uma ou mais referências a uma entidade durável, que gere de forma duradoura o estado do bloqueio. Apenas uma única instância dessa orquestração pode executar o código na seção crítica de cada vez.
[FunctionName("Synchronize")]
public static async Task Synchronize(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var lockId = new EntityId("LockEntity", "MyLockIdentifier");
using (await context.LockAsync(lockId))
{
// Critical section. Only one orchestration can enter at a time.
}
}
O LockAsync método adquire fechaduras duráveis e devolve um IDisposable que termina a secção crítica quando é descartado. Este IDisposable resultado pode ser usado em conjunto com um using bloco para obter uma representação sintática da seção crítica. Quando uma função orchestrator entra em uma seção crítica, apenas uma instância pode executar esse bloco de código. Quaisquer outras instâncias que tentem entrar na secção crítica são bloqueadas até que a instância anterior saia da secção crítica.
O recurso de seção crítica também é útil para coordenar alterações em entidades duráveis. Para mais informações sobre secções críticas, consulte Coordenação de entidades.
Observação
As secções críticas estão disponíveis em Durable Functions 2.0. Atualmente, apenas as orquestrações internas do .NET implementam esta funcionalidade. Entidades e secções críticas ainda não estão disponíveis em Funções Duráveis para orquestrações isoladas de trabalhadores em .NET.
Chamadas para endpoints HTTP (Durable Functions 2.x)
As funções do Orchestrator não têm permissão para realizar operações de I/O, conforme descrito nas restrições do código de funções do Orchestrator. A solução típica para esta limitação é envolver qualquer código que precise de realizar operações de E/S numa função de atividade. Orquestrações que interagem com sistemas externos frequentemente utilizam funções de atividade para fazer chamadas HTTP e devolver os resultados à orquestração.
Para simplificar este padrão comum, as funções do orquestrador podem usar o CallHttpAsync método para invocar diretamente APIs HTTP.
[FunctionName("CheckSiteAvailable")]
public static async Task CheckSiteAvailable(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
Uri url = context.GetInput<Uri>();
// Make an HTTP GET request to the specified endpoint.
DurableHttpResponse response =
await context.CallHttpAsync(HttpMethod.Get, url);
if ((int)response.StatusCode == 400)
{
// Handle error codes.
}
}
Para além de suportar padrões básicos de pedido/resposta, o método suporta o tratamento automático de padrões comuns de sondagem HTTP 202 assíncronos. Também suporta autenticação com serviços externos através do uso de identidades geridas.
Para mais informações e exemplos detalhados, veja funcionalidades HTTP.
Observação
A chamada de endpoints HTTP diretamente a partir das funções do orquestrador está disponível no Durable Functions 2.0 e posteriores.
Múltiplos parâmetros
Não é possível passar vários parâmetros para uma função de atividade diretamente. A recomendação é passar uma matriz de objetos ou objetos compostos.
No .NET, também pode usar objetos ValueTuple para passar múltiplos parâmetros. O exemplo seguinte utiliza funcionalidades do ValueTuple adicionadas com C# 7:
[FunctionName("GetCourseRecommendations")]
public static async Task<object> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
string major = "ComputerScience";
int universityYear = context.GetInput<int>();
object courseRecommendations = await context.CallActivityAsync<object>(
"CourseRecommendations",
(major, universityYear));
return courseRecommendations;
}
[FunctionName("CourseRecommendations")]
public static async Task<object> Mapper([ActivityTrigger] IDurableActivityContext inputs)
{
// Parse the input for the student's major and year in university.
(string Major, int UniversityYear) studentInfo = inputs.GetInput<(string, int)>();
// Retrieve and return course recommendations by major and university year.
return new
{
major = studentInfo.Major,
universityYear = studentInfo.UniversityYear,
recommendedCourses = new []
{
"Introduction to .NET Programming",
"Introduction to Linux",
"Becoming an Entrepreneur"
}
};
}