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.
O controle de versão em Durable Functions é essencial porque as funções são inevitavelmente adicionadas, removidas e alteradas ao longo do tempo de vida de um aplicativo. Durable Functions permite encadear funções de maneiras que não eram possíveis anteriormente e esse encadeamento afeta a forma como você lida com o controle de versão.
Este artigo ajuda você a:
- Identifique se a alteração de código é uma alteração significativa.
- Escolha a estratégia de mitigação correta para implantar com segurança.
Comparação de estratégia rápida
Se você já souber que a alteração está falhando, use esta tabela para escolher uma estratégia de mitigação:
| Estratégia | Mais adequado para | Detalhes |
|---|---|---|
| Controle de versão de orquestração (recomendado) | A maioria dos aplicativos com alterações interruptivas. O recurso de tempo de execução integrado funciona com qualquer backend de armazenamento. | Ir para a seção |
| Implantações lado a lado | Aplicativos que não podem usar versionamento de orquestração ou que precisam de isolamento total com hubs de tarefas ou contas de armazenamento separadas. | Ir para a seção |
| Parar todas as instâncias em execução | A criação de protótipos e o desenvolvimento local onde perder orquestrações a bordo é aceitável. | Ir para a seção |
Dica
Se você estiver procurando o recurso de controle de versão de orquestração interno que fornece isolamento de versão automático em nível de runtime, consulte Versão de orquestração.
Importante
Antes de implantar, verifique se a alteração é uma alteração significativa:
- Você alterou o nome, o tipo de entrada ou o tipo de saída de uma função de atividade ou entidade?
- Você adicionou, removeu ou reordenou chamadas a atividades, sub-orquestrações, temporizadores ou eventos externos no código do orquestrador?
- Você renomeou ou removeu uma função que as orquestrações in-flight ainda podem chamar?
Se você respondeu sim a qualquer uma delas, use uma das estratégias de mitigação abaixo para evitar falhas na execução de orquestrações.
Tipos de alterações da falha
Existem vários exemplos de alterações interruptivas. Este artigo discute os tipos mais comuns. O tema principal subjacente é que alterações no código de função afetam orquestrações de função novas e existentes.
Alterações na assinatura da função de atividade ou entidade
Uma alteração de assinatura refere-se a uma alteração no nome, entrada ou saída de uma função. Se você fizer esse tipo de alteração em uma função de atividade ou entidade, ela poderá interromper a função de orquestrador que depende dela. Esse comportamento é especialmente verdadeiro para linguagens de programação com tipagem segura. Se atualizar a função de orquestrador para acomodar essa alteração, você poderá interromper instâncias existentes em curso.
Por exemplo, considere a função orquestradora a seguir.
[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
bool result = await context.CallActivityAsync<bool>("Foo");
await context.CallActivityAsync("Bar", result);
}
Essa função usa o resultado de Foo e a passa para Bar. Suponha que você precise alterar o valor retornado de Foo de um booliano para uma cadeia de caracteres para dar suporte a uma variedade maior de valores de resultado. O resultado tem esta aparência:
[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
string result = await context.CallActivityAsync<string>("Foo");
await context.CallActivityAsync("Bar", result);
}
Essa alteração funciona bem com todas as novas instâncias da função de orquestrador, mas deve interromper as instâncias em curso. Por exemplo, considere o caso em que uma instância de orquestração chama uma função nomeada Foo, obtém de volta um valor booliano e, em seguida, pontos de verificação. Se a alteração da assinatura for implantada nesse ponto, a instância verificada falhará imediatamente quando for retomada e reproduzir a chamada para Foo. Essa falha ocorre porque o resultado na tabela de histórico é um valor booliano, mas o novo código tenta desserializá-lo em um valor string, resultando em um comportamento inesperado ou até mesmo em uma exceção de runtime para linguagens de segurança de tipo.
Este exemplo é uma das diversas formas em que uma alteração de assinatura de função pode interromper instâncias existentes. Em geral, se um orquestrador precisar alterar a maneira como chama uma função, a alteração provavelmente será problemática.
Alterações na lógica do orquestrador
O outro tipo de problemas de controle de versão resulta da alteração do código de função do orquestrador de forma que altera o caminho de execução para instâncias em andamento.
Considere a seguinte função de orquestrador:
[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
bool result = await context.CallActivityAsync<bool>("Foo");
await context.CallActivityAsync("Bar", result);
}
Agora suponha que você queira adicionar uma nova chamada de função entre as duas chamadas de função existentes.
[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
bool result = await context.CallActivityAsync<bool>("Foo");
if (result)
{
await context.CallActivityAsync("SendNotification");
}
await context.CallActivityAsync("Bar", result);
}
Essa alteração adiciona uma nova chamada de função a SendNotification entre Foo e Bar. Nenhuma alteração de assinatura existe. O problema surge quando uma instância existente é retomada da chamada para Bar. Durante a reprodução, se a chamada original para Foo retornar true, o orquestrador reproduzirá chamadas em SendNotification, que não consta no histórico de execuções. O runtime detecta essa inconsistência e gera um erro de orquestração não determinística porque encontrou uma chamada para SendNotification quando esperava ver uma chamada para Bar. O mesmo tipo de problema pode ocorrer ao adicionar chamadas de API a outras operações duráveis, como criar temporizadores duráveis, aguardar eventos externos ou chamar sub-orquestrações.
Estratégias de mitigação
Aviso
Implantar alterações de ruptura sem uma estratégia de mitigação (a abordagem "não fazer nada") pode fazer com que as orquestrações falhem com erros de orquestrações não determinísticas, fiquem presas indefinidamente em um estado de Running, ou disparem falhas de execução de baixo nível que degradam o desempenho. Sempre use uma das estratégias a seguir ao implantar alterações interruptivas.
Versionamento de orquestração (recomendado)
Diferente das outras estratégias nesta seção, o versionamento de orquestração é um recurso de runtime interno que oferece isolamento de versão automático. Você não precisa gerenciar implantações separadas, hubs de tarefas ou contas de armazenamento. Em vez disso, o runtime em si controla as informações de versão e garante que as instâncias de orquestração sejam processadas por trabalhadores compatíveis.
Com controle de versão de orquestração:
- Cada instância de orquestração obtém uma versão permanentemente associada a ela quando criada.
- As funções de orquestrador podem examinar a versão e executar branches adequadamente, mantendo caminhos de código antigos e novos na mesma base de código.
- Os trabalhadores que executam versões de função de orquestrador mais recentes podem continuar executando instâncias de orquestração criadas por versões mais antigas.
- O runtime evita que trabalhos executando versões de função de orquestrador mais antigas executem orquestrações de versões mais recentes.
Essa abordagem requer uma configuração mínima (uma cadeia de caracteres de versão e uma estratégia de correspondência opcional) e é compatível com qualquer provedor de armazenamento. É a estratégia recomendada para os aplicativos que precisam dar suporte às alterações interruptivas, mantendo implantações de tempo de inatividade zero.
Para obter diretrizes detalhadas de configuração e implementação, consulte o versionamento de orquestração.
Parar todas as instâncias em curso
Outra opção é parar todas as instâncias em curso. Se você estiver usando o provedor Armazenamento do Azure padrão para Durable Functions, interrompa todas as instâncias limpando o conteúdo das filas internas control-queue e workitem-queue. Como alternativa, interrompa o aplicativo de funções, exclua essas filas e reinicie o aplicativo. As filas são recriadas automaticamente quando o aplicativo é reiniciado. As instâncias de orquestração anteriores podem permanecer no estado "Em execução" indefinidamente, mas não sobrecarregam seus logs com mensagens de erro nem causam danos à sua aplicação. Essa abordagem é ideal para o desenvolvimento rápido de protótipos, incluindo o desenvolvimento local.
Aviso
Essa abordagem requer acesso direto aos recursos de armazenamento subjacentes e não é apropriada para todos os provedores de armazenamento compatíveis com Durable Functions.
Implantações lado a lado
A maneira mais à prova de falhas para garantir que mudanças disruptivas sejam implantadas com segurança é implantá-las lado a lado com suas versões mais antigas. Você pode usar qualquer uma das seguintes técnicas:
- Conta de armazenamento diferente: implante todas as atualizações como um novo aplicativo de funções com uma conta de armazenamento diferente. Isso isola completamente o estado da nova versão do estado da versão antiga.
- Hub de tarefas diferente: implante uma nova cópia do aplicativo de funções com a mesma conta de armazenamento, mas com um nome de hub de tarefas atualizado. Essa abordagem cria novos artefatos de armazenamento para a nova versão, enquanto a versão antiga continua a usar seus artefatos existentes.
Ao fazer implantações lado a lado no Azure, você pode usar slots de implantação para executar ambas as versões simultaneamente, com apenas uma como o slot ativo de produção. Quando estiver pronto para expor a nova lógica de orquestração, alterne a nova versão para o slot de produção.
Observação
Essa orientação usa termos específicos do Armazenamento do Azure, mas geralmente se aplica a todos os provedores de armazenamento de Durable Functions suportados.
Observação
As trocas de slot de implantação funcionam melhor com gatilhos HTTP e webhook. Para gatilhos não HTTP, como filas ou Hubs de Eventos, a definição do gatilho deve derivar de uma configuração de aplicativo que é atualizada como parte da operação de troca.