Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
El control de versiones de orquestación aborda el desafío principal de implementar cambios en las funciones del orquestador mientras se mantiene el modelo de ejecución determinista que requiere Durable Functions. Sin esta característica, los cambios importantes en la lógica del orquestador o las firmas de función de actividad provocarían un error en las instancias de orquestación en curso durante la reproducción porque interrumpirían el requisito de determinismo que garantiza una ejecución confiable de orquestación. Esta característica integrada proporciona aislamiento automático de versiones con una configuración mínima. Es independiente del back-end, por lo que se puede usar mediante aplicaciones que aprovechan cualquiera de los proveedores de almacenamiento de Durable Function, incluido el Programador de tareas durables.
Note
Para los usuarios de Durable Task Scheduler, si usa los SDK de Durable Task en lugar de Durable Functions, debe consultar el artículo sobre el control de versiones de SDK de Durable Task.
Terminology
En este artículo se usan dos términos relacionados pero distintos:
- Función de orquestador (o simplemente "orquestador"): hace referencia al código de función que define la lógica del flujo de trabajo: la plantilla o el plano técnico para cómo se debe ejecutar un flujo de trabajo.
- Instancia de orquestación (o simplemente "orquestación"): hace referencia a una ejecución específica de una función de orquestador, con su propio estado, identificador de instancia y entradas. Varias instancias de orquestación se pueden ejecutar simultáneamente desde la misma función de orquestador.
Comprender esta distinción es fundamental para el control de versiones de orquestación, donde el código de la función del orquestador contiene lógica compatible con versiones, mientras que las instancias de orquestación están asociadas permanentemente a una versión específica cuando se crean.
Cómo funciona
Los principios básicos sobre los que opera la funcionalidad de control de versiones de orquestación son los siguientes:
Asociación de versiones: cuando se crea una instancia de orquestación, obtiene una versión asociada permanentemente a ella.
Ejecución sensible a versiones: el código de la función de Orchestrator puede examinar el valor de versión asociado a la instancia de orquestación actual y ramificar la ejecución según corresponda.
Compatibilidad con versiones anteriores: Los trabajadores que utilizan versiones más recientes del orquestador pueden seguir ejecutando instancias de orquestación creadas con versiones anteriores del orquestador.
Protección hacia adelante: El tiempo de ejecución previene automáticamente que los trabajadores que usan versiones anteriores del orquestador ejecuten orquestaciones iniciadas por versiones más recientes del orquestador.
Important
El control de versiones de orquestación se encuentra actualmente en versión preliminar pública.
Prerrequisitos
Antes de usar el versionado de orquestación, asegúrese de tener las versiones de paquete necesarias para el lenguaje de programación.
Si usa un lenguaje non-.NET (JavaScript, Python, PowerShell o Java) con agrupaciones de extensiones, la aplicación de funciones debe hacer referencia a la versión 4.26.0 o posterior del paquete de extensiones. Configure el extensionBundle intervalo en host.json para que la versión mínima sea al menos 4.26.0, por ejemplo:
{
"version": "2.0",
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.26.0, 5.0.0)"
}
}
Consulte la documentación de configuración del paquete de extensiones para obtener más información sobre cómo elegir y actualizar las versiones de lote.
Utilice Microsoft.Azure.Functions.Worker.Extensions.DurableTask la versión 1.5.0 o posterior.
Uso básico
El caso de uso más común para el control de versiones de orquestación es cuando necesita realizar cambios importantes en la lógica del orquestador mientras mantiene las instancias de orquestación en curso existentes que se ejecutan con su versión original. Lo único que debe hacer es actualizar defaultVersion en host.json y modificar el código del orquestador para comprobar la versión de orquestación y la ejecución de la rama en consecuencia. Vamos a recorrer los pasos necesarios.
Note
El comportamiento descrito en esta sección tiene como destino las situaciones más comunes y esto es lo que proporciona la configuración predeterminada. Sin embargo, se puede modificar si es necesario (consulte Uso avanzado para obtener más información).
Paso 1: configuración de la versión predeterminada
Para configurar la versión predeterminada para las orquestaciones, debe agregar o actualizar la defaultVersion configuración en el host.json archivo del proyecto de Azure Functions:
{
"extensions": {
"durableTask": {
"defaultVersion": "<version>"
}
}
}
La cadena de versión puede seguir cualquier formato que se adapte a la estrategia de control de versiones:
- Versionamiento multiparte:
"1.0.0","2.1.0" - Numeración simple:
"1","2" - Basado en fechas:
"2025-01-01" - Formato personalizado:
"v1.0-release"
Después de establecer el defaultVersion, todas las nuevas instancias de orquestación se asociarán permanentemente a esa versión.
Reglas de comparación de versiones
Cuando se selecciona la estrategia Strict o CurrentOrOlder (consulte Coincidencia de versiones), el entorno de ejecución compara la versión de la instancia de orquestación con el valor del trabajador defaultVersion mediante las siguientes reglas:
- Las versiones vacías o nulas se tratan como iguales.
- Una versión vacía o nula se considera anterior a cualquier versión definida.
- Si ambas versiones se pueden analizar como
System.Version, se usa elCompareTométodo . - De lo contrario, se realiza una comparación de cadenas que no distingue mayúsculas de minúsculas.
Paso 2: Lógica de la función del Orchestrator
Para implementar la lógica compatible con versiones en la función de orquestador, puede usar el parámetro de contexto pasado al orquestador para acceder a la versión de la instancia de orquestación actual, lo que le permite bifurcar la lógica del orquestador en función de la versión.
Important
Al implementar la lógica compatible con versiones, es fundamental conservar la lógica exacta del orquestador para versiones anteriores. Los cambios en la secuencia, el orden o la firma de las llamadas de actividad para las versiones existentes pueden interrumpir la reproducción determinista y provocar que las orquestaciones en curso produzcan errores o generen resultados incorrectos. Las rutas de acceso de código de la versión anterior deben permanecer sin cambios una vez implementadas.
[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
La propiedad context.Version es de solo lectura y refleja la versión asociada permanentemente a la instancia de orquestación cuando se creó. No se puede modificar este valor durante la ejecución de la orquestación. Si desea especificar una versión a través de medios distintos de host.json, puede hacerlo al iniciar una instancia de orquestación con las API del cliente de orquestación (consulte Inicio de nuevas orquestaciones y suborquestaciones con versiones específicas).
Tip
Si acaba de empezar a usar el control de versiones de orquestación y ya tiene orquestaciones en curso que se crearon antes de especificar un defaultVersion, todavía puede agregar el valor defaultVersion a host.json ahora. Para todas las orquestaciones creadas anteriormente, context.Version devuelve null (o un valor equivalente dependiente del idioma), por lo que puede estructurar la lógica del orquestador para controlar tanto las orquestaciones heredadas (versión nula) como las nuevas orquestaciones con versiones en consecuencia. A continuación se muestran los valores dependientes del idioma para comprobar el caso heredado:
- C#:
context.Version == nullocontext.Version is null - JavaScript:
context.df.version == null - Pitón:
context.version is None - PowerShell:
$null -eq $Context.Version - Java:
context.getVersion() == nulltenga en cuenta también que especificar"defaultVersion": nullenhost.jsones equivalente a no especificarlo en absoluto.
Tip
Dependiendo de su situación, puede preferir la bifurcación en diferentes niveles. Puede realizar un cambio local exactamente donde se requiere este cambio, como se muestra en el ejemplo. Como alternativa, puede hacer una bifurcación en un nivel más alto, incluso en el nivel de implementación del orquestador, lo que introduce cierta duplicación de código, pero puede mantener el flujo de ejecución claro. Es necesario elegir el enfoque que mejor se adapte a su escenario y estilo de codificación.
¿Qué ocurre después de la implementación?
Esto es lo que debe esperar una vez que implemente la función de orquestador actualizada con la nueva lógica de versión:
Coexistencia de trabajo: los trabajos que contienen el nuevo código de función de orquestador se iniciarán, mientras que algunos trabajos con el código anterior todavía están activos.
Asignación de versiones para nuevas instancias: todas las nuevas orquestaciones y suborquestaciones creadas por los nuevos trabajos obtendrán la versión de
defaultVersionasignada a ellas.Compatibilidad de Nuevos Trabajadores: Los nuevos trabajadores podrán procesar tanto las orquestaciones recién creadas como las previamente existentes, porque los cambios realizados en el Paso 2 de la sección anterior garantizan la compatibilidad retroactiva mediante lógica de ramificación consciente de las versiones.
Restricciones para Trabajadores Antiguos: los trabajadores antiguos solo podrán procesar las orquestaciones con una versión igual o inferior a la versión especificada en su propio
defaultVersionenhost.json, ya que no se espera que tengan código de orquestador compatible con versiones más recientes. Esta restricción impide errores de ejecución y comportamiento inesperado.
Note
El control de versiones de orquestación no influye en el ciclo de vida del trabajo. La plataforma Azure Functions administra la provisión y descomisionamiento de trabajadores según las reglas habituales dependiendo de las opciones de hospedaje.
Ejemplo: Reemplazo de una actividad en la secuencia
En este ejemplo se muestra cómo reemplazar una actividad por una actividad diferente en medio de una secuencia mediante el versionado de orquestaciones.
Versión 1.0
host.json configuración:
{
"extensions": {
"durableTask": {
"defaultVersion": "1.0"
}
}
}
Función de orquestador:
[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";
}
Versión 2.0 con procesamiento de descuentos
host.json configuración:
{
"extensions": {
"durableTask": {
"defaultVersion": "2.0"
}
}
}
Función de orquestador:
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";
}
Uso avanzado
Para escenarios de administración de versiones más sofisticados, puede configurar otras opciones para definir cómo maneja el tiempo de ejecución las coincidencias y conflictos de versiones.
Tip
Use la configuración predeterminada (CurrentOrOlder con Reject) para la mayoría de los escenarios para habilitar implementaciones graduales seguras al tiempo que conserva el estado de orquestación durante las transiciones de versión. Se recomienda continuar con la configuración avanzada solo si tiene requisitos específicos que no se pueden cumplir con el comportamiento predeterminado.
Coincidencia de versiones
La versionMatchStrategy configuración determina cómo el tiempo de ejecución coincide con las versiones de orquestación al cargar funciones de orquestador. Controla qué instancias de orquestación puede procesar un trabajador en función de la compatibilidad de versiones.
Configuration
{
"extensions": {
"durableTask": {
"defaultVersion": "<version>",
"versionMatchStrategy": "CurrentOrOlder"
}
}
}
Estrategias disponibles
None(no recomendado): omita completamente la versión de orquestación. Todo el trabajo recibido se procesa independientemente de la versión. Esta estrategia deshabilita eficazmente la comprobación de versiones y permite que cualquier trabajo procese cualquier instancia de orquestación.Strict: solo procesa las tareas de las orquestaciones con la misma versión exacta que la versión especificada pordefaultVersionen el objetohost.jsondel trabajo. Esta estrategia proporciona el nivel más alto de aislamiento de versión, pero requiere una coordinación cuidadosa de la implementación para evitar orquestaciones huérfanas. Las consecuencias de la falta de coincidencia de versiones se describen en la sección Control de errores de coincidencia de versiones.CurrentOrOlder(valor predeterminado): procese tareas de orquestaciones cuya versión sea menor o igual que la versión especificada pordefaultVersionen el objetohost.jsondel trabajo. Esta estrategia permite la compatibilidad con versiones anteriores, lo que permite a los trabajadores más recientes controlar las orquestaciones iniciadas por versiones anteriores del orquestador, a la vez que impide que los trabajadores más antiguos procesen orquestaciones más recientes. Las consecuencias de la falta de coincidencia de versiones se describen en la sección Control de errores de coincidencia de versiones.
Gestión de desajustes de versiones
La versionFailureStrategy configuración determina lo que sucede cuando una versión de instancia de orquestación no coincide con el actual defaultVersion.
Configuration:
{
"extensions": {
"durableTask": {
"defaultVersion": "<version>",
"versionFailureStrategy": "Reject"
}
}
}
Estrategias disponibles:
Reject(valor predeterminado): no procese la orquestación. La instancia de orquestación permanece en su estado actual y se puede reintentar más adelante cuando un trabajador compatible esté disponible. Esta estrategia es la opción más segura, ya que conserva el estado de orquestación.Fail: se produce un error en la orquestación. Esta estrategia finaliza inmediatamente la instancia de orquestación con un estado de error, que puede ser adecuado en escenarios en los que los errores de coincidencia de versiones indican problemas graves de implementación.
Inicio de nuevas orquestaciones y suborquestaciones con versiones específicas
De manera predeterminada, todas las nuevas instancias de orquestación se crean con el objeto defaultVersion actual especificado en la configuración host.json. Sin embargo, puede tener escenarios en los que necesite crear orquestaciones con una versión específica, incluso si difiere del valor predeterminado actual.
Cuándo usar versiones específicas:
- Migración gradual: quiere seguir creando orquestaciones con una versión anterior incluso después de implementar una versión más reciente.
- Escenarios de prueba: debe probar un comportamiento de versión específico en producción.
- Situaciones de reversión: debe revertir temporalmente a la creación de instancias con una versión anterior.
- Flujos de trabajo específicos de la versión: los distintos procesos empresariales requieren diferentes versiones de orquestación.
Puede invalidar la versión predeterminada proporcionando un valor de versión específico al crear nuevas instancias de orquestación mediante las API del cliente de orquestación. Esto permite un control específico sobre qué versión usa cada nueva instancia de orquestación.
[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);
// ...
}
También puede iniciar suborquestaciones con versiones específicas desde una función de orquestador:
[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);
// ...
}
Eliminación de rutas de código antiguo
Con el tiempo, es posible que desee quitar rutas de acceso de código heredadas de las funciones de orquestador para simplificar el mantenimiento y reducir la deuda técnica. Sin embargo, la eliminación del código debe realizarse cuidadosamente para evitar interrumpir las instancias de orquestación existentes.
Cuando sea seguro quitar código heredado:
- Todas las instancias de orquestación que usan la versión anterior han finalizado (se han completado con éxito, han fallado o han sido terminadas)
- No se crearán nuevas instancias de orquestación con la versión anterior.
- Ha comprobado a través de la supervisión o consulta que ninguna instancia se ejecuta con la versión antigua.
- Ha transcurrido un período de tiempo suficiente desde que se implementó por última vez la versión anterior (teniendo en cuenta los requisitos de continuidad empresarial).
Procedimientos recomendados para la eliminación:
- Supervisión de instancias en ejecución activa: use las API de administración de Durable Functions para consultar instancias mediante versiones específicas.
- Establecer directivas de retención: defina cuánto tiempo pretende mantener la compatibilidad con versiones anteriores para cada versión.
- Quitar incrementalmente: considere la posibilidad de quitar una versión a la vez en lugar de varias versiones simultáneamente.
- Eliminación de documentos: mantenga registros claros de cuándo se quitaron las versiones y por qué.
Warning
Eliminar rutas de código heredadas mientras las instancias de orquestación aún están ejecutando esas versiones puede provocar fallos de reproducción deterministas o un comportamiento inesperado. Compruebe siempre que ninguna instancia use la versión heredada antes de quitar el código.
procedimientos recomendados
Administración de versiones
-
Usar versionado de varias partes: adopte un esquema de versionado coherente como
major.minor.patch. - Cambios importantes en el documento: documente claramente qué cambios requieren una nueva versión.
- Plan de ciclo de vida de la versión: defina cuándo quitar rutas de acceso de código heredadas.
Organización del código
- Lógica de versiones separadas: use ramas claras o métodos separados para versiones distintas.
- Conservar el determinismo: evite modificar la lógica de versión existente una vez implementada. Si los cambios son absolutamente necesarios (por ejemplo, correcciones de errores críticos), asegúrese de mantener un comportamiento determinista y no modifique la secuencia de operaciones, o espere que las versiones de orquestador más recientes produzcan errores al procesar orquestaciones anteriores.
- Prueba exhaustiva: Pruebe todas las rutas de acceso de versión, especialmente durante las transiciones.
Supervisión y observabilidad
- Información de la versión de registro: incluya la versión en el registro para facilitar la depuración.
- Supervisión de la distribución de versiones: realice un seguimiento de las versiones que se están ejecutando activamente.
- Configurar alertas: monitorear errores relacionados con versiones.
Troubleshooting
Problemas comunes
Problema: Las instancias de orquestación creadas con la versión 1.0 no se pueden realizar después de implementar la versión 2.0
- Solución: asegúrese de que la ruta de acceso de código de la versión 1.0 del orquestador sigue siendo exactamente la misma. Cualquier cambio en la secuencia de ejecución puede interrumpir la reproducción determinista.
Problema: Los operarios que ejecutan versiones anteriores del orquestador no pueden ejecutar nuevas orquestaciones
-
Solución: este es el comportamiento esperado. El tiempo de ejecución impide intencionadamente que los trabajadores más antiguos ejecuten orquestaciones con versiones más recientes para mantener la seguridad. Asegúrese de que todos los trabajadores se actualicen a la versión más reciente del orquestador y que su configuración
defaultVersionenhost.jsonse actualice en consecuencia. Puede modificar este comportamiento si es necesario mediante las opciones de configuración avanzadas (consulte Uso avanzado para obtener más información).
-
Solución: este es el comportamiento esperado. El tiempo de ejecución impide intencionadamente que los trabajadores más antiguos ejecuten orquestaciones con versiones más recientes para mantener la seguridad. Asegúrese de que todos los trabajadores se actualicen a la versión más reciente del orquestador y que su configuración
Problema: la información de versión no está disponible en orchestrator (
context.Versionocontext.getVersion()es null, independientemente de ladefaultVersionconfiguración)- Solución: compruebe la sección Requisitos previos para asegurarse de que el entorno cumple todos los requisitos para el control de versiones de orquestación.
Problema: las orquestaciones de una versión más reciente están realizando un progreso muy lento o están completamente bloqueadas
-
Solución: el problema puede tener diferentes causas principales:
-
Trabajos más recientes insuficientes: asegúrese de que se implementen y activen un número suficiente de trabajos que contengan una versión igual o superior en
defaultVersionpara controlar las orquestaciones más recientes. - Interferencia de enrutamiento de orquestación de los trabajos más antiguos: los trabajos antiguos pueden interferir con el mecanismo de enrutamiento de orquestación, lo que dificulta que los nuevos trabajadores recojan orquestaciones para su procesamiento. Esto puede ser especialmente notable cuando se usan determinados proveedores de almacenamiento (Azure Storage o MSSQL). Normalmente, la plataforma Azure Functions garantiza que los trabajos antiguos se eliminen poco después de una implementación, por lo que normalmente cualquier retraso no es significativo. Sin embargo, si usa una configuración que le permite controlar el ciclo de vida de los trabajadores más antiguos, asegúrese de que los trabajadores más antiguos se cierren eventualmente. Como alternativa, considere la posibilidad de usar durable Task Scheduler, ya que proporciona un mecanismo de enrutamiento mejorado que es menos susceptible a este problema.
-
Trabajos más recientes insuficientes: asegúrese de que se implementen y activen un número suficiente de trabajos que contengan una versión igual o superior en
-
Solución: el problema puede tener diferentes causas principales: