Guía para solucionar problemas de Durable Functions

Durable Functions es una extensión de Azure Functions que permite crear orquestaciones sin servidor mediante código normal. Para más información sobre Durable Functions, consulte la Información general de Durable Functions.

En este artículo se proporciona una guía para solucionar problemas de escenarios comunes en aplicaciones Durable Functions.

Nota:

Los ingenieros de soporte técnico de Microsoft están disponibles para ayudar a diagnosticar problemas con la aplicación. Si no puede diagnosticar el problema mediante esta guía, puede presentar una incidencia de soporte técnico si accede a la hoja Nueva solicitud de soporte técnico en la sección Soporte técnico y solución de problemas de la página de la aplicación de funciones en Azure Portal.

Screenshot of support request page in Azure Portal.

Sugerencia

A la hora de depurar y diagnosticar problemas, se recomienda empezar por asegurarse de que la aplicación utiliza la última versión de la extensión Durable Functions. La mayoría de las veces, el uso de la versión más reciente mitiga los problemas conocidos ya notificados por otros usuarios. Lea el artículo Actualización de la versión de extensión Durable Functions para obtener instrucciones sobre cómo actualizar la versión de su extensión.

La pestaña Diagnosticar y resolver problemas de Azure Portal es un recurso útil para supervisar y diagnosticar posibles problemas relacionados con su aplicación. También proporciona soluciones potenciales a sus problemas en función del diagnóstico. Consulte Diagnóstico de aplicaciones Azure Function para obtener más detalles.

Si los recursos anteriores no han resuelto su problema, las siguientes secciones ofrecen consejos para síntomas de aplicación específicos:

La orquestación está bloqueada en el estado Pending

Cuando se inicia una orquestación, se escribe un mensaje de "inicio" en una cola interna administrada por la extensión Durable, y el estado de la orquestación se establece en "Pendiente". Después de que el mensaje de orquestación sea recogido y procesado con éxito por una instancia de aplicación disponible, el estado pasará a "En ejecución" (o a algún otro estado que no sea "Pendiente").

Siga estos pasos para solucionar los problemas de las instancias de orquestación que permanecen atascadas indefinidamente en el estado "Pendiente".

  • Compruebe las trazas de Durable Task Framework en busca de advertencias o errores para el Id. de instancia de orquestación afectado. Encontrará un ejemplo de consulta en la sección Errores/Advertencias de seguimiento.

  • Compruebe las colas de control de Azure Storage asignadas al orquestador bloqueado para ver si su "mensaje de inicio" todavía está ahí. Para más información sobre las colas de control, consulte la documentación sobre la cola de control del proveedor de Azure Storage.

  • Cambie la versión de configuración de la plataforma de su aplicación a "64 bits". A veces, las orquestaciones no se inician porque la aplicación se está quedando sin memoria. Cambiar al proceso de 64 bits permite a la aplicación asignar más memoria total. Esto solo se aplica a los planes Básico, Estándar, Premium y Elastic Premium de App Service. Los planes gratuitos o de consumo no admiten procesos de 64 bits.

La orquestación se inicia después de un retraso largo

Normalmente, las orquestaciones se inician en unos segundos después de que se programen. Sin embargo, hay ciertos casos en los que las orquestaciones pueden tardar más tiempo en iniciarse. Siga estos pasos para solucionar problemas cuando las orquestaciones tarden más de unos segundos en empezar a ejecutarse.

La orquestación no se completa o está bloqueada en el estado Running

Si una orquestación permanece en el estado "En ejecución" durante un largo periodo de tiempo, suele significar que está esperando a que se complete una tarea de larga duración que está programada. Por ejemplo, podría estar esperando a que se complete una tarea de temporizador durable, una tarea de actividad o una tarea de evento externo. Sin embargo, si observa que las tareas programadas se han completado correctamente, pero la orquestación todavía no está progresando, puede haber un problema que impida que la orquestación continúe con su siguiente tarea. Las orquestaciones en este estado suelen denominarse "orquestaciones bloqueadas".

Siga los siguientes pasos para solucionar problemas de orquestaciones bloqueadas:

  • Intente reiniciar la aplicación de funciones. Este paso puede ayudar si la orquestación se bloquea debido a un error transitorio o interbloqueo en la aplicación o en el código de extensión.

  • Compruebe las colas de control de cuentas de Azure Storage para ver si alguna cola crece continuamente. Esta consulta de KQL de mensajería de Azure Storage puede ayudar a identificar problemas con la puesta en cola de mensajes de orquestación. Si el problema afecta solo a una cola de control, podría indicar un problema que existe solo en una instancia de aplicación específica, en cuyo caso el escalado vertical u horizontal para salir de la instancia de VM incorrecto podría ayudar.

  • Use la consulta Application Insights en la sección Azure Storage Messaging para filtrar ese nombre de cola como Id. de partición y busque cualquier problema relacionado con esa partición de cola de control.

  • Consulte la guía de Procedimiento recomendado y herramientas de diagnóstico de Durable Functions. Algunos problemas pueden deberse a antipatrones conocidos de Durable Functions.

  • Consulte la documentación de control de versiones de Durable Functions. Algunos problemas pueden deberse a cambios importantes en las instancias de orquestación en curso.

La orquestación se ejecuta lentamente

El procesamiento intensivo de datos, los errores internos y los recursos de proceso insuficientes pueden hacer que las orquestaciones se ejecuten más lentamente de lo normal. Siga estos pasos para solucionar problemas de orquestaciones que tardan más de lo esperado en ejecutarse:

  • Compruebe las trazas de Durable Task Framework en busca de advertencias o errores para el Id. de instancia de orquestación afectado. Encontrará un ejemplo de consulta en la sección Errores/Advertencias de seguimiento.

  • Si su aplicación utiliza el modelo .NET en proceso, considere la posibilidad de habilitar las sesiones extendidas. Las sesiones extendidas pueden minimizar las cargas del historial, lo que puede ralentizar el procesamiento.

  • Compruebe los cuellos de botella de rendimiento y escalabilidad. El rendimiento de una aplicación depende de muchos factores. Por ejemplo, un uso elevado de CPU o un consumo de memoria grande puede provocar retrasos. Lea Rendimiento y reducción horizontal en Durable Functions para obtener orientación detallada.

Consultas de ejemplo

En esta sección se muestra cómo solucionar problemas escribiendo consultas KQL personalizadas en la instancia de Azure Application Insights configurada para su aplicación Azure Functions.

Mensajería de Azure Storage

Cuando se utiliza el proveedor Azure Storage predeterminado, todo el comportamiento de Durable Functions se rige por los mensajes de cola de Azure Storage y todo el estado relacionado con una orquestación se almacena en el almacenamiento de tablas y el almacenamiento de blobs. Cuando se habilita el seguimiento de Durable Task Framework, todas las interacciones de Azure Storage se registran en Application Insights, y estos datos son de vital importancia para depurar problemas de ejecución y rendimiento.

A partir de la versión 2.3.0 de la extensión Durable Functions, puede publicar estos registros de Durable Task Framework en su instancia de Application Insights actualizando la configuración de registro en el archivo host.json. Consulte el artículo sobre registro en Durable Task Framework para obtener información e instrucciones sobre cómo hacerlo.

La siguiente consulta es para inspeccionar las interacciones de Azure Storage de un extremo a otro para una instancia de orquestación específica. Edite start y orchestrationInstanceID para filtrar por intervalo de tiempo e Id. de instancia.

let start = datetime(XXXX-XX-XXTXX:XX:XX); // edit this 
let orchestrationInstanceID = "XXXXXXX"; //edit this
traces  
| where timestamp > start and timestamp < start + 1h 
| where customDimensions.Category == "DurableTask.AzureStorage" 
| extend taskName = customDimensions["EventName"]
| extend eventType = customDimensions["prop__EventType"] 
| extend extendedSession = customDimensions["prop__IsExtendedSession"]
| extend account = customDimensions["prop__Account"] 
| extend details = customDimensions["prop__Details"] 
| extend instanceId = customDimensions["prop__InstanceId"] 
| extend messageId = customDimensions["prop__MessageId"] 
| extend executionId = customDimensions["prop__ExecutionId"] 
| extend age = customDimensions["prop__Age"] 
| extend latencyMs = customDimensions["prop__LatencyMs"] 
| extend dequeueCount = customDimensions["prop__DequeueCount"] 
| extend partitionId = customDimensions["prop__PartitionId"] 
| extend eventCount = customDimensions["prop__TotalEventCount"] 
| extend taskHub = customDimensions["prop__TaskHub"] 
| extend pid = customDimensions["ProcessId"]
| extend appName = cloud_RoleName
| extend newEvents = customDimensions["prop__NewEvents"]
| where instanceId == orchestrationInstanceID
| sort by timestamp asc
| project timestamp, appName, severityLevel, pid, taskName, eventType, message, details, messageId, partitionId, instanceId, executionId, age, latencyMs, dequeueCount, eventCount, newEvents, taskHub, account, extendedSession, sdkVersion

Errores/advertencias de seguimiento

La siguiente consulta busca errores y advertencias para una instancia de orquestación determinada. Deberá proporcionar un valor para orchestrationInstanceID.

let orchestrationInstanceID = "XXXXXX"; // edit this
let start = datetime(XXXX-XX-XXTXX:XX:XX); 
traces  
| where timestamp > start and timestamp < start + 1h
| extend instanceId = iif(isnull(customDimensions["prop__InstanceId"] ) , customDimensions["prop__instanceId"], customDimensions["prop__InstanceId"] ) 
| extend logLevel = customDimensions["LogLevel"]
| extend functionName = customDimensions["prop__functionName"]
| extend status = customDimensions["prop__status"]
| extend details = customDimensions["prop__Details"] 
| extend reason = customDimensions["prop__reason"]
| where severityLevel > 1 // to see all logs of  severity level "Information" or greater.
| where instanceId == orchestrationInstanceID
| sort by timestamp asc 

Cola de control / Registros de Id. de partición

La siguiente consulta busca toda la actividad asociada a la cola de control de un instanceId. Deberá indicar el valor de instanceID en orchestrationInstanceID y la hora de inicio de la consulta en start.

let orchestrationInstanceID = "XXXXXX"; // edit this
let start = datetime(XXXX-XX-XXTXX:XX:XX); // edit this
traces  // determine control queue for this orchestrator
| where timestamp > start and timestamp < start + 1h 
| extend instanceId = customDimensions["prop__TargetInstanceId"] 
| extend partitionId = tostring(customDimensions["prop__PartitionId"])
| where partitionId contains "control" 
| where instanceId == orchestrationInstanceID
| join kind = rightsemi(
traces  
| where timestamp > start and timestamp < start + 1h 
| where customDimensions.Category == "DurableTask.AzureStorage" 
| extend taskName = customDimensions["EventName"]
| extend eventType = customDimensions["prop__EventType"] 
| extend extendedSession = customDimensions["prop__IsExtendedSession"]
| extend account = customDimensions["prop__Account"] 
| extend details = customDimensions["prop__Details"] 
| extend instanceId = customDimensions["prop__InstanceId"] 
| extend messageId = customDimensions["prop__MessageId"] 
| extend executionId = customDimensions["prop__ExecutionId"] 
| extend age = customDimensions["prop__Age"] 
| extend latencyMs = customDimensions["prop__LatencyMs"] 
| extend dequeueCount = customDimensions["prop__DequeueCount"] 
| extend partitionId = tostring(customDimensions["prop__PartitionId"])
| extend eventCount = customDimensions["prop__TotalEventCount"] 
| extend taskHub = customDimensions["prop__TaskHub"] 
| extend pid = customDimensions["ProcessId"]
| extend appName = cloud_RoleName
| extend newEvents = customDimensions["prop__NewEvents"]
) on partitionId
| sort by timestamp asc
| project timestamp, appName, severityLevel, pid, taskName, eventType, message, details, messageId, partitionId, instanceId, executionId, age, latencyMs, dequeueCount, eventCount, newEvents, taskHub, account, extendedSession, sdkVersion

Referencia de columna de Application Insights

A continuación se muestra una lista de las columnas proyectadas por las consultas anteriores y sus descripciones respectivas.

Columna Descripción
pid Id. de proceso de la instancia de la aplicación de funciones. Esto resulta útil para determinar si el proceso se recicló mientras se estaba ejecutando una orquestación.
taskName El nombre del evento que se está registrando.
eventType El tipo de mensaje, que suele representar el trabajo realizado por un orquestador. La lista completa de sus posibles valores y sus descripciones se encuentra aquí
extendedSession Valor booleano que indica si las sesiones extendidas están habilitadas.
account La cuenta de almacenamiento utilizada por la aplicación.
detalles Información adicional sobre un evento determinado, si está disponible.
instanceId El Id. de una instancia de orquestación o entidad determinada.
messageId El Id. único de Azure Storage para un mensaje de cola determinado. Este valor suele aparecer en los eventos de seguimiento ReceivedMessage, ProcessingMessage y DeletingMessage. Ten en cuenta que NO está presente en los eventos SendingMessage porque el Id. del mensaje lo genera Azure Storage después de que enviemos el mensaje.
executionId El Id. de la ejecución del orquestador, que cambia cada vez que se invoca continue-as-new.
age Número de milisegundos desde que se puso en cola un mensaje. Los números grandes suelen indicar problemas de rendimiento. Una excepción es el tipo de mensaje TimerFired, que puede tener un valor Age grande en función de la duración del temporizador.
latencyMs Número de milisegundos tomados por alguna operación de almacenamiento.
dequeueCount El número de veces que un mensaje se ha quitado de la cola. En circunstancias normales, este valor siempre es 1. Si es más de uno, podría haber un problema.
partitionId Nombre de la cola asociada a este registro.
totalEventCount Número de eventos de historial implicados en la acción actual.
taskHub El nombre de su central de tareas.
newEvents Una lista separada por comas de los eventos de historial que se están escribiendo en la tabla Historial almacenada.