Reintentos y control de errores de Azure Functions

El control de los errores en Azure Functions es importante para ayudarle a evitar la pérdida de datos, evitar eventos perdidos y para supervisar el estado de la aplicación. También es una forma importante de ayudarle a comprender los comportamientos de reintento de los desencadenadores basados en eventos.

En este artículo se describen las estrategias generales para el control de errores y las estrategias de reintento disponibles.

Importante

Quitaremos la compatibilidad con la directiva de reintento en el entorno de ejecución para desencadenadores distintos de Temporizador, Kafka y Event Hubs después de que esta característica esté disponible con carácter general (GA). La compatibilidad con la directiva de reintentos de versión preliminar para todos los desencadenadores que no sean Temporizador y Event Hubs se quitó en diciembre de 2022. Para más información, consulte la sección Reintentos.

Control de errores

Los errores que se produzcan en una función de Azure podrían deberse a cualquiera de las siguientes acciones:

  • Uso de desencadenadores y enlaces de Azure Functions integrados
  • Llamadas a las API de los servicios de Azure subyacentes
  • Llamadas a puntos de conexión REST
  • Llamadas a bibliotecas de cliente, paquetes o API de terceros

Para evitar la pérdida de datos o mensajes perdidos es importante llevar a cabo un buen control de errores. Esta sección describe algunas prácticas recomendadas para el manejo de errores y proporciona enlaces a más información.

Habilitación de Application Insights

Azure Functions se integra con Application Ideas para recopilar datos de error, datos de rendimiento y registros en tiempo de ejecución. Debería usar Application Insights para detectar y comprender mejor los errores que ocurran en las ejecuciones de funciones. Para más información, consulte Supervisión de Azure Functions.

Uso del control de errores estructurado

La captura y el registro de los errores son fundamentales para supervisar el estado de la aplicación. El nivel superior de cualquier código de función debe incluir un bloque try/catch. En el bloque catch, puede capturar y registrar errores. Para obtener información sobre los errores que pueden generar los enlaces, consulte Códigos de error de enlace.

Planificación la estrategia de reintento

Varias extensiones de enlaces de Functions proporcionan compatibilidad integrada con reintentos. Además, el entorno de ejecución permite definir directivas de reintento para las funciones desencadenadas por Temporizador, Kafka y Event Hubs. Para más información, consulte Reintentos. En el caso de los desencadenadores que no proporcionen comportamientos de reintento, es posible que quiera implementar su propio esquema de reintento.

Diseño para idempotencia

La aparición de errores al procesar datos podría suponer un problema para las funciones, especialmente al procesar mensajes. Es importante tener en cuenta lo que suceda cuando se produzca el error y cómo evitar el procesamiento duplicado. Para obtener más información, vea Diseño de funciones de Azure para entradas idénticas.

Reintentos

Hay dos tipos de reintentos disponibles para sus funciones:

  • Comportamientos de reintento integrados de extensiones de desencadenador individuales
  • Directivas de reintento proporcionadas por el runtime de Functions

En la tabla siguiente se indica qué desencadenadores admiten reintentos y dónde se configura el comportamiento de reintento. También vincula a más información sobre los errores que proceden de los servicios subyacentes.

Desencadenadores o enlaces Origen de reintento Configuración
Azure Cosmos DB Directivas de reintentos Nivel de función
Azure Blob Storage Extensión de enlace host.json
Azure Event Grid Extensión de enlace Suscripción a eventos
Azure Event Hubs Directivas de reintentos Nivel de función
Azure Queue Storage Extensión de enlace host.json
RabbitMQ Extensión de enlace Cola de mensajes fallidos
Azure Service Bus Extensión de enlace Cola de mensajes fallidos
Temporizador Directivas de reintentos Nivel de función
Kafka Directivas de reintentos Nivel de función

Directivas de reintentos

A partir de la versión 3.x del entorno de ejecución de Azure Functions, es posible definir directivas de reintento para los desencadenadores de Temporizador. Kafka, Event Hubs y Azure Cosmos DB que aplican el tiempo de ejecución de Functions.

La directiva de reintentos indica al tiempo de ejecución que vuelva a ejecutar una ejecución errónea hasta que se complete correctamente o se alcance el número máximo de reintentos.

Una directiva de reintentos se evalúa cuando una función desencadenada por Temporizador, Kafka, Event Hubs o Azure Cosmos DB genera una excepción no detectada. Como procedimiento recomendado, debería detectar todas las excepciones del código y volver a generar los errores que quiere que vuelva dar lugar a un reintento.

Importante

Los puntos de control de Event Hubs no se escribirán hasta que la directiva de reintentos de la ejecución haya finalizado. Debido a este comportamiento, el progreso de la partición específica se pausa hasta que haya finalizado el lote actual.

La extensión de Event Hubs v5 admite funcionalidades de reintento adicionales para las interacciones entre el host de Functions y el centro de eventos. Consulte clientRetryOptions en la sección de Event Hubs del archivo host.json para más información.

Estrategia de reintento

Es posible configurar dos estrategias de reintento compatibles con la directiva:

Puede transcurrir un período de tiempo especificado entre cada reintento.

Número máximo de reintentos

Puede configurar el número máximo de veces que se reintenta una ejecución de función antes de que se produzca un error eventual. El número de reintentos actual se almacena en la memoria de la instancia.

Es posible que una instancia de un error entre reintentos. Cuando se produce un error en una instancia durante una directiva de reintentos, se pierde el número de reintentos. Cuando hay errores de instancia, el desencadenador de Event Hubs puede reanudar el procesamiento y reintentar el lote en una nueva instancia, con el número de reintentos restablecido en cero. El desencadenador de temporizador no se reanuda en una nueva instancia.

Este comportamiento significa que el número máximo de reintentos es un mejor esfuerzo. En algunos casos excepcionales, se podría reintentar una ejecución más que el número máximo solicitado de veces. En el caso de los desencadenadores de Temporizador, los reintentos pueden ser menores que el número máximo solicitado.

Ejemplos de reintentos

Los reintentos de nivel de función se admiten con los siguientes paquetes NuGet:

[Function(nameof(TimerFunction))]
[FixedDelayRetry(5, "00:00:10")]
public static void Run([TimerTrigger("0 */5 * * * *")] TimerInfo timerInfo,
    FunctionContext context)
{
    var logger = context.GetLogger(nameof(TimerFunction));
    logger.LogInformation($"Function Ran. Next timer schedule = {timerInfo.ScheduleStatus.Next}");
}
Propiedad Descripción
MaxRetryCount Necesario. Número máximo de reintentos permitidos por ejecución de función. -1 significa que se reintentará indefinidamente.
DelayInterval Retraso que se usa entre reintentos. Especifíquelo como una cadena con el formato HH:mm:ss.

Esta es la directiva de reintentos del archivo function.json:

{
    "disabled": false,
    "bindings": [
        {
            ....
        }
    ],
    "retry": {
        "strategy": "fixedDelay",
        "maxRetryCount": 4,
        "delayInterval": "00:00:10"
    }
}
Propiedad de function.json Descripción
strategy Necesario. Estrategia de reintentos que se usará. Los valores válidos son fixedDelay y exponentialBackoff.
maxRetryCount Necesario. Número máximo de reintentos permitidos por ejecución de función. -1 significa que se reintentará indefinidamente.
delayInterval Retraso que se usa entre reintentos al utilizar la estrategia fixedDelay. Especifíquelo como una cadena con el formato HH:mm:ss.
minimumInterval Retraso mínimo entre reintentos al usar la estrategia exponentialBackoff. Especifíquelo como una cadena con el formato HH:mm:ss.
maximumInterval Retraso entre reintentos máximo al usar la estrategia exponentialBackoff. Especifíquelo como una cadena con el formato HH:mm:ss.

Aquí se muestra un ejemplo de Python que usa el contexto de reintento en una función:

import azure.functions
import logging


def main(mytimer: azure.functions.TimerRequest, context: azure.functions.Context) -> None:
    logging.info(f'Current retry count: {context.retry_context.retry_count}')

    if context.retry_context.retry_count == context.retry_context.max_retry_count:
        logging.warn(
            f"Max retries of {context.retry_context.max_retry_count} for "
            f"function {context.function_name} has been reached")

@FunctionName("TimerTriggerJava1")
@FixedDelayRetry(maxRetryCount = 4, delayInterval = "00:00:10")
public void run(
    @TimerTrigger(name = "timerInfo", schedule = "0 */5 * * * *") String timerInfo,
    final ExecutionContext context
) {
    context.getLogger().info("Java Timer trigger function executed at: " + LocalDateTime.now());
}

Códigos de error de enlace

Cuando se realicen integraciones con los servicios de Azure, podrían originarse errores desde las API de los servicios subyacentes. La información relacionada con errores específicos de enlace está disponible en las secciones "Excepciones y códigos de retorno" de los siguientes artículos:

Pasos siguientes