En este artículo, presento un estudio que compara entornos para Apache Kafka. El objetivo final es encontrar la configuración más eficaz y lograr la mejor relación precio-rendimiento.
Nuestra plataforma de datos proporciona servicios gestionados para la construcción de plataformas analíticas para grandes conjuntos de datos, compitiendo con otras soluciones del mercado. Para seguir siendo competitivos, realizamos periódicamente investigaciones internas para identificar y mejorar nuestras fortalezas, garantizando mejores acuerdos. Este artículo muestra uno de esos estudios. Actualmente, nuestra plataforma admite AWS y GCP como proveedores de nube. Ambos ofrecen múltiples generaciones de computación y dos arquitecturas de CPU (x86 con Intel y AMD, y ARM). Comparo estas configuraciones utilizando varias máquinas virtuales Java (JVM) para evaluar el rendimiento de las nuevas versiones en procesadores más nuevos.
Si quieres un TL;DR: ARM es genial. La arquitectura moderna y costosa no siempre significa "mejor". Puede ir directamente a los resultados o continuar para obtener más información sobre la metodología y la configuración.
Consideré probar el rendimiento con nuestro propio servicio, pero quería compararlo en diferentes entornos que aún no admitimos. Quería probar nuevas máquinas virtuales, regiones e incluso otros proveedores de nube. Entonces, comencé implementando un proyecto de juguete que utiliza Kafka base con diferentes imágenes de contenedor base. De esta manera, puedo ejecutar herramientas de evaluación comparativa en hardware específico y medir el rendimiento.
Mi objetivo es probar varias configuraciones para identificar los resultados más interesantes. Para eso, utilizo la idea de la matriz de prueba para filtrar los hallazgos iniciales. Analizaré estos hallazgos en profundidad utilizando herramientas como perf y eBPF para perfeccionar aún más el rendimiento.
Primero describamos los objetivos de las pruebas. Tengo mucha experiencia con OpenJDK JVM, pero hoy en día existen muchas alternativas de Microsoft, Amazon y otras empresas. Amazon Correto, por ejemplo, incluye funciones adicionales y parches optimizados para AWS. Dado que la mayoría de nuestros clientes utilizan AWS, quería incluir Amazon Correto en las pruebas para ver cómo funcionan estas JVM en esa plataforma.
Elegí estas versiones para la primera comparación:
Una vez definidas las versiones, preparé algunos scripts para crear imágenes de Kafka usando Amazon Correto y OpenJDK .
Para las pruebas de evaluación comparativa, cambié la configuración de Kafka para centrarme en métricas de rendimiento específicas. Quería probar diferentes combinaciones de [JVM] x [instance_type] x [architecture] x [cloud_provider] , por lo que era importante minimizar los efectos de la conectividad de la red y el rendimiento del disco. Hice esto ejecutando contenedores con tmpfs para almacenamiento de datos:
podman run -ti \ --network=host \ --mount type=tmpfs,destination=/tmp \ kfbench:3.6.1-21.0.2-amzn-arm64
Naturalmente, esta configuración no está pensada para producción, pero era necesario aislar los cuellos de botella de la CPU y la memoria. La mejor manera es eliminar las influencias de la red y el disco de las pruebas. De lo contrario, esos factores distorsionarían los resultados.
Utilicé la herramienta de referencia en la misma instancia para garantizar una latencia mínima y una mayor reproducibilidad. También probé pruebas sin configuraciones de red de host y con redes virtuales aisladas de cgroup, pero estas solo agregaron latencia innecesaria y aumentaron el uso de CPU para el reenvío de paquetes.
Si bien tmpfs asigna memoria dinámicamente y puede causar fragmentación y latencia, fue adecuado para nuestra prueba. Podría haber usado ramdisk en su lugar, que asigna memoria estáticamente y evita estos problemas, pero tmpfs fue más fácil de implementar y aun así proporcionó la información que buscábamos. Para nuestros propósitos, logró el equilibrio adecuado.
Además, apliqué algunas configuraciones adicionales de Kafka para expulsar datos de la memoria con más frecuencia:
############################# Benchmark Options ############################# # https://kafka.apache.org/documentation/#brokerconfigs_log.segment.bytes # Chaged from 1GB to 256MB to rotate files faster log.segment.bytes = 268435456 # https://kafka.apache.org/documentation/#brokerconfigs_log.retention.bytes # Changed from -1 (unlimited) to 1GB evict them because we run in tmpfs log.retention.bytes = 1073741824 # Changed from 5 minutes (300000ms) to delete outdated data faster log.retention.check.interval.ms=1000 # Evict all data after 15 seconds (default is -1 and log.retention.hours=168 which is ~7 days) log.retention.ms=15000 # https://kafka.apache.org/documentation/#brokerconfigs_log.segment.delete.delay.ms # Changed from 60 seconds delay to small value to prevent memory overflows log.segment.delete.delay.ms = 0
Aquí hay un resumen de los cambios:
Esta configuración no es adecuada para uso en producción, pero es importante para nuestras pruebas comparativas ya que reduce los efectos de factores irrelevantes.
En DoubleCloud, al momento de escribir este artículo, admitimos estas principales generaciones de recursos informáticos:
Para los procesadores Graviton, admitimos:
Además, probé instancias t2a en GCP como alternativa a Graviton en Ampere Altra. No los ofrecemos a nuestros clientes debido al soporte regional limitado de AWS, pero los incluí en los puntos de referencia para comparar el rendimiento. Esta podría ser una buena opción si se encuentra en una de las regiones "correctas".
Para la evaluación comparativa, desarrollé una herramienta liviana basada en la biblioteca franz-go y el ejemplo . Esta herramienta satura eficazmente a Kafka sin convertirse ella misma en un cuello de botella.
Si bien librdkafka es conocido por su confiabilidad y popularidad, lo evité debido a posibles problemas con cgo.
Kafka es conocido por su escalabilidad, lo que permite dividir los temas en múltiples particiones para distribuir eficientemente las cargas de trabajo de manera horizontal entre los brokers. Sin embargo, me concentré en evaluar el rendimiento de un solo núcleo para nuestro enfoque específico en la relación rendimiento-precio.
Por lo tanto, las pruebas utilizaron temas con particiones únicas para utilizar plenamente las capacidades centrales individuales.
Cada caso de prueba incluía dos tipos:
Utilicé mensajes de 8 KB, más grandes que el caso promedio de un cliente, para saturar completamente los hilos de partición de temas.
Presento una serie de gráficos que comparan diferentes casos de prueba utilizando una métrica de eficiencia sintética para evaluar diferentes arquitecturas. Esta métrica cuantifica el porcentaje de millones de filas que podemos ingerir en el agente Kafka , lo que proporciona una evaluación sencilla de la rentabilidad de la arquitectura.
Es importante reconocer que los resultados reales pueden variar debido a los descuentos adicionales de los proveedores de la nube. Siempre que fue posible, las pruebas se realizaron en Frankfurt para ambos proveedores de nube (o en los Países Bajos en los casos en que las opciones de tipo de instancia estaban restringidas).
En todos los gráficos, uso nombres convencionales para las instancias, los mismos que usan sus proveedores. Las instancias se clasifican primero por proveedores de nube (AWS, luego GCP) y luego por generación: de más antiguas a más nuevas.
Los resultados completos, aunque en forma cruda, están disponibles en mi hoja de evaluación comparativa completa . Allí podrá encontrar más datos de los que presento en este artículo, incluidos los números de latencia y ancho de banda, y el rendimiento comparativo de diferentes JVM.
Las instancias s1 de “primera generación” basadas en la generación m5a con AMD EPYC 7571, que datan del tercer trimestre de 2019, son nuestra opción heredada. Son las menos eficientes y lentas entre nuestras opciones en Frankfurt, y cuestan aproximadamente ~0,2080 €/h bajo demanda. La transición a la nueva familia s2, que cuesta ~0,2070 €/h, produce el doble de eficiencia por básicamente el mismo precio. Alentamos a los clientes a migrar a estas opciones más rentables y de mayor rendimiento para mejorar los tiempos de consulta y la velocidad de ingesta para aplicaciones analíticas.
La familia g1 se basa en Graviton 2 e históricamente ha ofrecido un buen valor, pero la familia s2 más nueva con procesadores AMD ahora iguala su nivel de eficiencia para Apache Kafka. A pesar de ofrecer un ancho de banda ligeramente menor y una ventaja de precio marginal, la familia g1 ahora se considera obsoleta en comparación con las opciones más nuevas.
La familia g2, impulsada por Graviton 3, destaca como nuestra principal recomendación debido a su eficiencia superior. Supera a las familias s2 e i2 hasta en un 39% en ciertos escenarios, ofreciendo una solución rentable en casi todas las regiones, lo que la hace ideal para la mayoría de los casos de uso de Apache Kafka. Dada la típica naturaleza ligada a IO de Kafka, optimizar la eficiencia computacional resulta crucial para ahorrar costos. He observado una tendencia creciente hacia la adopción de la arquitectura arm64, y casi la mitad de nuestros clústeres ya aprovechan esta tecnología más nueva.
Las pruebas muestran que cada nuevo procesador AMD o Intel mejora en términos de rendimiento y latencia generales. A pesar de ello, las ganancias de eficiencia para las nuevas generaciones m6 y m7 se han estancado. Incluso la generación m7, aunque potencialmente ofrece una latencia más baja en algunas regiones, no alcanza la eficiencia en comparación con la familia g2, según nuestras pruebas.
La familia m7a sobresale en aplicaciones de baja latencia, superando tanto a Intel como a las generaciones anteriores de AMD en términos de rendimiento y latencia. Si bien no está disponible universalmente, esta arquitectura refleja el progreso de AMD en la mejora del rendimiento. Si está disponible en su región, considere el m7a para obtener resultados superiores.
Las instancias de GCP generalmente tienen una eficiencia menor que sus alternativas de AWS. Esta fue una gran idea para mí, ya que los clientes normalmente prefieren GCP por su rentabilidad en aplicaciones analíticas, lo que resulta en facturas más bajas. Nuestra familia sg1 utiliza la generación del estándar n2, comparable a la familia AWS s2. Sin embargo, mi intento de ampliar esta comparación a otros tipos de instancias se vio limitado por la disponibilidad regional, especialmente para las generaciones c3 y n2.
Las instancias Arm que utilizan procesadores Tau de GCP ofrecen una mejora de eficiencia del 5 al 7 % con respecto a Graviton 2, lo que las convierte en una opción razonable de ahorro de costos, si está disponible en su región . Aunque el soporte de GCP para instancias arm se limita a cuatro regiones, proporciona un rendimiento y una eficiencia comparables a los de la familia g1.
Dado que los clústeres de Apache Kafka tienen un uso constante de VM, aprovechar los descuentos por uso sostenido permite obtener descuentos de hasta un 20 %. Esto hace que potencias computacionales aún más antiguas, como Ampere Altra, sean competitivas con Graviton 3 en términos de eficiencia. Sin embargo, las comparaciones directas son complicadas aquí debido a los descuentos adicionales de AWS que también pueden aplicarse.
Pensé que vería una mejora significativa con las versiones más nuevas de JVM en la arquitectura ARM. Sin embargo, parece que openjdk-11 y corretto-11 ya están bastante optimizados para ARM. Dado que las versiones más nuevas de Kafka requieren Java 17 y superior, cambié a Java 17, lo que resultó en una ganancia de rendimiento de aproximadamente entre un 4% y un 8% en nuestras pruebas comparativas.
Además, 21.0.2-amzn parece prometedor, ya que ofrece un aumento de rendimiento adicional del 10 al 20 % en tipos de instancias más nuevos.
De vez en cuando, realizo investigaciones internas para encontrar soluciones óptimas para nuestros grupos de producción y recopilar información útil. El cambio hacia la arquitectura ARM es ventajoso para los servicios gestionados, ya que ahorra dinero y reduce el uso de energía.
Depender de ARM ya ha demostrado ser beneficioso, ya que mejora el rendimiento y la rentabilidad tanto del servicio gestionado para Apache Kafka como del servicio gestionado para ClickHouse. Esta investigación ayudó a perfeccionar nuestra matriz de pruebas, identificando los entornos y áreas más eficientes para una mayor optimización. Siempre estamos en ello: ajustando y refinando bajo el capó, y estoy feliz de compartir nuestro conocimiento con la comunidad. ¡Manténganse al tanto!