Editar

Compartir a través de


Guía de rendimiento y escala para Event Hubs y Azure Functions

Azure Event Hubs
Azure Functions

En este artículo se proporcionan instrucciones para optimizar la escalabilidad y el rendimiento al usar Azure Event Hubs y Azure Functions juntos en las aplicaciones.

Agrupación de funciones

Normalmente, una función encapsula una unidad de trabajo en un flujo de procesamiento de eventos. Por ejemplo, una función puede transformar un evento en una nueva estructura de datos o enriquecer los datos para las aplicaciones de bajada.

En Functions, una aplicación de funciones ofrece el contexto de ejecución de las funciones. Los comportamientos de las aplicaciones de funciones se aplican a todas las funciones que hospeda la aplicación de funciones. Las funciones de una aplicación de funciones se implementan y escalan juntas. Todas las funciones de una aplicación de funciones deben compartir el mismo lenguaje.

La forma en que las funciones se agrupan en aplicaciones de funciones puede afectar al rendimiento y a las funcionalidades de escalado de las aplicaciones de funciones. Puede agrupar según los derechos de acceso, la implementación y los patrones de uso que invocan el código.

Para obtener instrucciones sobre los procedimientos recomendados de Functions para agrupar y otros aspectos, consulte Procedimientos recomendados para Azure Functions fiables y Mejorar el rendimiento y la fiabilidad de Azure Functions.

La lista siguiente es una guía para agrupar funciones. La guía tiene en cuenta los aspectos de almacenamiento y de los grupos de consumidores:

  • Hospedar una sola función en una aplicación de funciones: si Event Hubs desencadena una función, puede reducir la contención entre esa función y las demás funciones, aislar la función en su propia aplicación de funciones. El aislamiento es especialmente importante si las otras funciones consumen mucha CPU o memoria. Esta técnica ayuda porque cada función tiene su propia superficie de memoria y patrones de uso que pueden afectar directamente al escalado de la aplicación de funciones que la hospeda.

  • Asigne a cada aplicación de funciones su propia cuenta de almacenamiento: evite compartir cuentas de almacenamiento entre aplicaciones de funciones. Además, si una aplicación de funciones usa una cuenta de almacenamiento, no use esa cuenta para otras operaciones o necesidades de almacenamiento. Puede ser especialmente importante evitar el uso compartido de cuentas de almacenamiento para las funciones que desencadena Event Hubs, ya que estas funciones pueden tener un gran volumen de transacciones de almacenamiento debido a la creación de puntos de comprobación.

  • Cree un grupo de consumidores dedicado para cada aplicación de funciones: un grupo de consumidores es una vista de un centro de eventos. Los distintos grupos de consumidores tienen vistas diferentes, lo que significa que los estados, las posiciones y los desplazamientos pueden diferir. Los grupos de consumidores permiten que varias aplicaciones consumidoras tengan su propia vista del flujo de eventos y para que lean el flujo de forma independiente a su propio ritmo y con sus propios desplazamientos. Para más información sobre los grupos de consumidores, consulte Características y terminología de Azure Event Hubs.

    Un grupo de consumidores tiene una o varias aplicaciones de consumidor asociadas, y una aplicación de consumidor puede usar uno o varios grupos de consumidores. En una solución de procesamiento de flujos, cada aplicación de consumidor se corresponde con un grupo de consumidores. Una aplicación de funciones es un ejemplo excelente de una aplicación de consumidor. En el diagrama siguiente se proporciona un ejemplo de dos aplicaciones de funciones que leen desde un centro de eventos, donde cada aplicación tiene su propio grupo de consumidores dedicado:

    Grupos de consumidores dedicados para cada aplicación de funciones

    No comparta grupos de consumidores entre aplicaciones de funciones y otras aplicaciones de consumidor. Cada aplicación de funciones debe ser una aplicación distinta con su propio grupo de consumidores asignado para garantizar la integridad de desplazamiento en cada consumidor y simplificar las dependencias en una arquitectura de streaming de eventos. Esta configuración, junto con la acción de proporcionar a cada función desencadenada por el centro de eventos su propia aplicación de funciones y cuenta de almacenamiento, ayuda a establecer las bases para un rendimiento y un escalado óptimos.

Planes de hospedaje de funciones

Existen varias opciones de hospedaje para aplicaciones de funciones y es importante revisar sus capacidades. Para obtener información sobre esas opciones de hospedaje, consulte las opciones de hospedaje de Azure Functions. Tome nota de cómo se escalan las opciones.

El plan de Consumo es el predeterminado. Las aplicaciones de funciones del plan de Consumo se escalan de forma independiente y son más eficaces cuando evitan tareas de larga duración.

Los planes Premium y Dedicado se usan a menudo para hospedar varias funciones y aplicaciones de funciones que consumen más CPU y memoria. Con el plan Dedicado, ejecutará las funciones en un plan de Azure App Service con tarifas normales del plan de App Service. Es importante tener en cuenta que todas las aplicaciones de funciones de estos planes comparten los recursos asignados al plan. Si las funciones tienen perfiles de carga diferentes o requisitos únicos, es mejor hospedarlas en planes diferentes, especialmente en las aplicaciones procesamiento de flujos.

Container Apps de Azure proporciona soporte integrado para desarrollar, implementar y administrar aplicaciones de funciones en contenedores en Azure Functions. Esto permite ejecutar las funciones controladas por eventos en un entorno totalmente administrado, basado en Kubernetes, con soporte integrado para la supervisión de código abierto, mTLS, Dapr y KEDA.

Escalado de Event Hubs

Cuando se implementa un espacio de nombres de Event Hubs, hay varias configuraciones importantes que deben evaluarse para garantizar un rendimiento y un escalado máximos. Esta sección se centra en el nivel Estándar de Event Hubs y las características únicas de ese nivel que afectan al escalado cuando también usa Functions. Para obtener más información sobre los niveles de Event Hubs, vea Nivel Básico frente a Estándar frente a Premium frente a Dedicado.

Un espacio de nombres de Event Hubs corresponde a un clúster de Kafka. Para obtener información sobre cómo se relacionan Event Hubs y Kafka entre sí, consulte ¿Qué es Azure Event Hubs para Apache Kafka?

Descripción de las unidades de procesamiento (TU)

En el nivel Estándar de Event Hubs, el rendimiento se clasifica como la cantidad de datos que entra y se lee del espacio de nombres dentro por unidad de tiempo. Las unidades de procesamiento son unidades de capacidad de rendimiento adquiridas previamente.

Se facturan por hora.

Todos los centros de eventos de un espacio de nombres comparten las unidades de procesamiento. Para calcular correctamente las necesidades de capacidad, debe tener en cuenta todas las aplicaciones y servicios, tanto los publicadores como los consumidores. Las funciones afecta al número de bytes y eventos que se publican y se leen desde un centro de eventos.

El énfasis para determinar el número de TU se basa en el punto de entrada. Pero el agregado para las aplicaciones de consumidor, incluida la velocidad a la que se procesan esos eventos, también debe incluirse en el cálculo.

Para más información sobre las unidades de rendimiento de Event Hubs, consulte Unidades de rendimiento.

Escalado vertical con inflado automático

El inflado automático se puede habilitar en un espacio de nombres de Event Hubs para dar cabida a situaciones en las que la carga supera el número configurado de TU. El uso del inflado automático evita la limitación de la aplicación y ayuda a garantizar que el procesamiento, incluida la ingesta de eventos, continúe sin interrupciones. Dado que la configuración de TU afecta a los costes, el uso del inflado automático ayuda a abordar las preocupaciones sobre el sobreaprovisionamiento.

El inflado automático es una característica de Event Hubs que a menudo se confunde con la escalabilidad automática, especialmente en el contexto de las soluciones sin servidor. Sin embargo, el inflado automático, a diferencia de la escalabilidad automática, no se reduce verticalmente cuando ya no se necesita capacidad agregada.

Si la aplicación necesita una capacidad que supere el número máximo permitido de TU, considere la posibilidad de usar el nivel Premium o el nivel Dedicado de Event Hubs.

Particiones y funciones simultáneas

Después de crear un centro de eventos, es necesario especificar el número de particiones. El recuento de particiones es fijo y no se puede cambiar excepto en los niveles Premium y Dedicado. Cuando Event Hubs desencadena aplicaciones de funciones, es posible que el número de instancias simultáneas sea igual al número de particiones.

En los planes de hospedaje Consumo y Premium, las instancias de la aplicación de función se escalan de forma dinámica para cumplir con la cantidad de particiones, si es necesario. El plan de hospedaje Dedicado ejecuta funciones en un plan de App Service y requiere que configure manualmente las instancias o configure un esquema de escalabilidad automática. Para obtener más información, consulte Planes de hospedaje Dedicado para Azure Functions.

En última instancia, una relación uno a uno entre el número de particiones y las instancias de función, o consumidores, es el objetivo ideal para lograr el máximo rendimiento en una solución de procesamiento de flujo. Para lograr un paralelismo óptimo, tenga varios consumidores en un grupo de consumidores. Para Functions, este objetivo se traduce en muchas instancias de una función en el plan. El resultado se conoce como paralelismo de nivel de partición o el grado máximo de paralelismo, como se muestra en el siguiente diagrama:

Grado máximo de paralelismo

Podría parecer que tiene sentido configurar tantas particiones como sea posible para lograr el máximo rendimiento y tener en cuenta la posibilidad de un mayor volumen de eventos. Sin embargo, hay varios factores importantes que se deben tener en cuenta al configurar muchas particiones:

  • Más particiones pueden generar un mayor rendimiento: debido a que el grado de paralelismo es el número de consumidores (instancias de función), cuantas más particiones haya, mayor será el rendimiento simultáneo. Este hecho es importante al compartir un número designado de TU para un centro de eventos con otras aplicaciones de consumidor.
  • Más funciones pueden requerir más memoria: a medida que aumenta el número de instancias de función, también aumenta el uso de memoria de los recursos en el plan. En algún momento, demasiadas particiones pueden degradar el rendimiento de los consumidores.
  • Existe un riesgo de retroceso por parte de los servicios de bajada: a medida que se genera más rendimiento, corre el riesgo de sobrecargar los servicios de bajada o recibir presión de retroceso de ellos. La distribución ramificada de los consumidores debe tenerse en cuenta al considerar las consecuencias en los recursos circundantes. Algunas posibles consecuencias son la limitación de otros servicios, la saturación de la red y otras formas de contención de recursos.
  • Las particiones se pueden rellenar de forma dispersa: la combinación de muchas particiones y un bajo volumen de eventos puede dar lugar a datos que se distribuyen de manera dispersa entre las particiones. En cambio, una menor cantidad de particiones puede proporcionar un mejor rendimiento y uso de recursos.

Disponibilidad y coherencia

Cuando no se especifica una clave de partición o un identificador, Event Hubs enruta un evento entrante a la siguiente partición disponible. Esta práctica proporciona alta disponibilidad y ayuda a aumentar el rendimiento de los consumidores.

Cuando es necesario ordenar un conjunto de eventos, el productor de eventos puede especificar que se usará una partición determinada para todos los eventos del conjunto. La aplicación de consumidor que lee de la partición recibe los eventos en el orden adecuado. Esta compensación proporciona coherencia, pero pone en peligro la disponibilidad. No use este enfoque a menos que se deba conservar el orden de los eventos.

Para Functions, la ordenación se logra cuando los eventos se publican en una partición determinada y una función desencadenada por Event Hubs obtiene una concesión a la misma partición. Actualmente, no se admite la capacidad de configurar una partición con el enlace de salida de Event Hubs. En su lugar, el mejor enfoque es usar uno de los SDK de Event Hubs para publicar en una partición específica.

Para obtener más información sobre la compatibilidad de Event Hubs con la disponibilidad y la coherencia, consulte Disponibilidad y coherencia en Event Hubs.

Desencadenador de Event Hubs

Esta sección se centra en la configuración y las consideraciones para optimizar las funciones que desencadena Event Hubs. Entre los factores se incluyen el procesamiento por lotes, el muestreo y las características relacionadas que influyen en el comportamiento de un enlace de desencadenador del centro de eventos.

Procesamiento por lotes para funciones desencadenadas

Puede configurar funciones que desencadena un centro de eventos para procesar un lote de eventos o un evento a la vez. El procesamiento de un lote de eventos puede ser más eficiente cuando reduce parte de la sobrecarga de las invocaciones de funciones. A menos que necesite procesar solo un evento, la función se debe configurar para procesar varios eventos cuando se invoca.

La habilitación del procesamiento por lotes para el enlace de desencadenador de Event Hubs varía según el lenguaje:

  • En JavaScript, Python y otros lenguajes, el procesamiento por lotes se habilita cuando la propiedad de cardinalidad se establece en many en el archivo function.json de la función.
  • En C#, la cardinalidad se configura automáticamente cuando se designa una matriz para el tipo en el atributo EventHubTrigger.

Para obtener más información sobre cómo se habilita el procesamiento por lotes, consulte Desencadenador de Azure Event Hubs para Azure Functions.

Configuración del desencadenador

Varias opciones de configuración del archivo host.json desempeñan un papel clave en las características de rendimiento del enlace de desencadenador de Event Hubs para Functions:

  • maxEventBatchSize: este valor representa el número máximo de eventos que puede recibir la función cuando se invoca. Si el número de eventos recibidos es menor que esta cantidad, la función se sigue invocando con tantos eventos como estén disponibles. No se puede establecer el tamaño mínimo del lote.
  • prefetchCount: el recuento de capturas previas es uno de los valores más importantes a la hora de optimizar el rendimiento. El canal AMQP subyacente hace referencia a este valor para determinar cuántos mensajes se capturarán y almacenarán en caché para el cliente. El recuento de captura previa debe ser mayor o igual que el valor maxEventBatchSize, y normalmente se establece en un múltiplo de esa cantidad. Establecer este valor a un número inferior al valor maxEventBatchSize puede perjudicar el rendimiento.
  • batchCheckpointFrequency: a medida que la función procesa lotes, este valor determina la velocidad a la que se crean los puntos de control. El valor predeterminado es 1, lo que significa que hay un punto de control cada vez que una función procesa con éxito un único lote. Se crea un punto de control en el nivel de partición para cada lector del grupo de consumidores. Para obtener información sobre cómo esta configuración influye en las reproducciones y reintentos de los eventos, consulte Función de Azure desencadenada por el centro de eventos: reproducciones y reintentos (entrada de blog).

Realice varias pruebas de rendimiento para determinar los valores que se van a establecer para el enlace del desencadenador. Se recomienda cambiar la configuración de forma incremental y medir de forma coherente para ajustar estas opciones. Los valores predeterminados son un punto inicial para la mayoría de las soluciones de procesamiento de eventos.

Puntos de control

Los puntos de control marcan o confirman las posiciones del lector en una secuencia de eventos de partición. Es responsabilidad del host de Functions establecer puntos de control a medida que se procesan los eventos y se cumple el valor de frecuencia del punto de comprobación por lotes. Para más información sobre la creación de puntos de control, consulte Características y terminología de Azure Event Hubs.

Los siguientes conceptos le pueden ayudar a comprender la relación entre la creación de puntos de control y cómo la función procesa los eventos:

  • Las excepciones siguen contando para la finalización correcta: si el proceso de función no se bloquea durante el procesamiento de eventos, la finalización de la función se considera correcta, incluso aunque se produzcan excepciones. Cuando se completa la función, el host de Functions evalúa batchCheckpointFrequency. Si es el momento de un punto de control, crea uno, independientemente de si había excepciones. El hecho de que las excepciones no afecten a la creación de puntos de control no deben afectar al uso adecuado de la comprobación y el control de excepciones.
  • La frecuencia del lote es importante: en las soluciones de streaming de gran volumen de eventos, puede ser beneficioso cambiar batchCheckpointFrequency a un valor mayor que 1. Aumentar este valor puede reducir la tasa de creación de puntos de control y, como consecuencia, el número de operaciones de E/S de almacenamiento.
  • Se pueden producir reproducciones: cada vez que se invoca una función con el enlace de desencadenador de Event Hubs, usa el punto de control más reciente para determinar dónde reanudar el procesamiento. El desplazamiento de cada consumidor se guarda en el nivel de partición para cada grupo de consumidores. Las reproducciones se producen cuando no se produce un punto de control durante la última invocación de la función y la función se invoca de nuevo. Para obtener más información sobre los duplicados y las técnicas de desduplicación, consulte Idempotencia.

Comprender la creación de puntos de control es fundamental cuando se consideran procedimientos recomendados para el control de errores y los reintentos, un tema que se describe más adelante en este artículo.

Muestreo de telemetría

Functions proporciona compatibilidad integrada con Application Insights, una extensión de Azure Monitor que proporciona funcionalidades de supervisión del rendimiento de las aplicaciones. Con esta característica, puede registrar información sobre las actividades de función, el rendimiento, las excepciones en tiempo de ejecución, etc. Para más información, consulte Introducción sobre Application Insights.

Esta capacidad eficaz ofrece algunas opciones de configuración clave que afectan al rendimiento. Algunas de las configuraciones y consideraciones importantes para la supervisión y el rendimiento son las siguientes:

  • Habilitación del muestreo de telemetría: para escenarios de alto rendimiento, debe evaluar la cantidad de telemetría e información que necesita. Considere la posibilidad de usar la característica de muestreo de telemetría en Application Insights para evitar degradar el rendimiento de la función con métricas de telemetría innecesarios.
  • Configuración de valores de agregación: examine y configure la frecuencia con la que se agregan los datos y se envían a Application Insights. Esta opción de configuración está en el archivo host.json junto con muchas otras opciones relacionadas con el muestreo y el registro. Para más información, consulte Configuración del agregador.
  • Deshabilitación de AzureWebJobDashboard: en el caso de las aplicaciones que tienen como destino la versión 1.x del entorno de ejecución de Azure Functions, este valor almacena la cadena de conexión en una cuenta de almacenamiento que usa el SDK de Azure para conservar los registros del panel WebJobs. Si se usa Application Insights en lugar del panel WebJobs, este valor se debe quitar. Para obtener más información, consulte AzureWebJobsDashboard.

Cuando Application Insights se habilita sin muestreo, se envían todos los datos de telemetría. El envío de datos sobre todos los eventos puede tener un efecto perjudicial en el rendimiento de la función, especialmente en escenarios de streaming de eventos de alto rendimiento.

Aprovechar el muestreo y evaluar continuamente la cantidad adecuada de telemetría necesaria para la supervisión es crucial para un rendimiento óptimo. La telemetría se debe usar para la evaluación general del estado de la plataforma y para solucionar problemas ocasionales, no para capturar métricas empresariales principales. Para más información, consulte Configuración del muestreo.

Enlace de salida

Use el enlace de salida de Event Hubs para Azure Functions para simplificar la publicación en un flujo de eventos desde una función. Entre las ventajas de usar este enlace se incluyen las siguientes:

  • Administración de recursos: el enlace controla los ciclos de vida del cliente y de la conexión y reduce el potencial de problemas que pueden surgir con el agotamiento de puertos y la administración del grupo de conexiones.
  • Menos código: el enlace abstrae el SDK subyacente y reduce la cantidad de código que necesita para publicar eventos. Le ayuda a escribir código que sea más fácil de escribir y mantener.
  • Procesamiento por lotes: para varios lenguajes, se admite el procesamiento por lotes para publicar de forma eficaz en un flujo de eventos. El procesamiento por lotes puede mejorar el rendimiento y ayudar a simplificar el código que envía los eventos.

Se recomienda encarecidamente revisar la lista de lenguajes compatibles con Functions y las guías para desarrolladores de esos lenguajes. En la sección Enlaces de cada lenguaje se proporcionan ejemplos detallados y documentación.

Procesamiento por lotes al publicar eventos

Si la función solo publica un único evento, configurar el enlace para devolver un valor es un enfoque común que resulta útil si la ejecución de la función siempre termina con una instrucción que envía el evento. Esta técnica solo se debe utilizar para las funciones sincrónicas que devuelven un único evento.

Se recomienda el procesamiento por lotes para mejorar el rendimiento al enviar varios eventos a una secuencia. El procesamiento por lotes permite que el enlace publique eventos de la manera más eficaz posible.

La compatibilidad para usar el enlace de salida para enviar varios eventos a Event Hubs está disponible en C#, Java, Python y JavaScript.

Generar múltiples eventos con el modelo en proceso (C#)

Utilice los tipos ICollector y IAsyncCollector al enviar varios eventos desde una función en C#.

  • El método ICollector<T>.Add() se puede usar en funciones sincrónicas y asincrónicas. Ejecuta la operación de adición en cuanto se llama.
  • El método IAsyncCollector<T>.AddAsync() prepara los eventos que se publicarán en el flujo de eventos. Si escribe una función asincrónica, debe usar IAsyncCollector para administrar mejor los eventos publicados.

Para obtener ejemplos de uso de C# para publicar eventos únicos y varios, consulte Enlace de salida de Azure Event Hubs para Azure Functions.

Generar múltiples eventos con el modelo de trabajo aislado (C#)

Dependiendo de la versión de tiempo de ejecución de Functions, el modelo de trabajo aislado admitirá diferentes tipos para los parámetros que se pasan al enlace de salida. Para múltiples eventos, se utiliza una matriz para encapsular el conjunto. Se recomienda revisar los atributos de enlace de salida y los detalles de uso del modelo aislado, así como tomar nota de las diferencias entre las versiones de la extensión.

Limitación y presión retroactiva

Las consideraciones de limitación se aplican a los enlaces de salida, no solo para Event Hubs, sino también para servicios de Azure como Azure Cosmos DB. Es importante familiarizarse con los límites y las cuotas que se aplican a esos servicios, y planear en consecuencia.

Para manejar errores posteriores con el modelo en proceso, puede incluir AddAsync y FlushAsync en un controlador de excepciones para funciones .NET para detectar excepciones de IAsyncCollector. Otra opción es usar los SDK de Event Hubs directamente en lugar de usar enlaces de salida.

Si está aprovechando el modelo aislado para funciones, entonces debe utilizar el manejo estructurado de excepciones para detectar excepciones de manera responsable al devolver los valores de salida.

Código de función

En esta sección se describen las áreas clave que se deben tener en cuenta al escribir código para procesar eventos en una función que desencadena Event Hubs.

Programación asincrónica

Se recomienda escribir la función para usar código asincrónico y evitar el bloqueo de llamadas, especialmente cuando intervienen llamadas de E/S.

Estas son las instrucciones que debe seguir al escribir una función para procesar de forma asincrónica:

  • Todo asincrónico o todo sincrónico: si una función está configurada para ejecutarse de forma asincrónica, todas las llamadas de E/S también deben ser asincrónicas. En la mayoría de los casos, el código parcialmente asincrónico es peor que el código completamente sincrónico. Elija asincrónico o sincrónico, y mantenga esa opción durante todo el proyecto.
  • Evite las llamadas de bloqueo: las llamadas de bloqueo vuelven al autor de la llamada solo una vez completada la llamada, a diferencia de las llamadas asincrónicas, que se devuelven inmediatamente. Un ejemplo en C# sería llamar a Task.Result o Task.Wait en una operación asincrónica.

Más información sobre las llamadas de bloqueo

Usar llamadas de bloqueo para las operaciones asincrónicas puede provocar el colapso del grupo de subprocesos y el bloqueo del proceso de la función. El bloqueo sucede porque una llamada de bloqueo necesita que se cree otro subproceso para compensar la llamada original que ahora está en espera. Como resultado, se necesitan el doble de subprocesos para completar la operación.

Evitar este enfoque sincrónico sobre asincrónico es especialmente importante cuando Event Hubs está implicado, ya que un bloqueo en la función no actualiza el punto de control. La próxima vez que se invoque la función, podría acabar en este ciclo y parecer que se ha bloqueado, o que avanza lentamente, ya que las ejecuciones de funciones agotan el tiempo de espera.

La solución de este fenómeno suele comenzar con la revisión de la configuración del desencadenador y la ejecución de experimentos que pueden implicar el aumento del número de particiones. Las investigaciones también pueden llevar a cambiar varias de las opciones de procesamiento por lotes, como el tamaño máximo de lote o el recuento de captura previa. La impresión es que se trata de un problema de rendimiento o de un valor de configuración que solo debe ajustarse en consecuencia. Pero el problema principal está en el propio código y debe solucionarse allí.

Colaboradores

Microsoft mantiene este artículo. Originalmente lo escribió el siguiente colaborador.

Autor principal:

Para ver los perfiles no públicos de LinkedIn, inicie sesión en LinkedIn.

Pasos siguientes

Antes de continuar, considere la posibilidad de revisar estos artículos relacionados: