En este capítulo, vas a aprender lo siguiente:
- Configurar Durable Functions en el portal de administración de Azure
- Crear una aplicación Hola, mundo de Durable Functions
- Probar y solucionar problemas de Durable Functions
- Implementar aplicaciones fiables multiproceso mediante Durable Functions
Introducción
Al trabajar en el desarrollo de aplicaciones modernas que deban estar alojadas en el cloud, debes asegurarte de que las aplicaciones no tengan estado. El hecho de no tener estado es un factor esencial para el desarrollo de aplicaciones compatibles con el cloud. Por ejemplo, debes evitar la persistencia de cualquier dato en el recurso que sea específico para cualquier instancia de máquina virtual (VM) aprovisionada para cualquier servicio de Azure (por ejemplo, el servicio de aplicaciones, la API, etc.). Si lo haces, no puedes aprovechar algunos de los servicios, como la funcionalidad de escalado automático, ya que el aprovisionamiento de instancias es dinámico. Si dependes de algún recurso específico de la máquina virtual, te encontrarás con comportamientos inesperados.
Dicho esto, la desventaja del enfoque mencionado anteriormente es que terminas trabajando en la identificación de formas de persistencia de datos en diferentes medios, dependiendo de la arquitectura de tu aplicación.
Para obtener más información sobre Durable Functions, consulta la documentación oficial, disponible en https://docs.microsoft.com/ en-us/azure/azure-functions/durable-functions-overview.
Configurar Durable Functions en el portal de administración de Azure
Azure ha ideado una nueva forma de manejar el hecho de no tener estado en la arquitectura sin servidor, junto con otras características, como la durabilidad y la fiabilidad, en forma de Durable Functions. Está disponible como una extensión de Azure Functions. En este capítulo, comenzaremos a descubrir las Durable Functions.
Preparación
Crea una nueva aplicación de función si aún no está creada. Asegúrate de que la versión del runtime sea ~2 en Configuración de la aplicación, como se muestra en la siguiente captura de pantalla:

Cómo hacerlo…
Sigue estos pasos:
- Haz clic en el botón + para crear una función nueva:

- Crea una nueva función de inicio HTTP de Durable Functions seleccionando Durable Functions en el menú desplegable Escenario, como se muestra en la siguiente captura de pantalla:

- Posteriormente, se abrirá una pestaña nueva:

- Haz clic en el botón Instalar, que se muestra en el paso anterior, para iniciar la instalación de extensiones DurableTask. La instalación de las dependencias debería de llevar alrededor de dos minutos:

- Una vez que se complete el proceso, debe aparecer lo siguiente:

Y eso no es todo…
Actualmente, C# es el único lenguaje compatible para el desarrollo de Durable
Functions. La compatibilidad con otros lenguajes se encuentra en la fase de preview.
Crear una aplicación Hola, mundo de Durable Functions
Aunque la intención general de este libro es que cada receta de cada capítulo resuelva al menos un problema empresarial, esta receta no resuelve ningún problema de dominio en tiempo real. En su lugar, proporciona orientación de inicio rápido para ayudarte a comprender mejor las Durable Functions y sus componentes, junto con el enfoque del desarrollo de Durable Functions. En el siguiente capítulo, descubriremos lo fácil que es desarrollar una aplicación basada en el flujo de trabajo utilizando Durable Functions.
Preparación
Antes de seguir avanzando, vamos a seguir estos pasos:
- Si no lo has hecho ya, descarga e instala Postman desde https://www.getpostman.com/
- Obtén más información acerca del orquestador y los enlaces de desencadenador de actividad en https://docs.microsoft.com/en-us/ azure/azure-functions/durable-functions-bindings
Cómo hacerlo…
Para desarrollar Durable Functions, es necesario que creemos las tres funciones siguientes:
- Cliente de orquestador: una función de Azure que puede administrar instancias de orquestador.
- Función de orquestador: la función real de orquestador permite el desarrollo de flujos de trabajo con estado a través de código. Estas funciones pueden llamar de forma asincrónica a otras Azure Functions (denominadas Funciones de actividad), e incluso pueden guardar los valores devueltos de estas funciones en variables locales.
- Funciones de actividad: son las funciones a las que llamarán las funciones del orquestador.
Crear una función HttpStart en el cliente de orquestador
Sigue estos pasos:
- Crea una nueva función de inicio HTTP de Durable Functions seleccionando Durable Functions en el menú desplegable Escenario y haz clic en el inicio HTTP de Durable Functions, que abre una pestaña nueva que se muestra a continuación. Vamos a crear una nueva función HTTP denominada HttpStart:

- Poco después, se te dirigirá al editor de código. La siguiente función es un desencadenador de HTTP que acepta el nombre de la función que debe ejecutarse junto con la entrada. Utiliza el método StartNewAsync del objeto DurableOrchestrationClient para iniciar la orquestación:
#r «Microsoft.Azure.WebJobs.Extensions.DurableTask»
#r «Newtonsoft.Json» using System.Net;
public static async Task<HttpResponseMessage> Run(
HttpRequestMessage req,
DurableOrchestrationClient starter, string functionName,
ILogger log)
{
// 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); }
- Ve a la pestaña Integrar y haz clic en Editor avanzado, como se muestra en la siguiente captura de pantalla:

- En el Editor avanzado, los enlaces deben ser similares a los siguientes. En caso contrario, reemplaza el código predeterminado por el código siguiente:
{ «bindings»:
[
{
«authLevel»: «anonymous»,
«name»: «req»,
«type»: «httpTrigger»,
«direction»: «in»,
«route»: «orchestrators/{functionName}»,
«methods»: [
«post»,
«get»
]
},
{
«name»: «$return»,
«type»: «http»,
«direction»: «out»
},
{
«name»: «starter»,
«type»: «orchestrationClient»,
«direction»: «in»
}
]
}
La función HttpStart actúa como una puerta de enlace para invocar todas las funciones de la aplicación de función. Cualquier solicitud que realices utilizando el formato de URL https://<durablefunctionname>>.azurewebsites.net/ api/orchestrators/{functionName} la recibirá esta función HttpStart. Esta función se encargará de ejecutar la función de orquestador en función del parámetro disponible en el parámetro de ruta {functionName}. Todo esto es posible con el atributo de ruta, definido en function.json de la función HttpStart.
Crear la función de orquestador
Sigue estos pasos:
- Vamos a crear una función de orquestador haciendo clic en la plantilla Orquestador de Durable Functions, como se muestra a continuación:

- Después de hacer clic en el mosaico Orquestador de Durable Functions, se te redirigirá a la pestaña siguiente donde proporcionarás el nombre de la función. Después de proporcionar el nombre, haz clic en el botón Crear para crear la función de orquestador:

- En DurableFuncManager, reemplaza el código predeterminado con el siguiente y haz clic en el botón Guardar para guardar los cambios: el siguiente orquestador llamará a las funciones de actividad mediante el método CallActivityAsync del objeto DurableOrchestraionContext:
#r «Microsoft.Azure.WebJobs.Extensions.DurableTask» public static async Task<List<string>> Run(DurableOrchestrationContext context)
{
var outputs = new List<string>(); outputs.Add(await context.CallActivityAsync<string> («ConveyGreeting», «Welcome Cookbook Readers»)); return outputs; }
- En el Editor avanzado de la pestaña Integrar, sustituye el código predeterminado por el código siguiente:
{
«bindings»: [
{
«name»: «context»,
«type»: «orchestrationTrigger»,
«direction»: «in»
}
]
}
Crear una función de actividad
Sigue estos pasos:
- Crea una función nueva denominada ConveyGreeting utilizando la plantilla Actividad de Durable Functions:

- Sustituye el código predeterminado por el código siguiente que solo muestra el nombre que se proporciona como entrada y, a continuación, haz clic en el botón Guardar para guardar los cambios:
#r «Microsoft.Azure.WebJobs.Extensions.DurableTask» public static string Run(string name)
{
return $»Hello Welcome Cookbook Readers!»; }
- En el Editor avanzado de la pestaña Integrar, sustituye el código predeterminado por el código siguiente:
{
«bindings»: [
{
«name»: «name»,
«type»: «activityTrigger»,
«direction»: «in»
}
]
}
En esta receta, hemos creado un cliente de orquestación, una función de orquestador y una función de actividad. Descubriremos cómo probarlos en nuestra próxima receta.
Cómo funciona…
Echemos un vistazo al funcionamiento de la receta:
- Primero desarrollamos el cliente de orquestador (en nuestro caso, HttpStart), que es capaz de crear orquestadores utilizando la función StartNewAsync de la clase DurableOrchestrationClient. Este método crea una nueva instancia de orquestador.
- Después, desarrollamos la función de orquestador, la parte más importante de Durable Functions. A continuación, encontramos algunas de las características principales más importantes del contexto de orquestador:
° Puede invocar varias funciones de actividad
° Puede guardar la salida devuelta por una función de actividad y pasarla a otra función de actividad.
° Estas funciones de orquestador también son capaces de crear puntos de control que guardan puntos de ejecución, de modo que si hay algún problema con las máquinas virtuales, es posible reemplazar o reanudar el servicio automáticamente.
- Y, por último, desarrollamos la función de actividad, donde escribimos la mayor parte de la lógica empresarial. En nuestro caso, solo está devolviendo un mensaje simple.
Y eso no es todo…
Las Durable Functions dependen del marco de tareas durables. Puedes obtener más información sobre el marco de tareas durables en https://github.com/Azure/ durabletask.
Probar y solucionar problemas de Durable Functions
En los capítulos anteriores, hemos analizado varias formas de probar Azure Functions. Podemos probar Durable Functions con el mismo conjunto de herramientas. Sin embargo, el enfoque de las pruebas es completamente diferente debido a sus características y la forma en que funciona.
En esta receta, descubriremos algunas de las cosas esenciales que uno debe tener en cuenta al trabajar con Durable Functions.
Preparación
Si aún no lo has hecho, descarga e instala:
- La herramienta Postman, disponible en https://www.getpostman.com.
- Explorador de Microsoft Azure Storage, disponible en http:// storageexplorer.com.
Cómo hacerlo…
Sigue estos pasos:
- Desplázate hasta el editor de código de la función HttpStart y obtén la URL haciendo clic en </>Obtener la dirección URL de la función. Sustituye el valor de la plantilla {functionName} por DurableFuncManager.
- Hagamos una solicitud POST mediante Postman:

- Después de hacer clic en el botón Guardar, obtendrás una respuesta con lo siguiente:
° El ID de instancia
° La dirección URL para recuperar el estado de la función
° La dirección URL para enviar un evento a la función
° La dirección URL para finalizar la solicitud

- Haz clic en statusQueryGetUri en el paso anterior para ver el estado de la función. Al hacer clic en el enlace en el paso anterior, se abrirá la consulta en una pestaña nueva de la herramienta Postman. Una vez abierta la pestaña nueva, haz clic en el botón Enviar para obtener el resultado real:

- Si todo va bien, podemos ver runtimeStatus como Completado en Postman, como se muestra en la captura de pantalla anterior. También obtendrás ocho registros en el almacenamiento de tablas, donde se almacena el historial de ejecución, que se muestra a continuación:

- Si algo ha ido mal, puedes ver el mensaje de error en la columna de resultados, en la que se detalla en qué función ha ocurrido el error. A continuación, desplázate a la pestaña Monitor de esa función para ver una explicación detallada del error.
Implementar aplicaciones fiables multiproceso mediante Durable Functions
He trabajado en algunas de las aplicaciones donde se requiere la ejecución paralela para realizar algunas tareas informáticas. La ventaja principal de este enfoque es que se obtiene el resultado deseado con bastante rapidez según los subprocesos que se creen. Se podría lograr de varias maneras utilizando diferentes tecnologías. Sin embargo, el desafío en estos enfoques es que, si algo sale mal en medio de cualquiera de los subprocesos, no es fácil realizar la autorreparación y reanudar desde el punto en el que se detuvo. Estoy seguro de que muchos de vosotros os habéis enfrentado a problemas similares en vuestra aplicación, ya que es un caso empresarial muy común.
En esta receta, implementaremos una forma sencilla de ejecutar una función en paralelo con varias instancias utilizando Durable Functions para el siguiente escenario.
Supongamos que tenemos cinco clientes (cuyos ID son 1, 2, 3, 4 y 5, respectivamente) que se nos acercaron para generar una gran cantidad de códigos de barras (por ejemplo, alrededor de 50 000). Tomaría mucho tiempo generar los códigos de barras, ya que implicaría algunas tareas de procesamiento de imágenes. Por lo tanto, una forma sencilla de procesar rápidamente la solicitud es utilizar la programación asincrónica creando un hilo para cada uno de los clientes y luego ejecutando la lógica en paralelo para cada uno de ellos.
También simularemos un caso de uso simple para comprender cómo las Durable Functions se reparan automáticamente cuando la máquina virtual en la que están alojadas se desactiva o se reinicia.
Preparación
Si aún no lo has hecho, instala:
- La herramienta Postman, disponible en https://www.getpostman.com/
- Explorador de Microsoft Azure Storage, disponible en http:// storageexplorer.com/
Cómo hacerlo…
En esta receta, crearemos los siguientes desencadenadores de la función de Azure:
- Una función de orquestador, denominada GenerateBARCode
- Dos funciones de desencadenador de actividad, que son:
° GetAllCustomers: para hacerlo simple, esta función simplemente devuelve la matriz de ID de clientes. En tus aplicaciones del mundo real, dispondrías de lógica empresarial que decidiría qué clientes son aptos y, en función de esa lógica, devolverías los ID de los clientes aptos.
° CreateBARCodeImagesPerCustomer: esta función no crea realmente el código de barras; más bien, simplemente registra un mensaje en la consola, ya que nuestro objetivo es comprender las características de las Durable Functions. Para cada cliente, generaremos aleatoriamente un número inferior a 50 000 y simplemente iteraremos a través de ese número.
Crear la función de orquestador
Sigue estos pasos:
1. Crea una función nueva denominada GenerateBARCode utilizando la plantilla orquestador de Durable Functions. Reemplaza el código predeterminado por el siguiente y haz clic en el botón Guardar para guardar los cambios. El siguiente código clasifica inicialmente la función de actividad GetAllCustomers, almacena todos los identificadores de los clientes en una matriz y luego, para cada cliente, vuelve a llamar a otra función de actividad que devuelve el número de códigos de barras que se generan. Finalmente, espera hasta que las funciones de actividad para todos los clientes se completen y luego devuelve la suma de todos los códigos de barras que se generan para todos los clientes.
#r «Microsoft.Azure.WebJobs.Extensions.DurableTask» public static async Task<int> Run(
DurableOrchestrationContext context)
{
int[] customers = await
context.CallActivityAsync<int[]>(«GetAllCustomers»,null);
var tasks = new Task<int>[customers.Length]; for (int nCustomerIndex = 0; nCustomerIndex < customers.
Length; nCustomerIndex++)
{
tasks[nCustomerIndex] = context.CallActivityAsync<int>
(«CreateBARCodeImagesPerCustomer»,
customers[nCustomerIndex]);
}
await Task.WhenAll(tasks);
int nTotalItems = tasks.Sum(item => item.Result);
return nTotalItems; }
2. En el Editor avanzado de la pestaña Integrar, sustituye el código predeterminado por el código siguiente:
{
«bindings»: [
{
«name»: «context»,
«type»: «orchestrationTrigger»,
«direction»: «in»
}
]
}
Crear una función de actividad GetAllCustomers
Sigue estos pasos:
- Crea una función nueva denominada GetAllCustomers con la plantilla de actividad de Durable Functions, sustituye el código predeterminado por el código siguiente y, a continuación, haz clic en el botón Guardar para guardar los cambios:
#r «Microsoft.Azure.WebJobs.Extensions.DurableTask» public static int[] Run(string name)
{
int[] customers = new int[]{1,2,3,4,5}; return customers; }
- En el Editor avanzado de la pestaña Integrar, sustituye el código predeterminado por el código siguiente:
{
«bindings»: [
{
«name»: «name»,
«type»: «activityTrigger»,
«direction»: «in»
}
]
}
Crear una función de actividad CreateBARCodeImagesPerCustomer
Sigue estos pasos:
1. Crea una función nueva denominada CreateBARCodeImagesPerCustomer utilizando la plantilla Actividad de Durable Functions. Reemplaza el código predeterminado por el siguiente y luego haz clic en el botón Guardar para guardar los cambios:
#r «Microsoft.Azure.WebJobs.Extensions.DurableTask»
#r «Microsoft.WindowsAzure.Storage» using Microsoft.WindowsAzure.Storage.Blob;
public static async Task<int> Run(DurableActivityContext customerContext,ILogger log)
{
int ncustomerId = Convert.ToInt32 (customerContext.GetInput<string>());
Random objRandom = new Random(Guid.NewGuid().
GetHashCode());
int nRandomValue = objRandom.Next(50000); for(int nProcessIndex = 0;nProcessIndex<=nRandomValue; nProcessIndex++)
{
log.LogInformation($» running for {nProcessIndex}»);
}
return nRandomValue; }
- En el Editor avanzado de la pestaña Integrar, sustituye el código predeterminado por el código siguiente:
{
«bindings»: [
{
«name»: «customerContext»,
«type»: «activityTrigger»,
«direction»: «in»
}
]
}
- Vamos a ejecutar la función con Postman. Detendremos App Service para simular un reinicio de la máquina virtual en la que se ejecutaría la función para ver cómo Durable Function reanuda el proceso desde el punto en el que se detuvo.
- Realiza una solicitud POST utilizando Postman, como se muestra a continuación:

- Después de hacer clic en el botón Guardar, obtendrás una respuesta con la dirección URL de estado. Haz clic en statusQueryGetURi para ver el estado de la función. Al hacer clic en el enlace statusQueryGetURi, se abrirá en una pestaña nueva en la herramienta Postman. Una vez abierta la pestaña nueva, haz clic en el botón Enviar para ver el progreso de la función.
- Mientras se está ejecutando la función, dirígete a la hoja Información general de la aplicación de función y detén el servicio haciendo clic en el botón Detener:

- La ejecución de la función se detendrá a la mitad. Vayamos a nuestra cuenta de almacenamiento en Storage Explorer y abramos la tabla DurableFunctionsHubHistory para ver el progreso:

- Después de un tiempo (en mi caso, después de solo cinco minutos), vuelve a la hoja Información general e inicia el servicio de aplicaciones de la función. Verás que la Durable Function se reanudará desde el punto en el que se detuvo. No escribimos ningún código para ello; es una característica «out-of-the-box». A continuación, se muestra la captura de pantalla de la función completada:

Cómo funciona…
Durable Functions nos permiten desarrollar una ejecución fiable de nuestras funciones, lo que significa que, aunque las máquinas virtuales se bloqueen o se reinicien mientras la función se esté ejecutando, vuelve automáticamente a su estado anterior. Lo hace con la ayuda de lo que se denomina crear punto de comprobación y reproducir, donde el historial de la ejecución se almacena en la tabla de almacenamiento.
Puedes ver más información sobre esta característica en https:// docs.microsoft.com/en-us/azure/azure-functions/ durable-functions-checkpointing-and-replay.
Y eso no es todo…
- Si obtienes la respuesta 404 No encontrado al ejecutar la dirección URL statusQueryGetURi, no te preocupes. Llevará algún tiempo, pero finalmente funcionará cuando hagas una solicitud más adelante.
- Para ver el historial de ejecución de tus Durable Functions, dirígete a la tabla DurableFunctionsHubHistory, que se encuentra en la cuenta de almacenamiento surgida al crear la aplicación de la función:

Encontrarás el nombre de la cuenta de almacenamiento en Configuración de la aplicación, como se muestra en la captura de pantalla anterior.