Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Aprenda a crear soluciones sólidas y confiables sin servidor mediante Azure Functions con desencadenadores de Azure Event Hubs. En este artículo se tratan los procedimientos recomendados para los puntos de control, el control de errores y la implementación de patrones de disyuntor para garantizar que no se pierda ningún evento y las aplicaciones controladas por eventos permanezcan estables y resistentes.
Desafíos de los flujos de eventos en sistemas distribuidos
Considere un sistema que envía eventos a una velocidad constante de 100 eventos por segundo. A esta velocidad, en cuestión de minutos varias instancias paralelas pueden consumir los 100 eventos entrantes cada segundo.
Sin embargo, tenga en cuenta estos desafíos para consumir una secuencia de eventos:
- Un publicador de eventos envía un evento corrupto.
- El código de función encuentra una excepción no controlada.
- Un sistema descendente se desconecta y bloquea el procesamiento de eventos.
A diferencia de un desencadenador de Azure Queue Storage, que bloquea los mensajes durante el procesamiento, Azure Event Hubs lee, por partición, desde un único punto de la secuencia. Este comportamiento de lectura, que es más parecido a un reproductor de vídeo, proporciona las ventajas deseadas de alto rendimiento, varios grupos de consumidores y capacidad de reproducción. Los eventos se leen, hacia delante o hacia atrás, desde un punto de control, pero debe mover el puntero para procesar nuevos eventos. Para obtener más información, consulte Punto de control en la documentación de Event Hubs.
Cuando se producen errores en una secuencia y decide no avanzar el puntero, se bloquea el procesamiento adicional de eventos. En otras palabras, si detuvieras el puntero para enfrentarte a un problema al procesar un único evento, los eventos sin procesar comienzan a acumularse.
Functions evita interbloqueos al avanzar siempre el puntero de la secuencia, independientemente del éxito o error. Dado que el puntero continúa avanzando, las funciones deben tratar los errores adecuadamente.
Cómo el desencadenador de Event Hubs consume eventos
Azure Functions consume eventos de un centro de eventos mediante el ciclo de los pasos siguientes:
- Se crea un puntero y se conserva en Azure Storage para cada partición del centro de eventos.
- Los nuevos eventos se reciben en un lote (de forma predeterminada) y el host intenta desencadenar la función que proporciona un lote de eventos para su procesamiento.
- Cuando la función completa la ejecución, con o sin excepciones, el puntero está avanzado y se guarda un punto de control en la cuenta de almacenamiento de host predeterminada.
- Si las condiciones impiden que la ejecución de la función se complete, el host no puede avanzar el puntero. Cuando el puntero no puede avanzar, las ejecuciones posteriores vuelven a procesar los mismos eventos.
Este comportamiento revela algunos puntos importantes:
Las excepciones no controladas pueden provocar la pérdida de eventos:
Las ejecuciones de función que generan una excepción siguen progresando el puntero. Establecer una directiva de reintento u otra lógica de reintento retrasa el avance del puntero hasta que todo el proceso de reintento se complete.
Functions garantiza la entrega al menos una vez :
Es posible que el código y los sistemas dependientes necesiten tener en cuenta el hecho de que el mismo evento se pueda procesar dos veces. Para más información, consulte Diseño de Azure Functions para una entrada idéntica.
Control de excepciones
Aunque todo el código de función debe incluir un bloque try/catch en el nivel más alto de código, tener un catch bloque es aún más importante para las funciones que consumen eventos de Event Hubs. De ese modo, cuando se produce una excepción, el bloque catch controla el error antes de que el puntero avance.
Mecanismos y directivas de reintento
Dado que muchas excepciones en la nube son transitorias, el primer paso en el control de errores siempre es reintentar la operación. Puede aplicar directivas de reintento integradas o definir su propia lógica de reintento.
Directivas de reintentos
Functions proporciona directivas de reintento integradas para Event Hubs. Al usar directivas de reintento, simplemente genera una nueva excepción y el host intenta procesar el evento de nuevo en función de la directiva definida. Este comportamiento de reintento requiere la versión 5.x o posterior de la extensión de Event Hubs. Para más información, consulte Directivas de reintentos.
Lógica de reintento personalizada
También puede definir su propia lógica de reintento en la propia función. Por ejemplo, podría implementar una directiva que siga un flujo de trabajo ilustrado por las reglas siguientes:
- Intente procesar un evento tres veces (posiblemente con un retraso entre intentos).
- Si el resultado final de todos los reintentos es un error, agregue un evento a una cola para que el procesamiento pueda continuar en la secuencia.
- Los eventos dañados o no procesados se controlan más adelante.
Nota:
Polly es un ejemplo de una biblioteca de resistencia y control de errores transitorios para aplicaciones de C#.
Errores de no excepción
Algunos problemas pueden producirse sin que se produzca una excepción. Por ejemplo, considere un caso en el que una solicitud agota el tiempo de espera o la instancia que ejecuta la función se bloquea. Cuando una función no se logra completar sin una excepción, el puntero de desplazamiento nunca se avanza. Si el puntero no avanza, cualquier instancia que se ejecute después de una ejecución con error continúa leyendo los mismos eventos. Esta situación proporciona una garantía al menos una vez.
La garantía de que cada evento se procesa al menos una vez implica que algunos eventos se pueden procesar más de una vez. Las aplicaciones de función deben tener en cuenta esta posibilidad y deben crearse en torno a los principios de idempotencia.
Control de estados de error
Es posible que la aplicación pueda controlar de forma aceptable algunos errores en el procesamiento de eventos. Sin embargo, también debe estar preparado para manejar el estado de error persistente, que puede ocurrir como resultado de fallos en el procesamiento posterior. En este estado de error, como un almacén de datos de bajada que está sin conexión, la función debe dejar de desencadenarse en eventos hasta que el sistema alcance un estado correcto.
Patrón de disyuntor
Al implementar el patrón circuit breaker, la aplicación puede pausar eficazmente el procesamiento de eventos y reanudarlo más tarde una vez que se hayan resuelto los problemas.
Hay dos componentes necesarios para implementar un interruptor de circuito en un proceso de flujo de eventos:
- Estado compartido en todas las instancias para realizar un seguimiento y supervisar el estado del circuito.
- Proceso principal que puede administrar el estado del circuito, como
openoclosed.
Los detalles de implementación pueden variar, pero para compartir el estado entre instancias, se necesita un mecanismo de almacenamiento. Puede almacenar el estado en Azure Storage, una caché de Redis o cualquier otro servicio persistente al que puedan acceder las instancias de la aplicación de funciones.
Durable Functions y Azure Logic Apps proporcionan infraestructura para administrar flujos de trabajo y estados de circuito. En este artículo se describe el uso de Logic Apps para pausar y reiniciar las ejecuciones de funciones, lo que proporciona el control necesario para implementar el patrón de interruptor de circuito.
Definición de un umbral de error entre instancias
Se requiere un estado externo compartido persistente para supervisar el estado del circuito cuando varias instancias procesan eventos simultáneamente. A continuación, puede supervisar este estado persistente en función de las reglas que indican un estado de error, como:
Cuando hay más de 100 errores de evento en un período de 30 segundos en todas las instancias, interrumpa el circuito para detener el desencadenamiento en nuevos eventos.
Los detalles de implementación de esta lógica de supervisión varían en función de las necesidades específicas de la aplicación, pero en general debe crear un sistema que:
- Registra errores en el almacenamiento persistente.
- Inspeccione el recuento gradual cuando se registren nuevos errores para determinar si se cumple el umbral de error del evento.
- Cuando se alcanza este umbral, emita un evento que indique al sistema que interrumpa el circuito.
Administración del estado del circuito con Azure Logic Apps
Azure Logic Apps no solo incluye conectores integrados para diferentes servicios y características de orquestación con estado, sino que también es una opción natural para administrar el estado del circuito. Después de detectar cuándo un circuito debe interrumpirse, puede compilar una aplicación lógica para implementar este flujo de trabajo:
- Desencadene un flujo de trabajo de Event Grid que detenga el procesamiento de la función.
- Envíe un correo electrónico de notificación que incluya una opción para reiniciar el flujo de trabajo.
Para obtener información sobre cómo deshabilitar y volver a habilitar funciones específicas mediante la configuración de la aplicación, consulte Deshabilitación de funciones en Azure Functions.
El destinatario del correo electrónico puede investigar el estado del circuito y, cuando proceda, reiniciar el circuito a través de un vínculo en el correo electrónico de notificación. A medida que el flujo de trabajo reinicia la función, los eventos se procesan desde el último punto de control del centro de eventos.
Cuando se usa este enfoque, no se pierde ningún evento, los eventos se procesan en orden y se puede interrumpir el circuito siempre que sea necesario.
Estrategias de migración para desencadenadores de Event Grid
Al migrar una aplicación de funciones existente entre regiones o entre algunos planes, debe volver a crear la aplicación durante el proceso de migración. En este caso, durante el proceso de migración, es posible que tenga dos aplicaciones que puedan consumir desde la misma secuencia de eventos y escribir en el mismo destino de salida.
Debe considerar el uso de grupos de consumidores para evitar la pérdida o duplicación de datos de eventos durante el proceso de migración:
Cree un nuevo grupo de consumidores para la nueva aplicación de destino.
Configure el desencadenador en la nueva aplicación para usar este nuevo grupo de consumidores.
Esto permite que ambas aplicaciones procesen eventos de forma independiente durante la validación.
Valide que la nueva aplicación está procesando correctamente los eventos.
Detenga la aplicación original o quite su suscripción o grupo de consumidores.