Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Durable Functions é uma extensão do Azure Functions que fornece uma maneira de executar funções com estado em um ambiente de computação sem servidor. Em um aplicativo de funções durável, você pode usar uma função de orquestrador para orquestrar a execução de outras funções duráveis. As funções do orchestrator têm as seguintes características:
- Eles definem fluxos de trabalho de função usando código de procedimento. Não são necessários esquemas declarativos ou designers.
- Eles podem chamar outras funções duráveis de forma síncrona e assíncrona. A saída de funções chamadas pode ser salva em variáveis locais.
- Eles foram projetados para serem duráveis e confiáveis. O progresso da execução é salvo automaticamente como um ponto de verificação quando a função chama um operador
awaitouyield. O estado local não é perdido quando o processo é reciclado ou a máquina virtual é reiniciada. - Eles podem ter longa duração. O tempo de vida 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 de orquestrador e como elas podem ajudá-lo a resolver vários desafios de desenvolvimento de aplicativos. Para obter informações sobre os tipos de funções disponíveis em um aplicativo durable functions, consulte os tipos e recursos de Durable Functions.
Identidade de orquestração
Cada instância de uma orquestração tem um identificador de instância, também conhecido como uma ID de instância. Por padrão, cada ID de instância é um GUID (identificador global exclusivo) gerado automaticamente. No entanto, as 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 exclusiva em um hub de tarefas.
As seguintes regras se aplicam a IDs de instância:
- Eles devem ter entre 1 e 100 caracteres.
- Eles não devem começar com
@. - Eles não devem conter
/,\ou#?caracteres. - Eles não devem conter caracteres de controle.
Observação
Geralmente, recomendamos que você use IDs de instância geradas automaticamente sempre que possível. As IDs de instância geradas pelo usuário são destinadas a cenários em que há um mapeamento um-para-um entre uma instância de orquestração e uma entidade externa específica do aplicativo, como uma ordem de compra ou um documento.
Além disso, a imposição real das regras de restrição de caractere pode variar dependendo do provedor de armazenamento que o aplicativo usa. Para ajudar a garantir o comportamento e a compatibilidade corretos, é altamente recomendável que você siga as regras de ID da instância anteriores.
A ID da instância de uma orquestração é um parâmetro necessário para a maioria das operações de gerenciamento de instância. As IDs de instância também são importantes para diagnóstico. Por exemplo, você os usa quando pesquisa dados de acompanhamento de orquestração no Application Insights para fins de solução de problemas ou análise. Por esse motivo, recomendamos que você salve as IDs de instância geradas em um local externo, o que facilita a referência a elas posteriormente. Exemplos de locais incluem bancos de dados ou registros de aplicativos.
Reliability
As funções do Orchestrator utilizam o padrão de design fornecimento de eventos para ajudar a manter seu estado de execução de forma confiável. Em vez de armazenar diretamente o estado atual de uma orquestração, a Estrutura de Tarefas Duráveis usa um armazenamento somente de acréscimo para registrar a série completa de ações executadas pela orquestração de função. Um armazenamento somente para anexação oferece muitas vantagens em comparação com despejo do estado de runtime completo. Os benefícios incluem maior desempenho, escalabilidade e capacidade de resposta. Você também obtém consistência eventual para dados transacionais e trilhas e histórico de auditoria completos. As trilhas de auditoria dão suporte a ações de compensação confiáveis.
As Durable Functions usam o fornecimento de eventos de forma transparente. Em segundo plano, a função de orquestrador usa um operador await em C# e um operador yield em JavaScript e Python. Esses operadores devolvem o controle da thread do orquestrador para o despachante do Durable Task Framework. Em funções Java, não há nenhuma palavra-chave de linguagem especial. Em vez disso, chamar .await() em uma tarefa retorna o controle ao dispatcher por meio de uma instância personalizada de Throwable. Em seguida, o despachante confirma no armazenamento quaisquer novas ações agendadas pela função orquestradora. 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ções da instância de orquestração acrescentando todos os novos eventos ao armazenamento, assim como 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 de orquestrador pode ser descarregada da memória. Por padrão, o Durable Functions usa o Armazenamento do Azure como seu repositório de estado de runtime, mas também há suporte para outros provedores de armazenamento.
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 executa novamente toda a função desde o início para recompilar o estado local. Durante a reprodução, se o código tentar chamar uma função (ou fazer qualquer outro trabalho assíncrono), a Estrutura de Tarefas Duráveis consultará o histórico de execução da orquestração atual. Se descobrir que a função de atividade já executou e rendeu um resultado, ela reproduzirá o resultado dessa função e o código do orquestrador continuará sendo executado. A repetição continua até que o código da função seja concluído ou até que uma nova tarefa assíncrona seja agendada.
Observação
Para ajudar o padrão de reprodução a funcionar de forma correta e confiável, o código de função do orquestrador deve ser determinístico. O código do orquestrador não determinístico pode resultar em erros de runtime ou outro comportamento inesperado. Para obter mais informações sobre restrições de código para funções de orquestrador, consulte restrições de código de função orchestrator.
Observação
Se uma função de orquestrador emitir mensagens de log, o comportamento de reprodução poderá fazer com que mensagens de log duplicadas sejam emitidas. Para obter mais informações sobre por que esse comportamento ocorre e como contorná-lo, consulte Registro de Aplicativos.
Histórico de orquestração
O comportamento de fornecimento de eventos da Estrutura de Tarefas Duráveis está intimamente associado ao código de função do orquestrador que você escreve. Suponha que você tenha uma função orquestradora de encadeamento de atividades, como a seguinte função orquestradora.
Observação
A versão 4 do modelo de programação Node.js para o Azure Functions está disponível em geral. O modelo v4 foi projetado para fornecer uma experiência mais flexível e intuitiva para desenvolvedores JavaScript e TypeScript. Para obter mais informações sobre as diferenças entre v3 e v4, consulte o guia de migração.
Nos snippets de código a seguir, 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, a Estrutura de Tarefas Duráveis salva o estado de execução da função em vários pontos de verificação. Em cada ponto de verificação, a estrutura salva o estado em um back-end de armazenamento durável, que é o Armazenamento de Tabelas do Azure por padrão. Esse estado é chamado de histórico de orquestração.
Tabela de histórico
De modo geral, a Estrutura de Tarefas Duráveis faz o seguinte em cada ponto de verificação:
- Salva o histórico de execução no armazenamento durável.
- Enfileira mensagens para funções que o orquestrador deseja invocar.
- Enfileira mensagens para o próprio orquestrador, como mensagens de temporizador persistentes.
Quando o ponto de verificação estiver completo, a função orquestradora pode ser removida da memória até que haja mais trabalho para ela realizar.
Observação
O Armazenamento do Azure não fornece garantias transacionais sobre a consistência de dados entre o armazenamento de tabelas e filas quando os dados são salvos. Para lidar com falhas, o provedor de Armazenamento do Azure de Funções Duráveis usa padrões de consistência eventual. Esses padrões ajudam a garantir que nenhum dado seja perdido se houver uma falha ou perda de conectividade no meio de um ponto de verificação. Provedores de armazenamento alternativos, como o provedor de armazenamento MSSQL (Microsoft SQL Server) de Funções Duráveis, podem fornecer garantias de consistência mais fortes.
Quando a função mostrada anteriormente é concluída, seu histórico se parece com os dados na tabela a seguir no Armazenamento de Tabelas. As entradas são abreviadas para fins ilustrativos.
| PartitionKey (InstanceId) | Tipo de Evento | Timestamp | Input | Nome | Resultado | Situação |
|---|---|---|---|---|---|---|
| eaee885b | ExecutionStarted | 2021-05-05T18:45:28.852Z | nulo | HelloCities | ||
| eaee885b | OrchestratorStarted | 2021-05-05T18:45:32.362Z | ||||
| eaee885b | TarefaAgendada | 2021-05-05T18:45:32.670Z | DigaOlá | |||
| eaee885b | OrchestratorCompleted | 2021-05-05T18:45:32.670Z | ||||
| eaee885b | TaskCompleted | 2021-05-05T18:45:34.201Z | ""Olá, Tóquio!"" | |||
| eaee885b | OrchestratorStarted | 2021-05-05T18:45:34.232Z | ||||
| eaee885b | TarefaAgendada | 2021-05-05T18:45:34.435Z | DigaOlá | |||
| eaee885b | OrchestratorCompleted | 2021-05-05T18:45:34.435Z | ||||
| eaee885b | TaskCompleted | 2021-05-05T18:45:34.763Z | ""Olá Seattle!"" | |||
| eaee885b | OrchestratorStarted | 2021-05-05T18:45:34.857Z | ||||
| eaee885b | TarefaAgendada | 2021-05-05T18:45:34.857Z | DigaOlá | |||
| eaee885b | OrchestratorCompleted | 2021-05-05T18:45:34.857Z | ||||
| eaee885b | TaskCompleted | 2021-05-05T18:45:34.919Z | ""Olá, Londres!"" | |||
| eaee885b | OrchestratorStarted | 2021-05-05T18:45:35.032Z | ||||
| eaee885b | OrchestratorCompleted | 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 obter descrições detalhadas de todos os tipos de eventos de histórico, consulte Durable Task Framework History Events.
- Carimbo de data/hora: o carimbo de data/hora 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, seu valor retornado.
Aviso
Essa tabela pode ser útil como ferramenta de depuração. Mas tenha em mente que 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, a Estrutura de Tarefas Duráveis executa novamente a função de orquestrador do zero. Em cada nova execução, ele 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á concluída, a estrutura reproduzirá a saída dessa tarefa e passará para a próxima tarefa. Esse processo continua até que todo o histórico de execução tenha sido reproduzido. Assim que o histórico de execução atual tiver sido reproduzido, as variáveis locais serão restauradas para seus valores anteriores.
Recursos e padrões
As seções a seguir descrevem os recursos e padrões das funções do orquestrador.
Sub-orquestrações
As funções de orquestrador podem chamar funções de atividade, mas também outras funções de orquestrador. Por exemplo, você pode criar uma orquestração maior a partir de uma biblioteca de funções de orquestrador. Ou pode executar várias instâncias de uma função de orquestrador em paralelo.
Para obter mais informações e exemplos, consulte Sub-orquestrações em Durable Functions (Azure Functions).
Temporizadores duráveis
As orquestrações podem agendar temporizadores duráveis para implementar atrasos ou configurar o tratamento de tempo limite em ações assíncronas. Use temporizadores duráveis em funções de orquestrador em vez de APIs nativas de linguagem sleep.
Para obter mais informações e exemplos, consulte Timers in Durable Functions (Azure Functions).
Eventos externos
As funções de orquestrador podem aguardar eventos externos para atualizar uma instância de orquestração. Esse recurso de Funções Duráveis geralmente é útil para lidar com interações humanas ou outros retornos de chamada externos.
Para obter mais informações e exemplos, consulte Como lidar com eventos externos em Durable Functions (Azure Functions).
Tratamento de erros
As funções de orquestrador podem usar os recursos de tratamento de erros da linguagem de programação. Padrões existentes, como try/catch , têm suporte 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 de suborquestrador falhar com uma exceção, a política de repetição especificada poderá atrasar automaticamente e repetir a execução até um número especificado de vezes.
Observação
Se ocorrer uma exceção não tratada em uma função do orquestrador, a instância de orquestração será finalizada em um estado Failed. Uma instância de orquestração não pode ser reiniciada após falhar.
Para obter mais informações e exemplos, consulte Tratamento de erros em Durable Functions (Azure Functions).
Seções críticas (Durable Functions 2.x, somente .NET atualmente)
As instâncias de orquestração são de thread única, portanto, as condições de corrida não são uma preocupação dentro de uma orquestração. No entanto, as condições de concorrência são possíveis quando orquestrações interagem com sistemas externos. Para atenuar as condições de corrida ao interagir com sistemas externos, as funções de orquestrador podem definir seções críticas usando um LockAsync método no .NET.
O código de exemplo a seguir mostra uma função de orquestrador que define uma seção crítica. Ele usa o LockAsync método para inserir a seção crítica. Esse método requer a passagem de uma ou mais referências para uma entidade durável, que gerencia duravelmente o estado de bloqueio. Somente 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 os bloqueios duráveis e retorna um IDisposable que termina a seção crítica quando descartado. Esse IDisposable resultado pode ser usado junto com um using bloco para obter uma representação sintactica da seção crítica. Quando uma função de orquestrador entra em uma seção crítica, apenas uma instância pode executar esse bloco de código. Todas as outras instâncias que tentam inserir a seção crítica são bloqueadas até que a instância anterior saia da seção crítica.
O recurso de seção crítica também é útil para coordenar alterações em entidades duráveis. Para obter mais informações sobre seções críticas, consulte coordenação de entidade.
Observação
Seções críticas estão disponíveis no Durable Functions 2.0. Atualmente, somente orquestrações em processo do .NET implementam esse recurso. Entidades e seções críticas ainda não estão disponíveis no Durable Functions para orquestrações de workers isolados do .NET.
Chamadas para endpoints HTTP (Durable Functions 2.x)
As funções de orquestrador não têm permissão para fazer operações de E/S, conforme descrito nas restrições de código de função do Orchestrator. A solução alternativa típica para essa limitação é encapsular qualquer código que precise executar operações de E/S em uma função de atividade. Orquestrações que interagem com sistemas externos frequentemente usam funções de atividade para fazer chamadas HTTP e retornar os resultados para a orquestração.
Para simplificar esse padrão comum, as funções de orquestrador podem usar o CallHttpAsync método para invocar APIs HTTP diretamente.
[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.
}
}
Além de dar suporte a padrões básicos de solicitação/resposta, o método dá suporte ao tratamento automático de padrões de sondagem HTTP 202 assíncronos comuns. Ele também dá suporte à autenticação com serviços externos usando identidades gerenciadas.
Para obter mais informações e exemplos detalhados, consulte os recursos HTTP.
Observação
A chamada direta de endpoints HTTP a partir de funções do orquestrador está disponível no Durable Functions 2.0 e versões posteriores.
Vários parâmetros
Não é possível passar vários parâmetros diretamente para uma função de atividade. A recomendação é transmitir uma matriz de objetos ou objetos de composição.
No .NET, você também pode usar objetos ValueTuple para passar vários parâmetros. O exemplo a seguir usa os recursos do ValueTuple adicionados ao 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"
}
};
}