Enlaces para Durable Functions (Azure Functions)

La extensión Durable Functions presenta tres enlaces de desencadenador que controlan la ejecución de las funciones de orquestador, entidad y actividad. También presenta a un enlace de salida que actúa como un cliente para el tiempo de ejecución de Durable Functions.

Desencadenador de orquestación

El desencadenador de orquestación permite crear funciones de orquestador durables. Este desencadenador se ejecuta cuando se programa una nueva instancia de orquestación o cuando una ya existente recibe un evento. Entre los ejemplos de eventos que pueden desencadenar funciones de orquestador se incluyen expiraciones de temporizadores de larga duración, respuestas de funciones de actividades y eventos desencadenados por clientes externos.

Al crear funciones en .NET, el desencadenador de orquestación se configura mediante el atributo OrchestrationTriggerAttribute de .NET. Para Java, se usa la anotación @DurableOrchestrationTrigger.

Al escribir funciones de orquestador en lenguajes de scripting como JavaScript, Python o PowerShell, el desencadenador de orquestación se define mediante el objeto JSON siguiente de la matriz bindings del archivo function.json:

{
    "name": "<Name of input parameter in function signature>",
    "orchestration": "<Optional - name of the orchestration>",
    "type": "orchestrationTrigger",
    "direction": "in"
}
  • orchestration es el nombre de la orquestación que los clientes tienen que usar cuando quieren iniciar nuevas instancias de esta función de orquestador. Esta propiedad es opcional. Si no se especifica, se utiliza el nombre de la función.

Internamente, este enlace de desencadenador sondea el almacén de larga duración configurado en busca de nuevos eventos de orquestación, como eventos de inicio de orquestación, eventos de expiración de temporizadores de larga duración, eventos de respuestas de funciones de actividades y eventos externos desencadenados por otras funciones.

Comportamiento de un desencadenador

Estas son algunas notas acerca del desencadenador de orquestación:

  • Subprocesamiento único: un único subproceso de distribución se usa para toda la ejecución de función del orquestador en una instancia de host. Por esta razón, es importante asegurarse de que el código de función del orquestador es eficaz y no realiza ninguna E/S. También es importante asegurarse de que este subproceso no realizar ningún trabajo asincrónico excepto cuando se espera en tipos de tareas específicos de Durable Functions.
  • Control de mensajes dudosos: no hay compatibilidad con mensajes dudosos en los desencadenadores de orquestación.
  • Visibilidad de los mensajes: los mensajes de desencadenador de orquestación se quitan de la cola y se mantienen invisibles durante un tiempo configurable. La visibilidad de estos mensajes se renueva automáticamente siempre que la aplicación de la función se esté ejecutando y se mantenga correcta.
  • Valores devueltos: los valores devueltos se serializan en JSON y se conservan en la tabla de historial de orquestación en Azure Table Storage. Estos valores devueltos pueden ser consultados por el enlace de cliente de orquestación que se describe más adelante.

Advertencia

Las funciones del orquestador nunca deben usar ningún enlace de entrada o salida que no sea el enlace de desencadenador de orquestación. Si lo hacen, existe la posibilidad de que se produzcan problemas con la extensión Durable Task porque esos enlaces pueden no seguir las reglas de E/S y subprocesamiento único. Si desea usar otros enlaces, agréguelos a una función de actividad llamada desde la función de orquestador. Para más información sobre las restricciones de código de las funciones de orquestador, consulte Restricciones de código de las funciones de orquestador.

Advertencia

Las funciones de orquestador de JavaScript y Python nunca se deberían declarar async.

Uso del desencadenador

El enlace de desencadenador de orquestación admite entradas y salidas. Estas son algunas cosas que hay que saber acerca del control de entradas y salidas:

  • entradas: los desencadenadores de orquestación se pueden invocar con entradas a las que se accede a través del objeto de entrada de contexto. Todas las entradas tienen que ser serializables con JSON.
  • salidas: los desencadenadores de orquestación admiten valores de salida, así como de entrada. El valor devuelto de la función se utiliza para asignar el valor de salida y tiene que ser serializable con JSON.

Ejemplo de desencadenador

El código de ejemplo siguiente muestra el aspecto que podría tener la función del orquestador más simple "Hola mundo". Tenga en cuenta que este orquestador de ejemplo no programa realmente ninguna tarea.

[FunctionName("HelloWorld")]
public static string Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    string name = context.GetInput<string>();
    return $"Hello {name}!";
}

Nota

El código anterior corresponde a Durable Functions 2.x. En el caso de Durable Functions 1.x, debe usar DurableOrchestrationContext en lugar de IDurableOrchestrationContext. Para obtener más información sobre las diferencias entre versiones, vea el artículo Versiones de Durable Functions.

La mayoría de las funciones del orquestador llaman a funciones de actividad, por lo que aquí tenemos un ejemplo de "Hola mundo" que muestra cómo llamar a una función de actividad:

[FunctionName("HelloWorld")]
public static async Task<string> Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    string name = context.GetInput<string>();
    string result = await context.CallActivityAsync<string>("SayHello", name);
    return result;
}

Nota

El código anterior corresponde a Durable Functions 2.x. En el caso de Durable Functions 1.x, debe usar DurableOrchestrationContext en lugar de IDurableOrchestrationContext. Para obtener más información sobre las diferencias entre versiones, vea el artículo Versiones de Durable Functions.

Desencadenador de actividad

El desencadenador de actividad le permite crear funciones que las funciones del orquestador llaman, conocidas como funciones de actividad.

Si va a crear funciones en .NET, el desencadenador de actividad se configura mediante el atributo ActvityTriggerAttribute de .NET. Para Java, se usa la anotación @DurableActivityTrigger.

Si utiliza JavaScript, Python o PowerShell, el desencadenador de actividad se definirá mediante el objeto JSON siguiente en la matriz bindings de function.json:

{
    "name": "<Name of input parameter in function signature>",
    "activity": "<Optional - name of the activity>",
    "type": "activityTrigger",
    "direction": "in"
}
  • activityes el nombre de la actividad. Este valor es el nombre que utilizan las funciones del orquestador para invocar esta función de actividad. Esta propiedad es opcional. Si no se especifica, se utiliza el nombre de la función.

Internamente, este enlace de desencadenador sondea el almacén de larga duración configurado para los nuevos eventos de ejecución de actividad.

Comportamiento de un desencadenador

Estas son algunas notas acerca del desencadenador de actividad:

  • Subprocesamiento: a diferencia del desencadenador de orquestación, los desencadenadores de actividad no tienen ninguna restricción en relación a los subprocesos o E/S. Se puede tratar como funciones normales.
  • Control de mensajes dudosos: no hay compatibilidad con mensajes dudosos en los desencadenadores de actividad.
  • Visibilidad de los mensajes: los mensajes de desencadenador de actividad se quitan de la cola y se mantienen invisibles durante un tiempo configurable. La visibilidad de estos mensajes se renueva automáticamente siempre que la aplicación de la función se esté ejecutando y se mantenga correcta.
  • Valores devueltos: los valores devueltos se serializan en JSON y se conservan en el almacenamiento de larga duración configurado.

Uso del desencadenador

El enlace de desencadenador de actividad admite entradas y salidas como el desencadenador de orquestación. Estas son algunas cosas que hay que saber acerca del control de entradas y salidas:

  • entradas: los desencadenadores de actividad se pueden invocar con entradas desde una función del orquestador. Todas las entradas tienen que ser serializables con JSON.
  • salidas: las funciones de actividad admiten valores de salida, así como de entrada. El valor devuelto de la función se utiliza para asignar el valor de salida y tiene que ser serializable con JSON.
  • metadatos: las funciones de actividad de .NET pueden enlazar a un parámetro string instanceId para obtener el identificador de la instancia de la orquestación que llama.

Ejemplo de desencadenador

El ejemplo de código siguiente muestra el aspecto que podría tener una función de actividad simple SayHello:

[FunctionName("SayHello")]
public static string SayHello([ActivityTrigger] IDurableActivityContext helloContext)
{
    string name = helloContext.GetInput<string>();
    return $"Hello {name}!";
}

El tipo de parámetro predeterminado para el enlace ActivityTriggerAttribute de .NET es IDurableActivityContext (o DurableActivityContext para Durable Functions v1). Sin embargo, los desencadenadores de actividad de .NET también admiten enlazar directamente con tipos serializables con JSON (incluidos los tipos primitivos), por lo que la misma función podría simplificarse como sigue:

[FunctionName("SayHello")]
public static string SayHello([ActivityTrigger] string name)
{
    return $"Hello {name}!";
}

Uso de enlaces de entrada y de salida

Puede usar los enlaces de entrada y salida normales además del enlace de desencadenador de actividad. Por ejemplo, puede tomar la entrada del enlace de actividad y enviar un mensaje a un objeto EventHub mediante el enlace de salida de EventHub:

{
  "bindings": [
    {
      "name": "message",
      "type": "activityTrigger",
      "direction": "in"
    },
    {
      "type": "eventHub",
      "name": "outputEventHubMessage",
      "connection": "EventhubConnectionSetting",
      "eventHubName": "eh_messages",
      "direction": "out"
  }
  ]
}
module.exports = async function (context) {
    context.bindings.outputEventHubMessage = context.bindings.message;
};

Cliente de orquestación

El enlace del cliente de orquestación le permite escribir funciones que interactúan con las funciones del orquestador. Estas funciones se conocen a menudo como funciones de cliente. Por ejemplo, puede actuar en las instancias de orquestación de las siguientes formas:

  • Iniciarlas.
  • Consultar su estado.
  • Finalizarlas.
  • Enviarles eventos mientras se están ejecutando.
  • Purgar del historial de instancias.

Si usa .NET, puede enlazar con el cliente de orquestación mediante el atributo DurableClientAttribute (OrchestrationClientAttribute en Durable Functions v1.x). Para Java, use la anotación @DurableClientInput.

Si utiliza lenguajes de scripting como JavaScript, Python o PowerShell, el desencadenador del cliente de larga duración se definirá mediante el objeto JSON siguiente en la matriz bindings de function.json:

{
    "name": "<Name of input parameter in function signature>",
    "taskHub": "<Optional - name of the task hub>",
    "connectionName": "<Optional - name of the connection string app setting>",
    "type": "orchestrationClient",
    "direction": "in"
}
  • taskHub: se usa en escenarios donde varias aplicaciones de función comparten la misma cuenta de almacenamiento, pero tienen que estar aisladas entre sí. Si no se especifica, se usa el valor predeterminado host.json. Este valor tiene que coincidir con el valor usado por las funciones de orquestador de destino.
  • connectionName: nombre de una configuración de aplicación que contiene una cadena de conexión de cuenta de almacenamiento. La cuenta de almacenamiento representada por esta cadena de conexión tiene que ser la misma que utilizan las funciones del orquestador de destino. Si no se especifica, se utiliza la cadena de conexión de cuenta de almacenamiento predeterminada de la aplicación de función.

Nota

En la mayoría de los casos, se recomienda omitir estas propiedades y confiar en el comportamiento predeterminado.

Uso del cliente

En las funciones de .NET, habitualmente se enlaza con IDurableClient (DurableOrchestrationClient en Durable Functions v1.x) lo que proporciona acceso completo a todas las API de cliente de orquestación compatibles con Durable Functions. Para Java, se enlaza a la clase DurableClientContext. En otros lenguajes, debe usar el SDK específico del lenguaje para obtener acceso a un objeto de cliente.

Aquí tenemos un ejemplo de una función desencadenada por la cola que inicia una orquestación "HelloWorld".

[FunctionName("QueueStart")]
public static Task Run(
    [QueueTrigger("durable-function-trigger")] string input,
    [DurableClient] IDurableOrchestrationClient starter)
{
    // Orchestration input comes from the queue message content.
    return starter.StartNewAsync("HelloWorld", input);
}

Nota

El código de C# anterior corresponde a Durable Functions 2.x. En el caso de Durable Functions 1.x, debe usar el atributo OrchestrationClient en lugar del atributo DurableClient, además de usar el tipo de parámetro DurableOrchestrationClient en lugar de IDurableOrchestrationClient. Para obtener más información sobre las diferencias entre versiones, vea el artículo Versiones de Durable Functions.

Pueden encontrar más información acerca de cómo iniciar instancias en Administración de instancias.

Desencadenador de entidad

Los desencadenadores de entidad permiten crear funciones de entidad. Este desencadenador admite el procesamiento de eventos para una instancia de entidad específica.

Nota

Los desencadenadores de entidad están disponibles a partir de Durable Functions 2.x.

Internamente, este enlace de desencadenador sondea el almacén de larga duración configurado para las nuevas operaciones de entidad que deben ejecutarse.

Si va a crear funciones en .NET, el desencadenador de entidad se configura mediante el atributo EntityTriggerAttribute de .NET.

Si utiliza JavaScript, Python o PowerShell, el desencadenador de entidad se definirá mediante el objeto JSON siguiente en la matriz bindings de function.json:

{
    "name": "<Name of input parameter in function signature>",
    "entityName": "<Optional - name of the entity>",
    "type": "entityTrigger",
    "direction": "in"
}

Nota

Los desencadenadores de entidad aún no se admiten en Java.

De forma predeterminada, el nombre de una entidad es el nombre de la función.

Comportamiento de un desencadenador

Estas son algunas notas sobre el desencadenador de entidad:

  • De un único subproceso: un único subproceso de distribuidor se utiliza para procesar las operaciones de una entidad determinada. Si se envían varios mensajes a una sola entidad de manera simultánea, las operaciones se procesarán una a una.
  • Control de mensajes dudosos: no hay compatibilidad con mensajes dudosos en los desencadenadores de entidad.
  • Visibilidad de los mensajes: los mensajes de desencadenador de entidad se quitan de la cola y se mantienen invisibles durante un tiempo configurable. La visibilidad de estos mensajes se renueva automáticamente siempre que la aplicación de la función se esté ejecutando y se mantenga correcta.
  • Valores devueltos: las funciones de entidad no admiten valores devueltos. Hay API específicas que se pueden usar para guardar el estado o pasar valores devuelta a las orquestaciones.

Los cambios de estado realizados en una entidad durante su ejecución se conservarán automáticamente una vez completada la ejecución.

Para más información y ejemplos sobre cómo definir e interactuar con desencadenadores de entidad, consulte la documentación sobre entidades duraderas.

Cliente de entidad

El enlace de cliente de entidad permite desencadenar de manera asincrónica las funciones de entidad. Estas funciones se conocen a veces como funciones de cliente.

Si va a usar funciones precompiladas de .NET, puede enlazar con el cliente de entidad mediante el atributo DurableClientAttribute de .NET.

Nota

[DurableClientAttribute] también se puede usar para enlazar con el cliente de orquestación.

Si utiliza lenguajes de scripting (como el scripting de C#, JavaScript o Python) para desarrollar, el desencadenador de entidad se define mediante el objeto JSON siguiente de la matriz bindings de function.json:

{
    "name": "<Name of input parameter in function signature>",
    "taskHub": "<Optional - name of the task hub>",
    "connectionName": "<Optional - name of the connection string app setting>",
    "type": "durableClient",
    "direction": "in"
}

Nota

Los clientes de entidad aún no se admiten en Java.

  • taskHub: se usa en escenarios donde varias aplicaciones de función comparten la misma cuenta de almacenamiento, pero tienen que estar aisladas entre sí. Si no se especifica, se usa el valor predeterminado host.json. Este valor tiene que coincidir con el valor usado por las funciones de entidad de destino.
  • connectionName: nombre de una configuración de aplicación que contiene una cadena de conexión de cuenta de almacenamiento. La cuenta de almacenamiento representada por esta cadena de conexión tiene que ser la misma que utilizan las funciones de entidad de destino. Si no se especifica, se utiliza la cadena de conexión de cuenta de almacenamiento predeterminada de la aplicación de función.

Nota

En la mayoría de los casos, se recomienda omitir las propiedades opcionales y confiar en el comportamiento predeterminado.

Para más información y ejemplos sobre la interacción con entidades como cliente, consulte la documentación sobre entidades duraderas.

configuración de host.json

Configuración de Durable Functions.

Nota

Todas las versiones principales de Durable Functions son compatibles con todas las versiones del runtime de Azure Functions. Sin embargo, el esquema de la configuración de host.json es ligeramente diferente en función de la versión del runtime de Azure Functions y de la versión de la extensión de Durable Functions que se use. Los ejemplos siguientes son para Azure Functions 2.0 y 3.0. En ambos ejemplos, si se usa Azure Functions 1.0, la configuración disponible es la misma, pero la sección "durableTask" de host.json debería ir en la raíz de la configuración del archivo, en lugar de como un campo de "extensions".

{
 "extensions": {
  "durableTask": {
    "hubName": "MyTaskHub",
    "storageProvider": {
      "connectionStringName": "AzureWebJobsStorage",
      "controlQueueBatchSize": 32,
      "controlQueueBufferThreshold": 256,
      "controlQueueVisibilityTimeout": "00:05:00",
      "maxQueuePollingInterval": "00:00:30",
      "partitionCount": 4,
      "trackingStoreConnectionStringName": "TrackingStorage",
      "trackingStoreNamePrefix": "DurableTask",
      "useLegacyPartitionManagement": true,
      "workItemQueueVisibilityTimeout": "00:05:00",
    },
    "tracing": {
      "traceInputsAndOutputs": false,
      "traceReplayEvents": false,
    },
    "notifications": {
      "eventGrid": {
        "topicEndpoint": "https://topic_name.westus2-1.eventgrid.azure.net/api/events",
        "keySettingName": "EventGridKey",
        "publishRetryCount": 3,
        "publishRetryInterval": "00:00:30",
        "publishEventTypes": [
          "Started",
          "Pending",
          "Failed",
          "Terminated"
        ]
      }
    },
    "maxConcurrentActivityFunctions": 10,
    "maxConcurrentOrchestratorFunctions": 10,
    "extendedSessionsEnabled": false,
    "extendedSessionIdleTimeoutInSeconds": 30,
    "useAppLease": true,
    "useGracefulShutdown": false,
    "maxEntityOperationBatchSize": 50
  }
 }
}

Los nombres de la central de tareas deben empezar por una letra y estar formados únicamente por letras y números. Si no se especifica, el nombre predeterminado de la central de tareas de la aplicación de función es DurableFunctionsHub. Para más información, consulte el artículo sobre las centrales de tareas.

Propiedad Valor predeterminado Descripción
hubName DurableFunctionsHub Se pueden usar nombres de central de tareas alternativos para aislar varias aplicaciones de Durable Functions unas de otras, incluso si usan el mismo back-end de almacenamiento.
controlQueueBatchSize 32 El número de mensajes que se van a extraer a la vez de la cola de control.
controlQueueBufferThreshold Plan de consumo para Python: 32
Plan de consumo para JavaScript y C# : 128
Plan dedicado/Premium: 256
Número de mensajes de la cola de control que se pueden almacenar en búfer en la memoria a la vez, momento en que el distribuidor esperará para quitar cualquier mensaje adicional de la cola.
partitionCount 4 El recuento de particiones para la cola de control. Puede ser un entero positivo comprendido entre 1 y 16.
controlQueueVisibilityTimeout 5 minutos El tiempo de espera de visibilidad de los mensajes de la cola de control quitados de la cola.
workItemQueueVisibilityTimeout 5 minutos El tiempo de espera de visibilidad de los mensajes de la cola de elementos de trabajo quitados de la cola.
maxConcurrentActivityFunctions Plan de consumo: 10
Plan dedicado/Premium: 10 veces el número de procesadores en la máquina actual
El número máximo de funciones de actividad que se pueden procesar simultáneamente en una única instancia de host.
maxConcurrentOrchestratorFunctions Plan de consumo: 5
Plan dedicado/Premium: 10 veces el número de procesadores en la máquina actual
El número máximo de funciones de Orchestrator que se pueden procesar simultáneamente en una única instancia de host.
maxQueuePollingInterval 30 segundos Intervalo de sondeo de cola de elementos de trabajo y control máximo en formato hh:mm:ss: . Los valores más altos pueden provocar mayores latencias de procesamiento de mensajes. Los valores más bajos pueden provocar mayores costos de almacenamiento debido a transacciones de almacenamiento mayor.
connectionName (2.7.0 y versiones posteriores)
connectionStringName (2.x)
azureStorageConnectionStringName (1.x)
AzureWebJobsStorage Nombre de una configuración de aplicación o de una colección de configuraciones que especifica cómo conectarse a los recursos subyacentes de Azure Storage. Cuando se proporciona una única configuración de aplicación, debe ser una cadena de conexión de Azure Storage.
trackingStoreConnectionName (2.7.0 y versiones posteriores)
trackingStoreConnectionStringName
Nombre de una configuración de aplicación o colección de configuraciones que especifica cómo conectarse a las tablas de historial e instancias. Cuando se proporciona una única configuración de aplicación, debe ser una cadena de conexión de Azure Storage. Si no se especifica, se usa las conexiones connectionStringName (Durable 2.x) o azureStorageConnectionStringName (Durable 1.x).
trackingStoreNamePrefix Prefijo que se usará para las tablas de historial e instancias cuando se especifica trackingStoreConnectionStringName. Si no se establece, el valor de prefijo predeterminado será DurableTask. Si no se especifica trackingStoreConnectionStringName, las tablas de historial e instancias usarán el valor hubName como prefijo y se pasarán por alto todos los valores de configuración de trackingStoreNamePrefix.
traceInputsAndOutputs false Un valor que indica si se realizará el seguimiento de las entradas y salidas de las llamadas de función. El comportamiento predeterminado al realizar el seguimiento de eventos de ejecución de funciones es incluir el número de bytes en las entradas y salidas serializadas de las llamadas de función. Este comportamiento proporciona información mínima sobre el aspecto de las entradas y salidas, sin sobredimensionar los registros o exponer por accidente información confidencial. Al establecer esta propiedad en true, el registro de funciones predeterminado registra todo el contenido de las entradas y salidas de función.
traceReplayEvents false Un valor que indica si se debe escribir eventos de reproducción de orquestación en Application Insights.
eventGridTopicEndpoint La dirección URL de un punto de conexión de tema personalizado de Azure Event Grid. Cuando se establece esta propiedad, se publican eventos de notificación del ciclo de vida de orquestación en este punto de conexión. Esta propiedad admite la resolución de la configuración de la aplicación.
eventGridKeySettingName El nombre de la configuración de aplicación que contiene la clave usada para autenticarse con el tema personalizado de Azure Event Grid en EventGridTopicEndpoint.
eventGridPublishRetryCount 0 El número de reintentos, si, al publicar en el tema de Event Grid, se produce un error.
eventGridPublishRetryInterval 5 minutos Event Grid publica el intervalo de reintento en formato hh:mm:ss.
eventGridPublishEventTypes Lista de tipos de eventos que se van a publicar en Event Grid. Si no se especifica, se publicarán todos los tipos de evento. Los valores permitidos son Started, Completed, Failed y Terminated.
useAppLease true Si se establece en true, las aplicaciones requerirán que se adquiera una concesión de blob de nivel de aplicación antes de procesar los mensajes de la central de tareas. Para más información, consulte la documentación sobre la recuperación ante desastres y la distribución geográfica. Disponible a partir de la versión 2.3.0.
useLegacyPartitionManagement false Cuando se establece en false, usa un algoritmo de administración de particiones que reduce la posibilidad de que se ejecute la función duplicada al realizar un escalado horizontal. Disponible a partir de la versión 2.3.0.
useGracefulShutdown false (Versión preliminar) Habilite el apagado correcto para reducir la posibilidad de que se produzcan errores de apagado del host en las ejecuciones de función en proceso.
maxEntityOperationBatchSize(2.6.1) Plan de consumo: 50
Plan dedicado/Premium: 5000
Número máximo de operaciones de entidad que se procesan como un lote. Si se establece en 1, el procesamiento por lotes está deshabilitado y cada mensaje de operación se procesa mediante una invocación de función independiente.

Muchos de estos valores son para optimizar el rendimiento. Para obtener más información, vea Rendimiento y escalabilidad.

Pasos siguientes