Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
O controle de versão de orquestração aborda o principal desafio de implantar alterações nas funções do orquestrador, mantendo o modelo de execução determinístico que as Funções Duráveis exigem. Sem esse recurso, as alterações de quebra na lógica do orquestrador ou nas assinaturas da função de atividade fariam com que as instâncias de orquestração em voo falhassem durante a repetição, pois quebrariam o requisito de determinismo que garante a execução confiável da orquestração. Este recurso integrado fornece isolamento automático de versão com configuração mínima. É independente de back-end, por isso pode ser usado por aplicativos que aproveitam qualquer um dos provedores de armazenamento da Função Durável, incluindo o Agendador de Tarefas Duráveis.
Note
Para usuários do Agendador de Tarefas Duráveis, se você estiver usando os SDKs de Tarefa Durável em vez de funções Duráveis, consulte o artigo de controle de versão de SDKs de Tarefas Duráveis.
Terminology
Este artigo usa dois termos relacionados, mas distintos:
- Função orquestradora (ou simplesmente "orquestrador"): refere-se ao código da função que define a lógica do fluxo de trabalho - o modelo ou esquema de como um fluxo de trabalho deve ser executado.
- Instância de orquestração (ou simplesmente "orquestração"): refere-se a uma execução específica de uma função do orquestrador, com seu próprio estado, ID da instância e entradas. Várias instâncias de orquestração podem ser executadas simultaneamente a partir da mesma função de orquestrador.
Compreender essa distinção é crucial para o versionamento de orquestração, onde o código de função do orquestrador contém lógica com reconhecimento de versão, enquanto as instâncias de orquestração são permanentemente associadas a uma versão específica quando criadas.
Como funciona
O recurso de versionamento de orquestração opera com base nestes princípios fundamentais:
Associação de versão: quando uma instância de orquestração é criada, ela recebe uma versão permanentemente associada a ela.
Execução com reconhecimento de versão: O código da função do orquestrador pode examinar o valor da versão associado à instância de orquestração atual e ramificar a execução conforme necessário.
Compatibilidade com versões anteriores: os trabalhadores que executam versões mais recentes do orchestrator podem continuar executando instâncias de orquestração criadas por versões mais antigas do orchestrator.
Proteção avançada: o tempo de execução impede automaticamente que os trabalhadores que executam versões mais antigas do orchestrator executem orquestrações iniciadas por versões mais recentes do orchestrator.
Important
O versionamento da orquestração está atualmente em versão pública preliminar.
Pré-requisitos
Antes de usar o versionamento de orquestração, verifique se tem as versões de pacote necessárias para a sua linguagem de programação.
Se você estiver usando uma linguagem non-.NET (JavaScript, Python, PowerShell ou Java) com pacotes de extensão, seu aplicativo de função deverá fazer referência ao Extension Bundle versão 4.26.0 ou posterior. Configure o extensionBundle intervalo em host.json de forma que a versão mínima seja pelo menos 4.26.0, por exemplo:
{
"version": "2.0",
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.26.0, 5.0.0)"
}
}
Consulte a documentação de configuração do pacote de extensão para obter detalhes sobre como escolher e atualizar as versões do pacote.
Use a Microsoft.Azure.Functions.Worker.Extensions.DurableTask versão 1.5.0 ou posterior.
Utilização básica
O caso de uso mais comum para o controle de versão de orquestração é quando você precisa fazer alterações significativas na lógica do orquestrador, mantendo as instâncias de orquestração em voo existentes em execução com a versão original. Tudo o que precisa fazer é atualizar o defaultVersion no seu host.json e modificar o código do orquestrador para verificar a versão da orquestração e executar a ramificação de acordo. Vamos percorrer as etapas necessárias.
Note
O comportamento descrito nesta seção tem como alvo as situações mais comuns, e é isso que a configuração padrão fornece. No entanto, ele pode ser modificado se necessário (consulte Uso avançado para obter detalhes).
Etapa 1: configuração da versão padrão
Para configurar a versão padrão para as suas orquestrações, é necessário adicionar ou atualizar a definição defaultVersion no ficheiro host.json do seu projeto Azure Functions.
{
"extensions": {
"durableTask": {
"defaultVersion": "<version>"
}
}
}
A cadeia de caracteres de versão pode seguir qualquer formato que se adapte à sua estratégia de controle de versão:
- Versionamento multipartes:
"1.0.0","2.1.0" - Numeração simples:
"1","2" - Com base na data:
"2025-01-01" - Formato personalizado:
"v1.0-release"
Depois de definir o defaultVersion, todas as novas instâncias de orquestração serão permanentemente associadas a essa versão.
Regras de comparação de versões
Quando a Strict ou CurrentOrOlder estratégia é selecionada (consulte Version matching), o tempo de execução compara a versão da instância de orquestração com o defaultVersion valor do worker usando as seguintes regras:
- As versões vazias ou nulas são tratadas como iguais.
- Uma versão vazia ou nula é considerada mais antiga do que qualquer versão definida.
- Se ambas as versões puderem ser analisadas como
System.Version, oCompareTométodo será usado. - Caso contrário, a comparação de cadeia de caracteres sem diferenciação de maiúsculas e minúsculas será executada.
Etapa 2: Lógica da função do orquestrador
Para implementar a lógica com reconhecimento de versão em sua função de orquestrador, você pode usar o parâmetro de contexto passado para o orquestrador para acessar a versão da instância de orquestração atual, o que permite ramificar a lógica do orquestrador com base na versão.
Important
Ao implementar a lógica com reconhecimento de versão, é extremamente importante preservar a lógica exata do orquestrador para versões mais antigas. Quaisquer alterações na sequência, ordem ou assinatura de chamadas de atividade para versões existentes podem quebrar a repetição determinística e fazer com que as orquestrações em voo falhem ou produzam resultados incorretos. Os caminhos de código da versão antiga devem permanecer inalterados depois de implantados.
[Function("MyOrchestrator")]
public static async Task<string> RunOrchestrator(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
if (context.Version == "1.0")
{
// Original logic for version 1.0
...
}
else if (context.Version == "2.0")
{
// New logic for version 2.0
...
}
...
}
Note
A context.Version propriedade é somente leitura e reflete a versão que estava permanentemente associada à instância de orquestração quando ela foi criada. Não é possível modificar esse valor durante a execução da orquestração. Se desejar especificar uma versão por meios diferentes de host.json, poderá fazê-lo ao iniciar uma instância de orquestração com as APIs do cliente de orquestração (consulte Iniciar novas orquestrações e suborquestrações com versões específicas).
Tip
Se estás apenas a começar a usar a versão de orquestração e já tens orquestrações ativas que foram criadas antes de especificares um defaultVersion, ainda podes adicionar a configuração defaultVersion ao teu host.json agora. Para todas as orquestrações criadas anteriormente, context.Version retorna null (ou um valor equivalente dependente do idioma), para que você possa estruturar a lógica do orquestrador para lidar com as orquestrações herdadas (versão nula) e novas versões de acordo. A seguir estão os valores dependentes do idioma para verificar o caso herdado:
- C#:
context.Version == nulloucontext.Version is null - JavaScript:
context.df.version == null - Python:
context.version is None - PowerShell:
$null -eq $Context.Version - Java:
context.getVersion() == nullObserve também que especificar"defaultVersion": nullemhost.jsoné equivalente a não especificá-lo de todo.
Tip
Dependendo da sua situação, você pode preferir ramificar em diferentes níveis. Você pode fazer uma alteração local exatamente onde essa alteração é necessária, como mostra o exemplo. Como alternativa, você pode ramificar em um nível mais alto, mesmo no nível de implementação de todo o orquestrador, o que introduz alguma duplicação de código, mas pode manter o fluxo de execução claro. Cabe a você escolher a abordagem que melhor se adapta ao seu cenário e estilo de codificação.
O que acontece após a implantação
Veja o que esperar depois de implantar sua função de orquestrador atualizada com a nova lógica de versão:
Coexistência do trabalhador: Os trabalhadores que contêm o novo código de função do orquestrador serão iniciados, enquanto alguns trabalhadores com o código antigo ainda estão potencialmente ativos.
Atribuição de versão para novas instâncias: Todas as novas orquestrações e suborquestrações criadas pelos novos trabalhadores receberão a versão de
defaultVersionatribuída a elas.Compatibilidade dos Novos Trabalhadores: Os novos trabalhadores poderão processar as orquestrações recém-criadas e as orquestrações previamente existentes, pois as alterações realizadas na Etapa 2 da seção anterior garantem compatibilidade retroativa através de lógica ramificada ciente de versões.
Restrições de trabalhadores antigos: Os trabalhadores antigos terão permissão para processar apenas as orquestrações com uma versão igual ou inferior à versão especificada na sua própria versão em
defaultVersion, nohost.json, porque não devem ter código de orquestrador compatível com essas versões mais novas. Essa restrição evita erros de execução e comportamento inesperado.
Note
O controle de versão da orquestração não influencia o ciclo de vida do trabalhador. A plataforma Azure Functions gerencia o provisionamento e o descomissionamento de trabalhadores com base em regras regulares, dependendo das opções de hospedagem.
Exemplo: Substituindo uma atividade na sequência
Este exemplo mostra como substituir uma atividade por uma atividade diferente no meio de uma sequência usando o versionamento de orquestração.
Versão 1.0
configuração do host.json:
{
"extensions": {
"durableTask": {
"defaultVersion": "1.0"
}
}
}
Função orquestradora:
[Function("ProcessOrderOrchestrator")]
public static async Task<string> ProcessOrder(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
var orderId = context.GetInput<string>();
await context.CallActivityAsync("ValidateOrder", orderId);
await context.CallActivityAsync("ProcessPayment", orderId);
await context.CallActivityAsync("ShipOrder", orderId);
return "Order processed successfully";
}
Versão 2.0 com processamento de desconto
configuração do host.json:
{
"extensions": {
"durableTask": {
"defaultVersion": "2.0"
}
}
}
Função orquestradora:
using DurableTask.Core.Settings;
[Function("ProcessOrderOrchestrator")]
public static async Task<string> ProcessOrder(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
var orderId = context.GetInput<string>();
await context.CallActivityAsync("ValidateOrder", orderId);
if (VersioningSettings.CompareVersions(context.Version, "1.0") <= 0)
{
// Preserve original logic for existing instances
await context.CallActivityAsync("ProcessPayment", orderId);
}
else // a higher version (including 2.0)
{
// New logic with discount processing (replaces payment processing)
await context.CallActivityAsync("ApplyDiscount", orderId);
await context.CallActivityAsync("ProcessPaymentWithDiscount", orderId);
}
await context.CallActivityAsync("ShipOrder", orderId);
return "Order processed successfully";
}
Utilização avançada
Para cenários de controle de versão mais sofisticados, você pode definir outras configurações para controlar como o tempo de execução lida com correspondências e incompatibilidades de versão.
Tip
Use a configuração padrão (CurrentOrOlder com Reject) para a maioria dos cenários para permitir implantações contínuas seguras enquanto preserva o estado de orquestração durante as transições de versão. Recomendamos continuar com a configuração avançada somente se você tiver requisitos específicos que não podem ser atendidos com o comportamento padrão.
Correspondência de versões
A versionMatchStrategy configuração determina como o tempo de execução corresponde às versões de orquestração ao carregar funções do orquestrador. Ele controla quais instâncias de orquestração um trabalhador pode processar com base na compatibilidade de versão.
Configuration
{
"extensions": {
"durableTask": {
"defaultVersion": "<version>",
"versionMatchStrategy": "CurrentOrOlder"
}
}
}
Estratégias disponíveis
None(não recomendado): Ignore completamente a versão de orquestração. Todo o trabalho recebido é processado independentemente da versão. Essa estratégia efetivamente desabilita a verificação de versão e permite que qualquer trabalhador processe qualquer instância de orquestração.Strict: Processe tarefas das orquestrações com a mesma versão especificada pordefaultVersionnohost.jsondo trabalhador. Essa estratégia fornece o mais alto nível de isolamento de versão, mas requer uma coordenação de implantação cuidadosa para evitar orquestrações órfãs. As consequências da incompatibilidade de versão são descritas na seção Tratamento de incompatibilidade de versão .CurrentOrOlder(padrão): processamento de tarefas de orquestrações cuja versão seja menor ou igual à versão especificada pelodefaultVersionno trabalhadorhost.json. Essa estratégia permite a compatibilidade com versões anteriores, permitindo que os trabalhadores mais novos lidem com orquestrações iniciadas por versões mais antigas do orquestrador, ao mesmo tempo em que impede que os trabalhadores mais velhos processem orquestrações mais recentes. As consequências da incompatibilidade de versão são descritas na seção Tratamento de incompatibilidade de versão .
Tratamento de incompatibilidade de versões
A versionFailureStrategy configuração determina o que acontece quando uma versão de instância de orquestração não corresponde à atual defaultVersion.
Configuration:
{
"extensions": {
"durableTask": {
"defaultVersion": "<version>",
"versionFailureStrategy": "Reject"
}
}
}
Estratégias disponíveis:
Reject(padrão): não processe a orquestração. A instância de orquestração permanece em seu estado atual e pode ser repetida mais tarde, quando um trabalhador compatível estiver disponível. Esta estratégia é a opção mais segura, pois preserva o estado de orquestração.Fail: Falha na orquestração. Essa estratégia encerra imediatamente a instância de orquestração com um estado de falha, o que pode ser apropriado em cenários em que incompatibilidades de versão indicam sérios problemas de implantação.
Iniciar novas orquestrações e sub-orquestrações com versões específicas
Por padrão, todas as novas instâncias de orquestração são criadas com a atual defaultVersion especificada na sua host.json configuração. No entanto, você pode ter cenários em que precisa criar orquestrações com uma versão específica, mesmo que ela seja diferente do padrão atual.
Quando usar versões específicas:
- Migração gradual: você deseja continuar criando orquestrações com uma versão mais antiga mesmo depois de implantar uma versão mais recente.
- Cenários de teste: você precisa testar o comportamento de versão específica na produção.
- Situações de reversão: você precisa reverter temporariamente para a criação de instâncias com uma versão anterior.
- Fluxos de trabalho específicos da versão: diferentes processos de negócios exigem diferentes versões de orquestração.
Você pode substituir a versão padrão fornecendo um valor de versão específico ao criar novas instâncias de orquestração usando as APIs do cliente de orquestração. Isso permite um controle refinado sobre qual versão cada nova instância de orquestração usa.
[Function("HttpStart")]
public static async Task<HttpResponseData> HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req,
[DurableClient] DurableTaskClient client,
FunctionContext executionContext)
{
var options = new StartOrchestrationOptions
{
Version = "1.0"
};
string instanceId = await client.ScheduleNewOrchestrationInstanceAsync("ProcessOrderOrchestrator", orderId, options);
// ...
}
Você também pode iniciar suborquestrações com versões específicas a partir de uma função de orquestração.
[Function("MainOrchestrator")]
public static async Task<string> RunMainOrchestrator(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
var subOptions = new SubOrchestratorOptions
{
Version = "1.0"
};
var result = await context.CallSubOrchestratorAsync<string>("ProcessPaymentOrchestrator", orderId, subOptions);
// ...
}
Removendo caminhos de código herdados
Com o tempo, você pode querer remover caminhos de código herdados de suas funções de orquestrador para simplificar a manutenção e reduzir a dívida técnica. No entanto, a remoção do código deve ser feita com cuidado para evitar a quebra de instâncias de orquestração existentes.
Quando é seguro remover o código herdado:
- Todas as instâncias de orquestração usando a versão antiga foram concluídas (bem-sucedidas, falhadas ou encerradas)
- Nenhuma nova instância de orquestração será criada com a versão antiga
- Você verificou por meio de monitoramento ou consulta que nenhuma instância está sendo executada com a versão herdada
- Um período de tempo suficiente se passou desde que a versão antiga foi implantada pela última vez (considerando seus requisitos de continuidade de negócios)
Práticas recomendadas para remoção:
- Monitorar instâncias em execução ativa: use as APIs de gerenciamento do Durable Functions para consultar instâncias usando versões específicas.
- Definir políticas de retenção: defina por quanto tempo você pretende manter a compatibilidade com versões anteriores para cada versão.
- Remover incrementalmente: considere remover uma versão de cada vez, em vez de várias versões simultaneamente.
- Remoção de documentos: mantenha registros claros de quando as versões foram removidas e por quê.
Warning
A remoção de caminhos de código herdados enquanto as instâncias de orquestração ainda estão executando essas versões pode causar falhas de repetição determinística ou comportamento inesperado. Sempre verifique se nenhuma instância está usando a versão herdada antes de remover o código.
Melhores práticas
Gerenciamento de versões
-
Use o versionamento com múltiplas partes: adote um esquema de versionamento consistente como
major.minor.patch. - Documentar alterações significativas: Documente claramente quais alterações exigem uma nova versão.
- Planejar o ciclo de vida da versão: defina quando remover caminhos de código herdados.
Organização de código
- Lógica de versão separada: use ramificações claras ou métodos separados para versões diferentes.
- Preservar o determinismo: evite modificar a lógica da versão existente depois de implantada. Se as alterações forem absolutamente necessárias (como correções de bugs críticos), certifique-se de que elas mantenham o comportamento determinístico e não alterem a sequência de operações, ou espere que as versões mais recentes do orquestrador falhem ao processar orquestrações mais antigas.
- Teste minuciosamente: teste todos os caminhos de versão, especialmente durante as transições.
Monitorização e observabilidade
- Informações de versão do log: inclua a versão em seu log para facilitar a depuração.
- Monitore a distribuição de versões: rastreie quais versões estão sendo executadas ativamente.
- Configurar alertas: monitore quaisquer erros relacionados à versão.
Troubleshooting
Problemas comuns
Problema: as instâncias de orquestração criadas com a versão 1.0 estão falhando após a implantação da versão 2.0
- Solução: Certifique-se de que o caminho do código da versão 1.0 no seu orquestrador permaneça exatamente o mesmo. Quaisquer alterações na sequência de execução podem quebrar a repetição determinística.
Problema: os trabalhadores que executam versões mais antigas do orquestrador não podem executar novas orquestrações
-
Solução: Este é um comportamento esperado. O tempo de execução impede intencionalmente que os trabalhadores mais velhos executem orquestrações com versões mais recentes para manter a segurança. Certifique-se de que todos os trabalhadores estejam atualizados para a versão mais recente do orchestrator e que sua
defaultVersionconfiguraçãohost.jsonseja atualizada de acordo. Você pode modificar esse comportamento, se necessário, usando as opções de configuração avançadas (consulte Uso avançado para obter detalhes).
-
Solução: Este é um comportamento esperado. O tempo de execução impede intencionalmente que os trabalhadores mais velhos executem orquestrações com versões mais recentes para manter a segurança. Certifique-se de que todos os trabalhadores estejam atualizados para a versão mais recente do orchestrator e que sua
Problema: as informações de versão não estão disponíveis no orchestrator (
context.Versionoucontext.getVersion()é nulo, independentemente da configuração dedefaultVersion)- Solução: verifique a secção Pré-requisitos para garantir que o seu ambiente atende a todos os requisitos para a versão de orquestração.
Problema: as orquestrações de uma versão mais recente estão progredindo muito lentamente ou estão completamente paradas
-
Solução: O problema pode ter diferentes causas profundas:
-
Trabalhadores mais novos insuficientes: certifique-se de que estejam
defaultVersionimplantados e ativos um número suficiente de trabalhadores com uma versão igual ou superior para lidar com as orquestrações mais recentes. - Interferência no roteamento de orquestração por trabalhadores mais velhos: Trabalhadores antigos podem interferir no mecanismo de roteamento de orquestração, dificultando a execução de tarefas de orquestração pelos novos trabalhadores. Isso pode ser especialmente percetível ao usar determinados provedores de armazenamento (Armazenamento do Azure ou MSSQL). Normalmente, a plataforma Azure Functions garante que os trabalhadores antigos sejam eliminados logo após uma implantação, portanto, qualquer atraso normalmente não é significativo. No entanto, se estiver a utilizar uma configuração que lhe permita controlar o ciclo de vida dos trabalhadores mais velhos, certifique-se de que os trabalhadores mais velhos são eventualmente encerrados. Como alternativa, considere usar o Agendador de Tarefas Duráveis, pois ele fornece um mecanismo de roteamento aprimorado que é menos suscetível a esse problema.
-
Trabalhadores mais novos insuficientes: certifique-se de que estejam
-
Solução: O problema pode ter diferentes causas profundas: