jueves, 9 de febrero de 2012

JMeter VII: Ejecución remota de scripts en JMeter.


Una de las características que presenta JMeter es la posibilidad de realizar la inyección de carga de un script desde varios equipos , de manera que se pueda aumentar el número de peticiones concurrentes/simultáneas a los servidores de la aplicación


Para lograr esto , hay que seguir una serie de pasos. En principio, son sencillos y no debe de presentar dificultad para un usuario novato lograr la ejecución de un script simple usando una o varias máquinas inyectoras.

Conceptos y requisitos previos.

Debemos tener en cuenta una serie de requerimientos previos, de sentido común, sobre los equipos controlador, inyectores y la aplicación a analizar.

  1. El equipo controlador tendrá el script a probar, así como los ficheros de parámetros CSV Dataset definidos para la prueba
  2. El equipo controlador tendrá conectividad con, al menos un puerto TCP de las máquinas inyectoras. Si debe ser un puerto explícito, esto debe ser configurado en el fichero jmeter.properties, sección “remote_hosts”
  3. El equipo controlador almacenará todos los ficheros ,tanto de resultados de la prueba generados por los listener o escritores de datos simples, como los de log del comportamiento del jmeter (jmeter.log)
  4. Los equipos inyectores tendrán los mismos ficheros de datos definidos en el script en las mismas rutas que se definen en el script.
  5. Los equipos inyectores dispondrán al menos de un puerto TCP disponible con el que se comunicarán con el equipo controlador
  6. Los equipos inyectores tendrán visibilidad sobre la aplicación a probar
  7. Todos los equipos ejecutarán la misma versión de JMeter.
  8. Los equipos inyectores , previo al lanzamiento de las pruebas ,tendrán en ejecución el proceso –servicio- demonio jmeter-server (.bat en el caso de Windows .sh en el caso de Unix)
La configuración de los equipos a actuar como inyectores remotos, se efectúa en el fichero jmeter.properties. Este fichero se encuentra en la ruta

JMETER_HOME\bin\jmeter.properties

El fichero tiene una sección “remote hosts” ,donde se incluye ,tanto los equipos que actuarán como inyectores remotos, como la configuración de los puertos TCP por donde se realizará la comunicación

#---------------------------------------------------------------------------
# Remote hosts and RMI configuration
#---------------------------------------------------------------------------

# Remote Hosts - comma delimited
remote_hosts=192.168.0.1,192.168.10.2,192.168.45.3
#remote_hosts=localhost:1099,localhost:2010

# RMI port to be used by the server (must start rmiregistry with same port)
#server_port=1099

# To change the port to (say) 1234:
# On the server(s)
# - set server_port=1234
# - start rmiregistry with port 1234
# On Windows this can be done by:
# SET SERVER_PORT=1234
# JMETER-SERVER
#
# On Unix:
# SERVER_PORT=1234 jmeter-server
#
# On the client:
# - set remote_hosts=server:1234

# To change the default port (1099) used to access the server:
#server.rmi.port=1234

# To use a specific port for the JMeter server engine, define
# the following property before starting the server:
#server.rmi.localport=4000

# From JMeter 2.3.1, the jmeter server creates the RMI registry as part of the server process.
# To stop the server creating the RMI registry:
#server.rmi.create=false

# From JMeter 2.3.1, define the following property to cause JMeter to exit after the first test
#server.exitaftertest=true

Tabla 1. jmeter.properties.Sección configuracion inyección remota

Invocación de inyectores remotos y ejecución de scripts


Una vez cumplimentados los requisitos y preparativos citados, la ejecución remota de scripts es sencilla. Dependiendo de si lo hacemos desde el entorno gráfico o desde línea de comandos.
Vamos a explicar ambos casos, aunque ,como cualquier que haya leido este blog, se recomienda vivamente para pruebas con niveles de carga altos, usar la opción desatendida.

Modo GUI

El modo del entorno gráfico, tiene una ventaja respecto al modo desatendido y es que permite incrementar la carga a lo largo de los inyectores a medida que avanza la prueba.

Para ello, lo que habría que hacer es ir seleccionando inyector remoto, tras inyector remoto , hasta que se llegue a los puntos de saturación o límites de carga buscados


Ilustración1. Opciones de inyección remota en modo GUI JMeter.

Modo desatendido (línea de comandos)

La manera de invocar la opción de inyección remota se haría con la siguiente sentencia y parámetros

JMETER_HOME\bin\jmeter -n -t RUTA_SCRIPT -R IP[,IP2,IP3...IPN] -X

Donde
  • RUTA_SCRIPT es la ruta al fichero .jmx del script de prueba
  • IP [,IP2,IP3...IPN] es el listado de las IP de los equipos inyectores
  • -X es opcional.Indica que ,una vez finalizada la prueba, cierre el servidor de JMeter en los equipos inyectores
Uso de variables en pruebas de carga con inyección remota

Como todos sabemos, uno de los problemas que se presentan con JMeter, es la ejecución de scripts de manera remota. La razón básica es porque no permite la exportación de las variables del equipo que ejecuta el script .jmx a los equipos que actúan como inyectores remotos

Ejemplo.

Ilustración 2. Variables definidas por usuario en script JMeter


Lógicamente, uno esperaría que al ejecutar un script donde se definen estas variables, estas tomaran los valores definidos en todos los equipos de prueba. Pero, ignoro la razón técnica, no se conservan dichas asignaciones. Por lo que las referencias en los equipos, aparecen con las cadenas literales del nombre de la variable.

Así, la variable ${FECHA}, que en un escenario ejecutado desde el equipo local tomaría el valor del año-mes-día , aparecerá en las invocaciones que las use como la cadena literal ${FECHA}

Para solventar esto, por puro método de prueba y error, hemos observado que, si uno quiere usar variables compartidas entre todos los equipos inyectores debe incluir la llamada con el formato

${__property(${expresión a asignar a la variable})}

Es decir: el uso de variables en escenarios remotos debe efectuarse mediante invocación explícita con la llamada a la función ${__property(…)}.

Para el caso de FECHA, la manera de incluir en una petición de muestreador http (o en el nombre de un fichero) sería algo como

${__property(${__time(YMD)})}.


Esto, estimado lector, puede ser algo raro si se ha parado a leer alguna vez la definición de las funciones .En concreto la relativa a property


“The property function returns the value of a JMeter property. If the property value cannot be found, and no default has been supplied, it returns the property name. When supplying a default value, there is no need to provide a function name - the parameter can be set to null, and it will be ignored.”

Es decir, la función property evalúa una propiedad de JMeter definida en los ficheros de la aplicación jmeter.properties, user.properties o el definido en la invocación por línea de comandos con el parámetro
–Gficherousuario.properties

Sin embargo , si uno intenta llevar a cabo la implementación de parámetros a usar dentro de un fichero “.properties” ,con vistas a evaluarlos como variables con la función property, el resultado es nulo. La función no implementa la variable pasada como parámetro a la función y produce el mismo resultado en su invocación explícita que el que presenta si la definimos como una variable definida por usuario en la construcción del script.

Es decir, según la imagen anterior de “Variables definidas por usuario”, una invocación en un muestreador http, que utilizara la variable YEAR, que ha sido definida como una invocación a la función time con formateo de el año ( ${__time(Y)} )
Ilustración 3. Peticion HTTP con variable de usuario

Debería haber sido invocada como

Ilustración 4. Petición HTTP con variable remota

Por lo tanto, resumiendo para el uso de pruebas distribuidas con JMeter debemos de tener en cuenta:

  • Las variables que definimos dentro del script de JMeter , deben ser explicitadas con la evaluación de la expresión que se desee mediante la función property
  • Debemos recordar que la carga lanzada en varios inyectores remotos no se distribuye, sino que se ejecuta tal y como se define en el script.
  • Es necesario invocar explícitamente a los equipos inyectores desde la línea de comandos con el parámetro –R IP1,IP2,IP3…IPN
  • La inclusión de variables de un CSVDataset, forzosamente incluirá que todos los equipos inyectores tengan el mismo fichero de datos, en la misma ruta en la que fue definido en el script.
  • Los equipos que actúen como inyectores remotos deben estar ejecutando el programa/servicio/demonio jmeter-server (en Windows jmeter-server.bat) y debe ser la misma versión de JMeter que el equipo que actúe como controlador del escenario.

Conclusión
Hemos llegado de momento, a finalizar esta exposición de conocimiento sobre JMeter. Quiero agradecer a mi compañero Federico Yansón el tiempo y esfuerzo dedicados, para lograr a comprender cómo lanzar pruebas remotas en JMeter de la manera más completa posible.