09/19/2023

Guía de Pruebas de Performance Distribuidas con JMeter

COMPARTIR EN:

  • Linkedin Logo
  • Twitter Logo
  • Facebook Logo
  • Mail Logo

En ciertas ocasiones durante el proceso de las pruebas de performance es posible alcanzar el límite de carga que puede ser generado por un solo equipo, ya sea debido al hardware del mismo, o por limitaciones de la herramienta de generación de carga, en este caso, JMeter.

Al enfrentarnos a esta situación, la forma de continuar con las pruebas de performance es realizando una distribución de la generación de la carga en distintos equipos. Desde un equipo “Master” se podrán controlar múltiples nodos remotos “Esclavos” que serán los encargados de generar la carga de manera distribuida y así alcanzar un mayor número de usuarios concurrentes.

pruebas de performance distribuidas

Introducción

Esta técnica también se puede aplicar con equipos virtuales en la nube, permitiendo escalar rápidamente y en caso de ser necesario ejecutar desde distintas ubicaciones geográficas.

El objetivo de esta guía es indicar de forma clara y concisa los pasos necesarios para poder realizar una ejecución de pruebas de performance distribuidas a través de la herramienta JMeter, tanto en Windows como en Linux.

Componentes

Antes de comenzar con la configuración, se desplegará aquí la información sobre los principales componentes de la ejecución.

Las imágenes presentadas a continuación ilustran la forma de trabajo de la ejecución distribuida:

componentes

Master: La instancia o máquina desde donde se estará controlando las pruebas distribuidas que se ejecuten desde otras máquinas generadoras de carga.

Esclavas: Instancias o máquinas generadoras de carga.

Pasos previos

Antes de comenzar con las configuraciones tanto de las generadoras como del nodo master, es necesario realizar ciertas validaciones:

Versiones

Lo primero que se debe verificar es que los nodos (Master y Esclavas) cuenten con la misma versión de JMeter y Java instalados.

JMeter

Para verificar la versión de JMeter en el equipo ejecute la herramienta abriendo el archivo ApacheJMeter.jar ubicado dentro de la carpeta carpetaJMeter/bin. Luego, cuando se abra la aplicación, verifique la versión titulada junto al nombre en la parte superior izquierda, tal como se muestra en la imagen debajo.

JMeter

En caso de no contar con interfaz gráfica, desde la terminal, y ubicado en el directorio donde se encuentra JMeter, ejecute el comando Jmeter -v y deberá ver algo similar a la siguiente captura.

JMeter

Java

Desde la terminal ejecute el comando java -version

JAVA

Verificación de Subred

Para poder hacer uso de la ejecución de pruebas distribuidas se debe corroborar que tanto la Master como las Esclavas están dentro de la misma subred. Lo dicho anteriormente es una condición que exige la herramienta.

Para verificar que los equipos se encuentran dentro de la misma subred, desde la terminal y en cada uno de los equipos, ejecutar el comando ipconfig (ifconfig en Linux) y verificar que en donde dice Máscara de subred los primeros nueve dígitos sean iguales.

Verificación de Subred

Firewall

Se debe permitir el tráfico a través de ciertos puertos, los cuales son indicados más adelante en el documento.

Configuración SSL del RMI

RMI (Remote Method Invocation) es un protocolo de comunicación que permite a un programa en una máquina virtual de Java (JVM) invocar métodos en un objeto remoto, que se encuentra en otra JVM en una máquina diferente.

En aplicaciones que utilizan RMI, el SSL puede ser utilizado para asegurar la conexión entre el cliente y el servidor. 

Para poder correr las pruebas de forma distribuida, JMeter provee un script para generar un almacén de claves RMI que contiene una clave y su certificado correspondiente

El script se encuentra en el directorio bin y está disponible para sistemas Windows (llamado bin/create-rmi-keystore.bat ) y sistemas Linux (llamado bin/create-rmi-keystore.sh ). 

Luego de ejecutado el script (se recomienda ejecutarlo desde dentro del directorio), se generará un par de claves, que serán válidas durante siete días, con una frase de contraseña predeterminada de valor ‘changeit’.

Cuando ejecute el script, le hará algunas preguntas sobre algunos nombres que incluirá en el certificado. Puede ingresar valores propios, siempre que la herramienta de almacenamiento de claves lo acepte. Ese valor tiene que coincidir con la propiedad “server.rmi.ssl.keystore.alias” , que por defecto es ‘rmi’.

Al utilizar Linux, se pedirá una password.

A continuación se presenta un ejemplo para poder crear satisfactoriamente el almacén de claves:

$ cd jmeter/bin

$ ./create-rmi-keystore.sh

What is your first and last name?

  [Unknown]:  rmi

What is the name of your organizational unit?

  [Unknown]:  My unit name

What is the name of your organization?

  [Unknown]:  My organization name

What is the name of your City or Locality?

  [Unknown]:  Your City

What is the name of your State or Province?

  [Unknown]:  Your State

What is the two-letter country code for this unit?

  [Unknown]:  XY

Is CN=rmi, OU=My unit name, O=My organization name, L=Your City, ST=Your State, C=XY correct?

  [no]:  yes

Luego de configurado el almacén, se debe copiar el archivo bin/rmi_keystore.jks en cada servidor y cliente de JMeter que desee utilizar para su configuración de pruebas distribuidas.

En caso de no desear configurar el SSL para el RMI, se puede simplemente deshabilitar indicando en el jmeter.properties el parámetro server.rmi.ssl.disable con el valor ‘true’. Tanto en el nodo Master como en los Esclavos.

Configuración de JMeter

Luego de realizadas las verificaciones previas y de configurar el SSL para RMI, se deben de configurar los hosts a ser utilizados por la Master.

Los mismos deben ser indicados por extensión dentro del archivo jmeter.properties.

  • En el nodo del controlador que actúa como Master, diríjase al directorio jmeter/bin
  • Abra el archivo jmeter.properties (utilizando el editor de texto de su preferencia)
  • Dirijase a la linea remote_hosts
  • Agregue la dirección IP o nombre de host de cada nodo Esclavo (separados por comas)

En el siguiente ejemplo se indican 5 equipos como generadores de carga. Cuatro de ellos a través de IP, y uno por nombre de host:

remote_hosts=192.168.0.10,192.168.0.11,esclava_3,192.168.0.13,192.168.0.14

Especificación de puertos

Para poder llevar a cabo una correcta ejecución del script, los nodos Master y Esclavos deben comunicarse entre sí a lo largo de toda la prueba.

En primera instancia el nodo Master debe realizar una conexión con los nodos Esclavos y ciertas verificaciones, luego se indica el comienzo de la ejecución a todos ellos, y finalmente debe indicar el fin de la ejecución del script. Por otro lado, los nodos Esclavos deben reportar periódicamente los resultados preliminares durante la ejecución de la prueba.

Para poder realizar esta comunicación entre nodos, la herramienta JMeter utiliza distintos puertos los cuales por defecto son asignados de forma aleatoria al momento de la ejecución. Si por el contrario se desea indicar estos puertos de forma manual, ya sea para permitir el tráfico únicamente por estos, o simplemente para tener un mayor control durante la ejecución, se deben realizar las siguientes configuraciones sobre el archivo jmeter.properties.

Puerto RMI

En los nodos Esclavos buscar el parámetro server_port e indicar el puerto deseado como se muestra en la siguiente captura:

Puerto RMI

En el nodo Master buscar el parámetro remote_hosts e indicar el puerto luego de la dirección IP o nombre de host como se muestra en la siguiente captura:

Puerto RMI

Puerto local cliente RMI

En el nodo Máster buscar el parámetro client.rmi.localport e indicar el puerto deseado como se muestra en la siguiente imagen:

Puerto local cliente RMI

Tener en cuenta que JMeter utiliza el puerto indicado y el siguiente.

Puerto local servidor RMI

En el nodo Esclavo buscar el parámetro server.rmi.localport e indicar el puerto deseado como se muestra en la siguiente captura:

Puerto local servidor RMI

Ejecución distribuida

Antes de dar inicio a las pruebas, y de ser posible, todas las generadoras deben tener la misma ruta accesible (por ejemplo C:\JMeter\Script\ en Windows o /home/ubuntu/Script/ en Linux) de forma tal que la ejecución del script funcione sin problemas. De lo contrario, dejar todos los archivos necesarios para la ejecución (csv, imágenes, etc.) dentro de la carpeta /bin de JMeter.

Luego de realizados y/o verificados todos los pasos anteriores, procedemos a dar comienzo al inicio de las pruebas. Una vez que esté todo configurado, ejecutar el comando “jmeter-server” en cada uno de los nodos Esclavos para iniciar el servicio de JMeter en modo servidor.

En Windows al ejecutar el jmeter-server.bat, si el proceso logró ejecutarse sin problemas, la terminal quedará como la imagen que se ve a continuación:

Ejecución distribuida

En Linux, el archivo a ejecutar es el jmeter-server, y es posible que se necesite otorgar permisos de ejecución sobre los archivos jmeter-server y jmeter.

A partir de este momento, los nodos Esclavos quedarán a la espera de que se les indique el comienzo de las pruebas.

Inicio de las pruebas

Existen distintas formas de iniciar la ejecución distribuida, en primer lugar, y solo a modo de depuración o verificación de la correcta configuración, utilizando la GUI (Graphic User Interface).

Por otro lado y ya enfocado en la ejecución formal de las pruebas, a través del CLI (Command Line Interface).

GUI

Para verificar la correcta configuración de todos los componentes, incluso el script en sí mismo, se recomienda hacer una primera ejecución desde la GUI de ser posible.

Para esto, iniciar JMeter de forma tradicional, abrir el Plan de Pruebas (archivo .jmx), dirigirse al menú Run y elegir la opción Remote Start. Se desplegará un menú con los hosts remotos configurados en el archivo jmeter.properties. Allí se podrá seleccionar uno y verificar el correcto funcionamiento del script con alguno de los elementos de depuración (View Results Tree o cualquier otro Listener de preferencia). También se debe visualizar en la terminal donde está ejecutando jmeter-server el inicio y finalización del script.

GUI

En el menú Run también es posible seleccionar la opción Remote Start All. En ese caso se iniciará la ejecución en todas las generadoras configuradas en el archivo jmeter.properties.

Es importante tener en cuenta que la configuración de los Thread Group aplica para cada una de las generadoras. Es decir, si se cuenta con 3 nodos Esclavos y se ejecuta el script desde el nodo Master configurado con 10 usuarios, cada generadora simulará 10 usuarios, llegando a un total de 30.

CLI

Si se cuenta con la configuración correcta en el jmeter.properties, simplemente se debe agregar la opción “-r” a la ejecución por línea de comandos que se utiliza normalmente, por ejemplo:

jmeter -n -t <ruta_al_script> -r

La opción “-r” toma a todas las esclavas mencionadas en la propiedad remote_hosts.

Por el contrario, se pueden indicar los nodos esclavos al momento de la ejecución, utilizando la opción “-R” seguido de las direcciones IP o nombres de hosts de los nodos Esclavos.

jmeter -n -t <ruta_al_script> -R server1,server2,…

Errores conocidos y soluciones

Error de SSL en equipos Linux

En algunas ocasiones, en equipos Linux se pueden presentar errores al configurar el SSL para RMI. En estos casos, la solución encontrada es cambiar el tipo del almacén de claves.

Para esto, se debe generar una nueva keystore rmi (llamada rmi_keystore2) que permita trabajar en este sistema:

  • Ingrese al Terminal 
  • Diríjase a la carpeta /bin
  • Ejecute el siguiente código: 

keytool -importkeystore -srckeystore rmi_keystore.jks -destkeystore rmi_keystore2.jks -deststoretype pkcs12 -destkeypass <password> 

  •  Ahora ingrese la password de su rmi_keystore2.jks.

Error de SSL en equipos LinuxA partir de aquí, trabajará con el archivo rmi_keystore2.jks. Se recomienda renombrarlo en los nodos Esclavos como rmi_keystore.jks, igual que el original.

Non HTTP response code

Durante la ejecución de las pruebas, cuando la capacidad de generación de las Esclavas llega a su límite, pueden aparecer excepciones como las siguientes:

  • javax.net.ssl.SSLHandshakeException/Non HTTP response message: Remote host terminated the handshake
  • javax.net.ssl.SSLException/Non HTTP response message: Connection timed out (Read failed)

En esos casos se recomienda contar con una mayor cantidad de nodos Esclavos y utilizar equipos en la nube aplicando las configuraciones para alta concurrencia.

Configuraciones para alta concurrencia

Dependiendo de la complejidad del script y los recursos necesarios para ejecutarlo, el límite de una generadora de carga puede estar en distintos niveles de concurrencia. Con estas configuraciones, un script de baja complejidad y en equipos con las siguientes características, se probó generar hasta 25.000 usuarios activos por instancia, pudiendo tener hasta 2 instancias de jmeter-server ejecutando en paralelo, llegando a 50.000 usuarios concurrentes por instancia de AWS.

Tipo de instancia esclava en AWS: r5b.12xlarge

RAM: 384GB

vCPU: 48 cores

Network: 10 Gigabit

En caso de que la infraestructura de ejecución este desplegada en AWS, tanto los equipos master como los esclavos deben encontrarse en la misma zona de disponibilidad:Configuraciones para alta concurrencia Habilitar tráfico en Amazon Web Services (AWS)

Si se utilizan equipos en la nube, por ejemplo AWS, se deberán generar las reglas de entrada para el nodo Master, así como para los nodos Esclavos.

En las siguientes capturas se puede ver la forma de hacerlo:

MasterMasterEsclavosEsclavosCuando se alcanza el límite pueden suceder distintos errores o excepciones de Java, JMeter o del sistema operativo mismo. En esos casos es importante aplicar las siguientes configuraciones:

Parámetros del Sistema Operativo (Linux)

En primer lugar se deben configurar los parámetros de ejecución del kernel. Para esto modificar el archivo /etc/sysctl.d/99-sysctl.conf (archivo de texto, se puede usar nano o vi) e incluir los siguientes parámetros:

kernel.shmall = 4294967296

fs.file-max = 250000

net.ipv4.ip_local_port_range = 1024 65535

kernel.pid_max = 4194303

net.ipv4.tcp_tw_reuse = 1

Actualizar los parámetros de las nuevas configuraciones con el siguiente comando:

sysctl -p

Preparación JMeter

Agregar setenv.sh en la ruta /bin del JMeter y definir los parámetros de la JVM como sigue:

export HEAP=”-Xms32G -Xmx32G -XX:MetaspaceSize=1G -XX:MaxMetaspaceSize=1G”

Configuración de múltiples instancias JMeter

Copiar la carpeta de instalación de JMeter, e incluir un -1 y -2 sobre el final, quedando por ejemplo:Configuración de múltiples instancias JMeterSe debe levantar cada uno de los jmeter-server correspondientes para cada instancia JMeter en el equipo, y tener en cuenta las configuraciones de puertos necesarios.

Verificacion

Para verificar si la configuración del equipo soporta los 50.000 usuarios, se puede utilizar un script de prueba y ejecutar de la manera que se muestra a continuación:

Configuración de múltiples instancias JMeter

Es posible verificar la cantidad de threads durante la ejecución con el siguiente comando:

ps -eLf | grep java | wc -l

Conclusiones

En esta guía se presentaron los pasos para llevar a cabo una prueba de carga de manera distribuida utilizando la herramienta JMeter, sobre sistemas operativos Windows y Linux.

Se plantea una configuración específica para alta concurrencia probada con equipos en la nube AWS generando hasta 1 millón de usuarios concurrentes utilizando hasta 20 nodos Esclavos.

Utilizar instancias en AWS para llevar a cabo la ejecución de las pruebas de carga brinda la escalabilidad necesaria para simular diferentes escenarios.