Optimización del rendimiento de una aplicación distribuida
En esta serie, se describen varios escenarios de aplicaciones en la nube, en los que se muestra cómo un equipo de desarrollo utilizó pruebas de carga y métricas para diagnosticar problemas de rendimiento. Estos artículos se basan en pruebas de carga reales que se realizaron al desarrollar las aplicaciones de ejemplo. El código de cada escenario está disponible en GitHub.
Escenarios:
- Transacción empresarial distribuida
- Llamada a varios servicios de back-end
- Procesamiento de flujo de eventos
El rendimiento se mide con frecuencia en términos de procesamiento, tiempo de respuesta y disponibilidad. Los objetivos de rendimiento se deben basar en las operaciones empresariales. Las tareas orientadas al cliente pueden tener unos requisitos más estrictos que las tareas operativas como, por ejemplo, la generación de informes.
Establezca un objetivo de nivel de servicio (SLO) que defina los objetivos de rendimiento de cada carga de trabajo. Normalmente, esto se consigue dividiendo un objetivo en un conjunto de indicadores clave de rendimiento (KPI), como:
- Latencia o tiempo de respuesta de solicitudes específicas
- El número de solicitudes realizadas por segundo
- Velocidad a la que el sistema genera excepciones.
Los objetivos de rendimiento deben incluir explícitamente una carga de destino. Además, no todos los usuarios reciben exactamente el mismo nivel de rendimiento, incluso aunque accedan al sistema simultáneamente y realicen el mismo trabajo. Por lo tanto, un objetivo de nivel de servicio (SLO) se debe elaborar en términos de percentiles.
Un SLO de ejemplo para podría ser: "Las solicitudes de cliente reciben una respuesta en menos de 500 ms @ P90, con cargas de hasta 25 000 solicitudes por segundo".
Puede ser especialmente difícil diagnosticar problemas de rendimiento en una aplicación distribuida. Algunos de los desafíos son:
Normalmente, una única transacción u operación empresarial afecta a varios componentes del sistema. Puede ser difícil obtener una vista integral global de una sola operación.
El consumo de recursos se distribuye entre varios nodos. Para obtener una vista coherente, debe agregar los registros y las métricas en un solo lugar.
La nube ofrece escalado elástico. El escalado automático es una técnica importante para administrar picos de carga, pero también puede enmascarar problemas subyacentes. Además, puede ser difícil saber qué componentes deben escalarse y cuándo.
Las cargas de trabajo a menudo no se escalan entre núcleos o subprocesos. Es importante comprender los requisitos de las cargas de trabajo y examinar los tamaños optimizados mejor. Algunos tamaños ofrecen núcleos restringidos y hyperthreading deshabilitado para mejorar las cargas de trabajo orientadas a un solo núcleo y por núcleo con licencia.
Los errores en cascada pueden provocar errores en niveles superiores al origen del problema. Como resultado, la primera señal del problema puede aparecer en un componente distinto al del origen del problema.
La optimización de rendimiento tiene algo de arte y de ciencia, pero con la adopción de un enfoque sistemático se asemeja más a un método científico. Estos son algunos procedimientos recomendados:
Habilite la telemetría para recopilar métricas. Instrumente el código. Siga los procedimientos recomendados de supervisión. Use un seguimiento correlacionado para que pueda ver todos los pasos de una transacción.
Supervise los percentiles 90/95/99, no solo la media. La media puede enmascarar valores atípicos. La frecuencia de muestreo de las métricas también es importante. Si la frecuencia de muestreo es demasiado baja, puede ocultar picos o valores atípicos que podrían indicar problemas.
Afronta los cuellos de botella de uno en uno. Formule una hipótesis y pruébela cambiando una variable cada vez. La eliminación de un cuello de botella a menudo permitirá descubrir otro cuello de botella en un nivel superior o inferior.
Los errores y los reintentos pueden tener un gran impacto en el rendimiento. Si ve que los servicios de back-end están limitando el sistema, escale horizontalmente o intente optimizar el uso (por ejemplo, optimizando las consultas de base de datos).
Busque antipatrones de rendimiento habituales.
Busque oportunidades para establecer paralelismos. Dos fuentes habituales de cuellos de botella son las colas de mensajes y las bases de datos. En ambos casos, el particionamiento puede ayudar. Para más información, consulte Creación de particiones de datos horizontales, verticales y funcionales. Busque las particiones más frecuentes que podrían indicar cargas de lectura o escritura desequilibradas.
Lectura de los escenarios de optimización del rendimiento