Patrones durable Functions y conceptos técnicos (Azure Functions)Durable Functions patterns and technical concepts (Azure Functions)

Durable Functions es una extensión de Azure Functions y Azure WebJobs.Durable Functions is an extension of Azure Functions and Azure WebJobs. Puede utilizar Durable Functions para escribir funciones con estado en un entorno sin servidor.You can use Durable Functions to write stateful functions in a serverless environment. La extensión administra el estado, establece puntos de control y reinicia en su nombre.The extension manages state, checkpoints, and restarts for you.

Este artículo se ofrece información detallada acerca de los comportamientos de la extensión Durable Functions para Azure Functions y patrones comunes de implementación.This article gives you detailed information about the behaviors of the Durable Functions extension for Azure Functions and common implementation patterns. La información puede ayudarle a determinar cómo utilizar Durable Functions para ayudar a solucionar los desafíos de desarrollo.The information can help you determine how to use Durable Functions to help solve your development challenges.

Nota

Durable Functions es una extensión avanzada para Azure Functions que no es adecuada para todas las aplicaciones.Durable Functions is an advanced extension for Azure Functions that isn't appropriate for all applications. En este artículo se supone que tiene está muy familiarizado con conceptos de Azure Functions y los desafíos implicados en el desarrollo de aplicaciones sin servidor.This article assumes that you have a strong familiarity with concepts in Azure Functions and the challenges involved in serverless application development.

PatronesPatterns

Esta sección describen algunos patrones comunes de aplicaciones que Durable Functions puede resultar útil.This section describes some common application patterns where Durable Functions can be useful.

Patrón 1: Diagrama de encadenamiento de funcionesPattern #1: Function chaining

En el modelo de encadenamiento de funciones, una secuencia de funciones se ejecuta en un orden específico.In the function chaining pattern, a sequence of functions executes in a specific order. En este patrón, el resultado de una función se aplica a la entrada de otra función.In this pattern, the output of one function is applied to the input of another function.

Un diagrama de la función de modelo de encadenamiento

Puede utilizar Durable Functions para implementar el patrón de forma concisa como se muestra en el siguiente ejemplo de encadenamiento de funciones:You can use Durable Functions to implement the function chaining pattern concisely as shown in the following example:

Script de C#C# script

public static async Task<object> Run(DurableOrchestrationContext context)
{
    try
    {
        var x = await context.CallActivityAsync<object>("F1");
        var y = await context.CallActivityAsync<object>("F2", x);
        var z = await context.CallActivityAsync<object>("F3", y);
        return  await context.CallActivityAsync<object>("F4", z);
    }
    catch (Exception)
    {
        // Error handling or compensation goes here.
    }
}

Nota

Existen diferencias sutiles entre escribir una función durable precompilada C# y escribir una función durable precompilada en el C# secuencia de comandos que se muestra en el ejemplo.There are subtle differences between writing a precompiled durable function in C# and writing a precompiled durable function in the C# script that's shown in the example. En un C# precompilado de función, parámetros duraderos se deben decorar con atributos respectivos.In a C# precompiled function, durable parameters must be decorated with respective attributes. Un ejemplo es el [OrchestrationTrigger] atributo para el DurableOrchestrationContext parámetro.An example is the [OrchestrationTrigger] attribute for the DurableOrchestrationContext parameter. En un C# precompilado función duradera, si los parámetros no son representativos correctamente, el tiempo de ejecución no puede insertar las variables en la función y se produce un error.In a C# precompiled durable function, if the parameters aren't properly decorated, the runtime can't inject the variables into the function, and an error occurs. Para obtener más ejemplos, vea el azure-functions-durable-extension ejemplos en GitHub.For more examples, see the azure-functions-durable-extension samples on GitHub.

JavaScript (solo Functions 2.x)JavaScript (Functions 2.x only)

const df = require("durable-functions");

module.exports = df.orchestrator(function*(context) {
    const x = yield context.df.callActivity("F1");
    const y = yield context.df.callActivity("F2", x);
    const z = yield context.df.callActivity("F3", y);
    return yield context.df.callActivity("F4", z);
});

En este ejemplo, los valores F1, F2, F3, y F4 son los nombres de otras funciones en la aplicación de función.In this example, the values F1, F2, F3, and F4 are the names of other functions in the function app. Puede implementar el flujo de control mediante el uso de construcciones de código imperativas normales.You can implement control flow by using normal imperative coding constructs. Código que se ejecuta de arriba hacia abajo.Code executes from the top down. El código puede implicar existente semántica de flujo de control del lenguaje, como instrucciones condicionales y bucles.The code can involve existing language control flow semantics, like conditionals and loops. Puede incluir la lógica de control de errores try / catch / finally bloques.You can include error handling logic in try/catch/finally blocks.

Puede usar el context parámetro DurableOrchestrationContext (.NET) y context.df (objeto de JavaScript) para invocar otras funciones por nombre, pasar parámetros y devolver la función salida.You can use the context parameter DurableOrchestrationContext (.NET) and the context.df object (JavaScript) to invoke other functions by name, pass parameters, and return function output. Cada vez que el código llama a await (C#) o yield (JavaScript), los puntos de control de marco de Durable Functions el progreso de la instancia actual de la función.Each time the code calls await (C#) or yield (JavaScript), the Durable Functions framework checkpoints the progress of the current function instance. Si la máquina virtual o el proceso se recicla a mitad de la ejecución, la instancia de la función se reanuda desde la anterior await o yield llamar.If the process or VM recycles midway through the execution, the function instance resumes from the preceding await or yield call. Para obtener más información, consulte la sección siguiente, el patrón Nº 2: Ventilador fuera/ventilador en.For more information, see the next section, Pattern #2: Fan out/fan in.

Nota

El context objeto de JavaScript representa toda la contexto de la función, no solo el DurableOrchestrationContext parámetro.The context object in JavaScript represents the entire function context, not only the DurableOrchestrationContext parameter.

Patrón 2: Ventilador fuera/ventilador enPattern #2: Fan out/fan in

En el ventilador out/ventilador de patrón, ejecutar varias funciones en paralelo y espere a que todas las funciones Finalizar.In the fan out/fan in pattern, you execute multiple functions in parallel and then wait for all functions to finish. A menudo, se realiza algún trabajo de agregación en los resultados devueltos por las funciones.Often, some aggregation work is done on the results that are returned from the functions.

Un diagrama del ventilador fuera/ventilador patrón

Con las funciones normales, puede multiplicar por tener la función enviar varios mensajes a una cola.With normal functions, you can fan out by having the function send multiple messages to a queue. Distribución ramificada de vuelta es mucho más difícil.Fanning back in is much more challenging. Para una función normal, de ventilador, escribir código para realizar un seguimiento cuando el final de las funciones desencadenadas por la cola y almacenarlo función salidas.To fan in, in a normal function, you write code to track when the queue-triggered functions end, and then store function outputs.

La extensión Durable Functions controla este patrón con código relativamente sencillo:The Durable Functions extension handles this pattern with relatively simple code:

Script de C#C# script

public static async Task Run(DurableOrchestrationContext context)
{
    var parallelTasks = new List<Task<int>>();

    // Get a list of N work items to process in parallel.
    object[] workBatch = await context.CallActivityAsync<object[]>("F1");
    for (int i = 0; i < workBatch.Length; i++)
    {
        Task<int> task = context.CallActivityAsync<int>("F2", workBatch[i]);
        parallelTasks.Add(task);
    }

    await Task.WhenAll(parallelTasks);

    // Aggregate all N outputs and send the result to F3.
    int sum = parallelTasks.Sum(t => t.Result);
    await context.CallActivityAsync("F3", sum);
}

JavaScript (solo Functions 2.x)JavaScript (Functions 2.x only)

const df = require("durable-functions");

module.exports = df.orchestrator(function*(context) {
    const parallelTasks = [];

    // Get a list of N work items to process in parallel.
    const workBatch = yield context.df.callActivity("F1");
    for (let i = 0; i < workBatch.length; i++) {
        parallelTasks.push(context.df.callActivity("F2", workBatch[i]));
    }

    yield context.df.Task.all(parallelTasks);

    // Aggregate all N outputs and send the result to F3.
    const sum = parallelTasks.reduce((prev, curr) => prev + curr, 0);
    yield context.df.callActivity("F3", sum);
});

El trabajo de distribución ramificada se distribuye en varias instancias de la F2 función.The fan-out work is distributed to multiple instances of the F2 function. El trabajo se realiza un seguimiento mediante el uso de una lista dinámica de las tareas.The work is tracked by using a dynamic list of tasks. .NET Task.WhenAll API o JavaScript context.df.Task.all se denomina API, para esperar a que todas las funciones llamadas finalicen.The .NET Task.WhenAll API or JavaScript context.df.Task.all API is called, to wait for all the called functions to finish. A continuación, la F2 función genera se agregan desde la lista de tareas dinámica y se pasan a la F3 función.Then, the F2 function outputs are aggregated from the dynamic task list and passed to the F3 function.

Los puntos de comprobación automáticos que se produce en el await o yield llamar en Task.WhenAll o context.df.Task.all garantiza que un bloqueo de midway posibles o el reinicio no requiere reiniciar una tarea ya se ha completado.The automatic checkpointing that happens at the await or yield call on Task.WhenAll or context.df.Task.all ensures that a potential midway crash or reboot doesn't require restarting an already completed task.

Patrón 3: Las API de HTTP asincrónicoPattern #3: Async HTTP APIs

El patrón de HTTP APIs de async aborda el problema de coordinar el estado de las operaciones de larga ejecución con los clientes externos.The async HTTP APIs pattern addresses the problem of coordinating the state of long-running operations with external clients. Un enfoque común para implementar este patrón es tener un HTTP llamada al desencadenador de la acción de ejecución prolongada.A common way to implement this pattern is by having an HTTP call trigger the long-running action. A continuación, redirigir al cliente a un punto de conexión de estado que el cliente sondea para saber cuando finalice la operación.Then, redirect the client to a status endpoint that the client polls to learn when the operation is finished.

Un diagrama del modelo de API HTTP

Durable Functions proporciona API integradas que simplifican el código que escribe para interactuar con las ejecuciones de funciones de ejecución prolongada.Durable Functions provides built-in APIs that simplify the code you write to interact with long-running function executions. Los ejemplos de inicio rápido de Durable Functions ( C# y JavaScript) muestran un comando REST simple que puede usar para iniciar nuevas instancias de función de orquestador.The Durable Functions quickstart samples (C# and JavaScript) show a simple REST command that you can use to start new orchestrator function instances. Cuando se inicia una instancia, la extensión expone webhook HTTP APIs que consultar el estado de la función de orquestador.After an instance starts, the extension exposes webhook HTTP APIs that query the orchestrator function status.

El ejemplo siguiente muestra comandos REST que se inician un orquestador y consultar su estado.The following example shows REST commands that start an orchestrator and query its status. Para evitar confusiones, se omiten algunos detalles en el ejemplo.For clarity, some details are omitted from the example.

> curl -X POST https://myfunc.azurewebsites.net/orchestrators/DoWork -H "Content-Length: 0" -i
HTTP/1.1 202 Accepted
Content-Type: application/json
Location: https://myfunc.azurewebsites.net/admin/extensions/DurableTaskExtension/b79baf67f717453ca9e86c5da21e03ec

{"id":"b79baf67f717453ca9e86c5da21e03ec", ...}

> curl https://myfunc.azurewebsites.net/admin/extensions/DurableTaskExtension/b79baf67f717453ca9e86c5da21e03ec -i
HTTP/1.1 202 Accepted
Content-Type: application/json
Location: https://myfunc.azurewebsites.net/admin/extensions/DurableTaskExtension/b79baf67f717453ca9e86c5da21e03ec

{"runtimeStatus":"Running","lastUpdatedTime":"2017-03-16T21:20:47Z", ...}

> curl https://myfunc.azurewebsites.net/admin/extensions/DurableTaskExtension/b79baf67f717453ca9e86c5da21e03ec -i
HTTP/1.1 200 OK
Content-Length: 175
Content-Type: application/json

{"runtimeStatus":"Completed","lastUpdatedTime":"2017-03-16T21:20:57Z", ...}

Dado que el tiempo de ejecución de Durable Functions administra el estado, no es necesario implementar su propio mecanismo de seguimiento de estado.Because the Durable Functions runtime manages state, you don't need to implement your own status-tracking mechanism.

La extensión Durable Functions tiene webhooks integrados que administrar las orquestaciones de larga ejecución.The Durable Functions extension has built-in webhooks that manage long-running orchestrations. Puede implementar este patrón utilizando sus propios desencadenadores de función (por ejemplo, HTTP, una cola o Event Hubs de Azure) y el orchestrationClient enlace.You can implement this pattern yourself by using your own function triggers (such as HTTP, a queue, or Azure Event Hubs) and the orchestrationClient binding. Por ejemplo, podría utilizar un mensaje en cola para desencadenar la terminación.For example, you might use a queue message to trigger termination. O bien, puede usar un desencadenador HTTP que está protegido por una directiva de autenticación de Azure Active Directory en lugar de webhooks integradas que utilizan una clave generada para la autenticación.Or, you might use an HTTP trigger that's protected by an Azure Active Directory authentication policy instead of the built-in webhooks that use a generated key for authentication.

Estos son algunos ejemplos de cómo usar el patrón de la API de HTTP:Here are some examples of how to use the HTTP API pattern:

C#C#

// An HTTP-triggered function starts a new orchestrator function instance.
public static async Task<HttpResponseMessage> Run(
    HttpRequestMessage req,
    DurableOrchestrationClient starter,
    string functionName,
    ILogger log)
{
    // The function name comes from the request URL.
    // The function input comes from the request content.
    dynamic eventData = await req.Content.ReadAsAsync<object>();
    string instanceId = await starter.StartNewAsync(functionName, eventData);

    log.LogInformation($"Started orchestration with ID = '{instanceId}'.");

    return starter.CreateCheckStatusResponse(req, instanceId);
}

JavaScript (solo Functions 2.x)JavaScript (Functions 2.x only)

// An HTTP-triggered function starts a new orchestrator function instance.
const df = require("durable-functions");

module.exports = async function (context, req) {
    const client = df.getClient(context);

    // The function name comes from the request URL.
    // The function input comes from the request content.
    const eventData = req.body;
    const instanceId = await client.startNew(req.params.functionName, undefined, eventData);

    context.log(`Started orchestration with ID = '${instanceId}'.`);

    return client.createCheckStatusResponse(req, instanceId);
};

En .NET, el parámetro starter DurableOrchestrationClient es un valor del enlace de salida orchestrationClient que forma parte de la extensión de Durable Functions.In .NET, the DurableOrchestrationClient starter parameter is a value from the orchestrationClient output binding, which is part of the Durable Functions extension. En JavaScript, este objeto se devuelve llamando a df.getClient(context).In JavaScript, this object is returned by calling df.getClient(context). Estos objetos proporcionan métodos que puede usar para iniciar, enviar eventos a, terminar y consultar para instancias de la función de orquestador nueva o existente.These objects provide methods you can use to start, send events to, terminate, and query for new or existing orchestrator function instances.

En los ejemplos anteriores, una función desencadenada por HTTP toma un functionName valor desde la dirección URL entrante y pasa el valor a StartNewAsync.In the preceding examples, an HTTP-triggered function takes in a functionName value from the incoming URL and passes the value to StartNewAsync. El CreateCheckStatusResponse enlace de API, a continuación, devuelve una respuesta que contiene un Location encabezado e información adicional acerca de la instancia.The CreateCheckStatusResponse binding API then returns a response that contains a Location header and additional information about the instance. Puede usar la información más adelante para consultar el estado de la instancia iniciada o para finalizar la instancia.You can use the information later to look up the status of the started instance or to terminate the instance.

Patrón 4: SupervisiónPattern #4: Monitor

El patrón de supervisión hace referencia a un proceso flexible y periódico en un flujo de trabajo.The monitor pattern refers to a flexible, recurring process in a workflow. Un ejemplo es el sondeo hasta que se cumplen determinadas condiciones.An example is polling until specific conditions are met. Puede usar normal desencadenador de temporizador para abordar básico escenario, como un trabajo de limpieza periódica, pero su intervalo es estático y administrar la duración de la instancia pasa a ser compleja.You can use a regular timer trigger to address a basic scenario, such as a periodic cleanup job, but its interval is static and managing instance lifetimes becomes complex. Puede utilizar Durable Functions para crear intervalos de periodicidad flexibles, administrar la vigencia de la tarea y crear procesos de varios monitores desde una única orquestación.You can use Durable Functions to create flexible recurrence intervals, manage task lifetimes, and create multiple monitor processes from a single orchestration.

Es un ejemplo del patrón de monitor invertir el escenario anterior de la API HTTP asincrónico.An example of the monitor pattern is to reverse the earlier async HTTP API scenario. En lugar de exponer un punto de conexión para un cliente externo supervisar una operación de larga ejecución, el monitor de ejecución prolongada consume un punto de conexión externo y, a continuación, espera un cambio de estado.Instead of exposing an endpoint for an external client to monitor a long-running operation, the long-running monitor consumes an external endpoint, and then waits for a state change.

Un diagrama del patrón de monitor

En unas pocas líneas de código, puede utilizar Durable Functions para crear a varios monitores que observan puntos de conexión arbitrarios.In a few lines of code, you can use Durable Functions to create multiple monitors that observe arbitrary endpoints. Los monitores pueden finalizar la ejecución cuando se cumple una condición, o la DurableOrchestrationClient pueden finalizar los monitores.The monitors can end execution when a condition is met, or the DurableOrchestrationClient can terminate the monitors. Puede cambiar un monitor wait intervalo según una condición específica (por ejemplo, retroceso exponencial).You can change a monitor's wait interval based on a specific condition (for example, exponential backoff.)

El código siguiente implementa a un monitor básico:The following code implements a basic monitor:

Script de C#C# script

public static async Task Run(DurableOrchestrationContext context)
{
    int jobId = context.GetInput<int>();
    int pollingInterval = GetPollingInterval();
    DateTime expiryTime = GetExpiryTime();

    while (context.CurrentUtcDateTime < expiryTime)
    {
        var jobStatus = await context.CallActivityAsync<string>("GetJobStatus", jobId);
        if (jobStatus == "Completed")
        {
            // Perform an action when a condition is met.
            await context.CallActivityAsync("SendAlert", machineId);
            break;
        }

        // Orchestration sleeps until this time.
        var nextCheck = context.CurrentUtcDateTime.AddSeconds(pollingInterval);
        await context.CreateTimer(nextCheck, CancellationToken.None);
    }

    // Perform more work here, or let the orchestration end.
}

JavaScript (solo Functions 2.x)JavaScript (Functions 2.x only)

const df = require("durable-functions");
const moment = require("moment");

module.exports = df.orchestrator(function*(context) {
    const jobId = context.df.getInput();
    const pollingInternal = getPollingInterval();
    const expiryTime = getExpiryTime();

    while (moment.utc(context.df.currentUtcDateTime).isBefore(expiryTime)) {
        const jobStatus = yield context.df.callActivity("GetJobStatus", jobId);
        if (jobStatus === "Completed") {
            // Perform an action when a condition is met.
            yield context.df.callActivity("SendAlert", machineId);
            break;
        }

        // Orchestration sleeps until this time.
        const nextCheck = moment.utc(context.df.currentUtcDateTime).add(pollingInterval, 's');
        yield context.df.createTimer(nextCheck.toDate());
    }

    // Perform more work here, or let the orchestration end.
});

Cuando se recibe una solicitud, se crea una nueva instancia de orquestación para ese identificador de trabajo.When a request is received, a new orchestration instance is created for that job ID. La instancia sondea un estado hasta que se cumple una condición y se cierra el bucle.The instance polls a status until a condition is met and the loop is exited. Un temporizador durable controla el intervalo de sondeo.A durable timer controls the polling interval. A continuación, se puede realizar más trabajo, o puede finalizar la orquestación.Then, more work can be performed, or the orchestration can end. Cuando el context.CurrentUtcDateTime (. NET) o context.df.currentUtcDateTime (JavaScript) supera el expiryTime valor, el monitor finaliza.When the context.CurrentUtcDateTime (.NET) or context.df.currentUtcDateTime (JavaScript) exceeds the expiryTime value, the monitor ends.

Patrón 5: Interacción humanaPattern #5: Human interaction

Muchos procesos automatizados implican a algún tipo de interacción humana.Many automated processes involve some kind of human interaction. Humana en un proceso automatizado es complicado, porque las personas que no sean como de alta disponibilidad y capacidad de respuesta como servicios en la nube.Involving humans in an automated process is tricky because people aren't as highly available and as responsive as cloud services. Un proceso automatizado podría permitir esto mediante la lógica de compensación y tiempos de espera.An automated process might allow for this by using timeouts and compensation logic.

Un proceso de aprobación es un ejemplo de un proceso empresarial que implica la interacción humana.An approval process is an example of a business process that involves human interaction. Aprobación de un administrador podría ser necesario para un informe de gastos que supera una determinada cantidad de dólares.Approval from a manager might be required for an expense report that exceeds a certain dollar amount. Si el administrador no aprueba el informe de gastos en 72 horas (quizás el administrador se fue de vacaciones), se inicia un proceso de escalado para obtener la aprobación de otra persona (quizás el jefe del administrador).If the manager doesn't approve the expense report within 72 hours (maybe the manager went on vacation), an escalation process kicks in to get the approval from someone else (perhaps the manager's manager).

Un diagrama del modelo de interacción humana

Puede implementar el patrón en este ejemplo, mediante el uso de una función de orquestador.You can implement the pattern in this example by using an orchestrator function. Usa el orquestador un temporizador durable para solicitar la aprobación.The orchestrator uses a durable timer to request approval. El orquestador lo escala si se produce el tiempo de espera.The orchestrator escalates if timeout occurs. El orquestador espera una evento externo, como una notificación generada por una interacción humana.The orchestrator waits for an external event, such as a notification that's generated by a human interaction.

Estos ejemplos crea un proceso de aprobación para demostrar el patrón de interacción humana:These examples create an approval process to demonstrate the human interaction pattern:

Script de C#C# script

public static async Task Run(DurableOrchestrationContext context)
{
    await context.CallActivityAsync("RequestApproval");
    using (var timeoutCts = new CancellationTokenSource())
    {
        DateTime dueTime = context.CurrentUtcDateTime.AddHours(72);
        Task durableTimeout = context.CreateTimer(dueTime, timeoutCts.Token);

        Task<bool> approvalEvent = context.WaitForExternalEvent<bool>("ApprovalEvent");
        if (approvalEvent == await Task.WhenAny(approvalEvent, durableTimeout))
        {
            timeoutCts.Cancel();
            await context.CallActivityAsync("ProcessApproval", approvalEvent.Result);
        }
        else
        {
            await context.CallActivityAsync("Escalate");
        }
    }
}

JavaScript (solo Functions 2.x)JavaScript (Functions 2.x only)

const df = require("durable-functions");
const moment = require('moment');

module.exports = df.orchestrator(function*(context) {
    yield context.df.callActivity("RequestApproval");

    const dueTime = moment.utc(context.df.currentUtcDateTime).add(72, 'h');
    const durableTimeout = context.df.createTimer(dueTime.toDate());

    const approvalEvent = context.df.waitForExternalEvent("ApprovalEvent");
    if (approvalEvent === yield context.df.Task.any([approvalEvent, durableTimeout])) {
        durableTimeout.cancel();
        yield context.df.callActivity("ProcessApproval", approvalEvent.result);
    } else {
        yield context.df.callActivity("Escalate");
    }
});

Para crear el temporizador duradero, llame a context.CreateTimer (. NET) o context.df.createTimer (JavaScript).To create the durable timer, call context.CreateTimer (.NET) or context.df.createTimer (JavaScript). context.WaitForExternalEvent (.NET) o context.df.waitForExternalEvent (JavaScript) reciben la notificación.The notification is received by context.WaitForExternalEvent (.NET) or context.df.waitForExternalEvent (JavaScript). A continuación, Task.WhenAny (. NET) o context.df.Task.any (JavaScript) se llama para decidir si se escala (tiempo de espera sucede primero) o procesar la aprobación (se recibe la aprobación antes de tiempo de espera).Then, Task.WhenAny (.NET) or context.df.Task.any (JavaScript) is called to decide whether to escalate (timeout happens first) or process the approval (the approval is received before timeout).

Un cliente externo puede entregar la notificación de eventos a una función de orquestador en espera utilizando el integrados APIs HTTP o mediante el DurableOrchestrationClient.RaiseEventAsync API desde otra función:An external client can deliver the event notification to a waiting orchestrator function by using either the built-in HTTP APIs or by using the DurableOrchestrationClient.RaiseEventAsync API from another function:

public static async Task Run(string instanceId, DurableOrchestrationClient client)
{
    bool isApproved = true;
    await client.RaiseEventAsync(instanceId, "ApprovalEvent", isApproved);
}
const df = require("durable-functions");

module.exports = async function (context) {
    const client = df.getClient(context);
    const isApproved = true;
    await client.raiseEvent(instanceId, "ApprovalEvent", isApproved);
};

Patrón #6: Agregador (versión preliminar)Pattern #6: Aggregator (preview)

El patrón sexto es acerca de cómo agregar datos de eventos durante un período de tiempo en una sola, direccionable entidad.The sixth pattern is about aggregating event data over a period of time into a single, addressable entity. En este patrón, los datos que se agreguen pueden proceder de varios orígenes, puede que se entreguen en lotes o pueden estar dispersos en long-períodos de tiempo.In this pattern, the data being aggregated may come from multiple sources, may be delivered in batches, or may be scattered over long-periods of time. El agregador deba actuar en datos de eventos que llegan y pueden necesitar los clientes externos consultar los datos agregados.The aggregator might need to take action on event data as it arrives, and external clients may need to query the aggregated data.

Diagrama de agregador

El aspecto más difícil intentar implementar este patrón con normal, las funciones sin estado es que el control de simultaneidad se convierte en un gran desafío.The tricky thing about trying to implement this pattern with normal, stateless functions is that concurrency control becomes a huge challenge. No sólo es necesario preocuparse por varios subprocesos que se modifican los mismos datos al mismo tiempo, también deberá preocuparse por lo que garantiza que el agregador solo se ejecuta en una sola máquina virtual a la vez.Not only do you need to worry about multiple threads modifying the same data at the same time, you also need to worry about ensuring that the aggregator only runs on a single VM at a time.

Mediante un función duradera entidad, uno puede implementar este patrón fácilmente como una sola función.Using a Durable Entity function, one can implement this pattern easily as a single function.

public static async Task Counter(
    [EntityTrigger(EntityClassName = "Counter")] IDurableEntityContext ctx)
{
    int currentValue = ctx.GetState<int>();
    int operand = ctx.GetInput<int>();

    switch (ctx.OperationName)
    {
        case "add":
            currentValue += operand;
            break;
        case "subtract":
            currentValue -= operand;
            break;
        case "reset":
            await SendResetNotificationAsync();
            currentValue = 0;
            break;
    }

    ctx.SetState(currentValue);
}

Los clientes pueden poner en cola operaciones para (también conocido como "señalización") una función de la entidad usando el orchestrationClient enlace.Clients can enqueue operations for (also known as "signaling") an entity function using the orchestrationClient binding.

[FunctionName("EventHubTriggerCSharp")]
public static async Task Run(
    [EventHubTrigger("device-sensor-events")] EventData eventData,
    [OrchestrationClient] IDurableOrchestrationClient entityClient)
{
    var metricType = (string)eventData.Properties["metric"];
    var delta = BitConverter.ToInt32(eventData.Body, eventData.Body.Offset);

    // The "Counter/{metricType}" entity is created on-demand.
    var entityId = new EntityId("Counter", metricType);
    await entityClient.SignalEntityAsync(entityId, "add", delta);
}

De forma similar, los clientes pueden consultar el estado de una función de entidad mediante métodos en el orchestrationClient enlace.Similarly, clients can query for the state of an entity function using methods on the orchestrationClient binding.

Nota

Funciones de la entidad actualmente solo están disponibles en el Durable Functions 2.0 preview.Entity functions are currently only available in the Durable Functions 2.0 preview.

La tecnologíaThe technology

En segundo plano, la extensión Durable Functions se basa en la parte superior de la Durable Task Framework, una biblioteca de código abierto en GitHub que se usa para compilar las orquestaciones de tarea durables.Behind the scenes, the Durable Functions extension is built on top of the Durable Task Framework, an open-source library on GitHub that's used to build durable task orchestrations. Al igual que Azure Functions es la evolución sin servidor de Azure WebJobs, Durable Functions es la evolución sin servidor de Durable Task Framework.Like Azure Functions is the serverless evolution of Azure WebJobs, Durable Functions is the serverless evolution of the Durable Task Framework. Microsoft y otras organizaciones utilizan Durable Task Framework ampliamente para automatizar los procesos críticos.Microsoft and other organizations use the Durable Task Framework extensively to automate mission-critical processes. Es una opción natural para el entorno de Azure Functions sin servidor.It's a natural fit for the serverless Azure Functions environment.

Abastecimiento de eventos, puntos de control y reproducciónEvent sourcing, checkpointing, and replay

Las funciones de orquestador confiable mantienen su estado de ejecución mediante el uso de la abastecimiento de eventos patrón de diseño.Orchestrator functions reliably maintain their execution state by using the event sourcing design pattern. En lugar de almacenar directamente el estado actual de una orquestación, la extensión Durable Functions usa un almacén de solo anexar para registrar toda la serie de acciones que realiza la función de orquestación.Instead of directly storing the current state of an orchestration, the Durable Functions extension uses an append-only store to record the full series of actions the function orchestration takes. Un almacén de solo anexar tiene muchas ventajas en comparación con el estado de tiempo de ejecución completo "volcado".An append-only store has many benefits compared to "dumping" the full runtime state. Ventajas incluyen un mayor rendimiento, escalabilidad y capacidad de respuesta.Benefits include increased performance, scalability, and responsiveness. También obtendrá la coherencia final para los datos transaccionales y seguimientos de auditoría completa y el historial.You also get eventual consistency for transactional data and full audit trails and history. Los seguimientos de auditoría admiten acciones de compensación confiables.The audit trails support reliable compensating actions.

Durable Functions usa transparente abastecimiento de eventos.Durable Functions uses event sourcing transparently. En segundo plano, el await (C#) o yield operador (JavaScript) en una función de orquestador cede el control del subproceso del orquestador al distribuidor de Durable Task Framework.Behind the scenes, the await (C#) or yield (JavaScript) operator in an orchestrator function yields control of the orchestrator thread back to the Durable Task Framework dispatcher. El distribuidor, a continuación, confirma las nuevas acciones que la función de orquestador programó (como llamar a una o más funciones secundarias o programar un temporizador durable) al almacenamiento.The dispatcher then commits any new actions that the orchestrator function scheduled (such as calling one or more child functions or scheduling a durable timer) to storage. La acción de confirmación transparente se anexa al historial de ejecución de la instancia de orquestación.The transparent commit action appends to the execution history of the orchestration instance. El historial se guarda en una tabla de almacenamiento.The history is stored in a storage table. La acción de confirmación, a continuación, agrega mensajes a una cola para programar el trabajo real.The commit action then adds messages to a queue to schedule the actual work. En este momento, la función del orquestador se puede descargar de la memoria.At this point, the orchestrator function can be unloaded from memory.

La facturación de la función de orquestador se detiene si usa el plan de consumo de Azure Functions.Billing for the orchestrator function stops if you're using the Azure Functions consumption plan. Cuando hay más trabajo que hacer, los reinicios de la función, y se reconstruye su estado.When there's more work to do, the function restarts, and its state is reconstructed.

Cuando una función de orquestación recibe más trabajo que realizar (por ejemplo, se recibe un mensaje de respuesta o expira un temporizador durable), el orquestador se reactiva y vuelve a ejecutar toda la función desde el principio para reconstruir el estado local.When an orchestration function is given more work to do (for example, a response message is received or a durable timer expires), the orchestrator wakes up and re-executes the entire function from the start to rebuild the local state.

Durante la reproducción, si el código intenta llamar a una función (o realizar cualquier otra async trabajo), Durable Task Framework consulta el historial de ejecución de la orquestación actual.During the replay, if the code tries to call a function (or do any other async work), the Durable Task Framework consults the execution history of the current orchestration. Si detecta que el función de actividad ya ejecuta y se produjo un resultado, reproduce el resultado de la función y el código del orquestador continúa ejecutándose.If it finds that the activity function has already executed and yielded a result, it replays that function's result and the orchestrator code continues to run. Reproducción continúa hasta que finalice el código de función o hasta que se ha programado nuevo trabajo asincrónico.Replay continues until the function code is finished or until it has scheduled new async work.

Restricciones de código del orquestadorOrchestrator code constraints

El comportamiento de reproducción del código de orchestrator crea restricciones sobre el tipo de código que puede escribir en una función de orquestador.The replay behavior of orchestrator code creates constraints on the type of code that you can write in an orchestrator function. Por ejemplo, código de orquestador debe ser determinista porque se reproducirá varias veces y se debe producir el mismo resultado cada vez.For example, orchestrator code must be deterministic because it will be replayed multiple times, and it must produce the same result each time. Para obtener una lista completa de las restricciones, vea restricciones de código del orquestador.For the complete list of constraints, see Orchestrator code constraints.

Supervisión y diagnósticoMonitoring and diagnostics

La extensión Durable Functions emite automáticamente datos de seguimiento estructurado a Application Insights si configura la aplicación de función con una clave de instrumentación de Application Insights de Azure.The Durable Functions extension automatically emits structured tracking data to Application Insights if you set up your function app with an Azure Application Insights instrumentation key. Puede usar los datos de seguimiento para supervisar las acciones y el progreso de las orquestaciones.You can use the tracking data to monitor the actions and progress of your orchestrations.

Este es un ejemplo del aspecto de Durable Functions eventos de seguimiento en el portal de Application Insights cuando usas Application Insights Analytics:Here's an example of what the Durable Functions tracking events look like in the Application Insights portal when you use Application Insights Analytics:

Resultados de la consulta de Application Insights

Puede encontrar útiles datos estructurados en el customDimensions campo en cada entrada de registro.You can find useful structured data in the customDimensions field in each log entry. Este es un ejemplo de una entrada que se expande totalmente:Here's an example of an entry that is fully expanded:

El campo customDimensions en una consulta de Application Insights

Debido al comportamiento de la reproducción del distribuidor de Durable Task Framework, podrá ver entradas del registro redundantes para acciones reproducidas.Because of the replay behavior of the Durable Task Framework dispatcher, you can expect to see redundant log entries for replayed actions. Entradas del registro redundantes pueden ayudarle a entender el comportamiento de reproducción del motor principal.Redundant log entries can help you understand the replay behavior of the core engine. El diagnósticos artículo muestra ejemplos de consultas que filtran los registros de reproducción para que pueda ver los registros de "en tiempo real".The Diagnostics article shows sample queries that filter out replay logs, so you can see just the "real-time" logs.

Almacenamiento y la escalabilidadStorage and scalability

La extensión Durable Functions usa blobs, tablas y colas de Azure Storage para conservar ejecución historial desencadenador y el estado de ejecución de la función.The Durable Functions extension uses queues, tables, and blobs in Azure Storage to persist execution history state and trigger function execution. Puede usar la cuenta de almacenamiento predeterminada para la aplicación de función, o puede configurar una cuenta de almacenamiento independiente.You can use the default storage account for the function app, or you can configure a separate storage account. Es posible que desee una cuenta independiente en función de los límites de rendimiento de almacenamiento.You might want a separate account based on storage throughput limits. El código de orquestador que escribe no interactúa con las entidades en estas cuentas de almacenamiento.The orchestrator code you write doesn't interact with the entities in these storage accounts. Durable Task Framework administra las entidades directamente como un detalle de implementación.The Durable Task Framework manages the entities directly as an implementation detail.

Las funciones del orquestador programan funciones de actividad y reciben sus respuestas a través de mensajes de la cola interna.Orchestrator functions schedule activity functions and receive their responses via internal queue messages. Cuando se ejecuta una aplicación de función en el plan de consumo de Azure Functions, el controlador de escala de Azure Functions supervisa estas colas.When a function app runs in the Azure Functions consumption plan, the Azure Functions scale controller monitors these queues. Se agregan nuevas instancias de proceso según sea necesario.New compute instances are added as needed. Al escalar horizontalmente a varias máquinas virtuales, puede ejecutar una función de orquestador en una máquina virtual, mientras que las funciones de actividad que las llamadas de función de orquestador se pueden ejecutar en varias máquinas virtuales diferentes.When scaled out to multiple VMs, an orchestrator function might run on one VM, while activity functions that the orchestrator function calls might run on several different VMs. Para obtener más información sobre el comportamiento de la escala de Durable Functions, consulte de escala y rendimiento.For more information about the scale behavior of Durable Functions, see Performance and scale.

El historial de ejecución para las cuentas de orchestrator se almacena en table storage.The execution history for orchestrator accounts is stored in table storage. Cada vez que una instancia se rehidrata en una máquina virtual concreta, el orquestador captura su historial de ejecución de table storage, por lo que puede volver a generar su estado local.Whenever an instance rehydrates on a particular VM, the orchestrator fetches its execution history from table storage so it can rebuild its local state. Un aspecto cómodo de tener el historial disponible en table storage es que puede usar herramientas como Explorador de Azure Storage para ver el historial de las orquestaciones.A convenient aspect of having the history available in table storage is that you can use tools like Azure Storage Explorer to see the history of your orchestrations.

Los blobs de almacenamiento se utilizan principalmente como un mecanismo de concesiones para coordinar el escalado horizontal de las instancias de orquestación en varias máquinas virtuales.Storage blobs are primarily used as a leasing mechanism to coordinate the scale-out of orchestration instances across multiple VMs. Los blobs de almacenamiento contienen datos para los mensajes grandes que no se puede almacenar directamente en las tablas o colas.Storage blobs hold data for large messages that can't be stored directly in tables or queues.

Captura de pantalla del explorador de Azure Storage

Nota

Aunque es fácil y cómodo ver el historial de ejecución en table storage, no realice ninguna dependencia en esta tabla.Although it's easy and convenient to see execution history in table storage, don't make any dependencies on this table. La tabla podría cambiar a medida que evoluciona la extensión Durable Functions.The table might change as the Durable Functions extension evolves.

Problemas conocidosKnown issues

Todos los problemas conocidos deben encontrarse en la lista de problemas en GitHub.All known issues should be tracked in the GitHub issues list. Si experimenta un problema y no se encuentra el problema en GitHub, abra un nuevo problema.If you run into a problem and can't find the issue in GitHub, open a new issue. Incluya una descripción detallada del problema.Include a detailed description of the problem.

Pasos siguientesNext steps

Para obtener más información acerca de Durable Functions, consulte tipos y características de funciones de Durable Functions.To learn more about Durable Functions, see Durable Functions function types and features.

Primeros pasos:To get started: