SyntaxHighlighter

jueves, 3 de octubre de 2013

Load Testing Moodle con Jmeter

Jmeter es una herramienta muy útil para hacer test de carga de distintas aplicaciones. Es tan flexible puede servir para poner a prueba tanto una aplicación web, como un servidor de base de datos o incluso un servicio tipo SOAP.

La potencia de Jmeter radica en la capacidad para simular la actividad de usuarios o las peticiones a un determinado servicio o aplicación, de forma concurrente. Estas pruebas nos pueden ayudar en el dimensionamiento del servidor, posibles fallos o problemas derivados de la concurrencia, etc.

Otra característica muy interesante de la herramienta es que puede "grabar" la actividad del navegador para después lanzar una determinada cantidad de usuarios o "hebras" que ejecuten esta misma actividad. Esto se realiza creando un proxy en jmeter al que debemos apuntar nuestro navegador. Jmeter se encargará de ir almacenando todas las peticiones que se realicen. Para encontrar más información podéis buscar "jmeter proxy record" o términos similares.

Obviamente cualquier prueba de carga nunca debería ser ejecutada en un servicio/servidor de producción.

Para ponerse al día con la herramienta lo mejor es pasar por su documentación y buscar algún ejemplo en concreto e ir modificándolo para adaptarlo a nuestras necesidades. Esto mismo es lo que he hecho yo, basándome en un plan de pruebas existente en los foros de moodle.org (todos los agradecimientos a su autor). A partir de este plan de pruebas he ido parametrizando algunos procedimientos y adaptando su funcionamiento a los cambios de Moodle v2.5.

Las tareas que he incluido en el plan son:
  • Abrir la página principal de Moodle
  • Login en Moodle
  • Entrar en el curso
  • Acciones del usuario en orden aleatorio:
    • Actividad de texto
    • Mensaje en el chat
    • Mensaje en el foro y contestar a un mensaje en el foro
    • Subir un fichero a archivos privados
    • Enviar un fichero a una actividad (implica subir fichero)
  • Salir de Moodle

Peticiones y respuestas

La forma de proceder para cada una de las tareas de nuestro test será la siguiente:
  1. Realizar una petición al servidor web con una serie de parámetros
  2. Recibir la respuesta del servidor y comprobar que se ha realizado con éxito
  3. Capturar nuevos parámetros que nos serán útiles en peticiones posteriores
  4. Realizar una pausa aleatoria antes de llevar a cabo la siguiente petición y así adaptar el test a los tiempos que emplearía un operador humano.
Pero... ¿Cómo sabemos si una petición ha sido correcta? Lo más indicado es seguir los pasos "manualmente" en el navegador y así ver (directamente en pantalla o abriendo el código fuente devuelto) cual es la respuesta de la plataforma a cada clic. De esta manera podemos ir identificando los textos que se presentarán después de cada petición y utilizarlos en Jmeter.

Bien, ya hemos considerado dos de los elementos más importantes en el diálogo que se establece entre nosotros (o nuestro navegador) y el servidor web: peticiones y respuestas. Pero hay un elemento que aún falta y que es imprescindible si queremos simular ese diálogo: las cookies!! 

Como ya sabéis prácticamente todas las aplicaciones web utilizan cookies. Moodle también necesita crear una cookie en el navegador del usuario para mantener la sesión. En Jmeter dispondremos de un objeto que hará de gestor de cookies de manera que "cada usuario virtual" pueda mantener una sesión con el servidor.

El plan

Variables globales

Definir las "variables globales" del experimento. Como por ejemplo el host al que accederemos y el path dentro de ese host que aloja la plataforma. Esto no es obligatorio, pero siempre está bien para poder cambiar la máquina o la ruta de forma fácil. Si no parametrizamos estos datos tendremos que modificar cada petición cuando queramos probar contra otra máquina o si ha habido cambios en la ruta.
Estas variables no varían durante toda la ejecución del plan, por lo que podemos definirlas a nivel de "Test Plan".
Si llamamos a las variables host y path, cada vez que hagamos una petición podremos utilizar la ruta ${host}${path}. Supongo que queda claro que para hacer referencia al valor de una variable debemos utilizar la forma ${variable}.
Además de estas variables también he definido una ruta para el almacenamiento de los resultados de los tests, donde utilizo la expresión ${__time(yyyyMMdd_HHmm)} que devuelve la fecha y hora en la que se realizó el test.

Grupo de hilos

El siguiente elemento a definir es nuestro grupo de hilos (cuantos hilos y cuantas veces queremos repetir cada hilo). Este elemento será el que contendrá el resto de objetos de nuestro plan. Dentro de este objeto definimos elementos para cada una de las hebras (usuarios) que lanzamos. Esto queda claro si nos detenemos en el elemento UserParameters que contiene una serie de variables que distintas para cada hebra. Por ejemplo, cada hebra accederá con un usuario/contraseña distintos, para ello se sortea  un número del 1 al 10 con la función __Random y se añade al prefijo de usuario y al prefijo de contraseña (UsernameHead y PasswordHead respectivamente). También se tienen los nombres de los objetos de Moodle a los que accederemos: jmeter course, jmeter text assignment, jmeter forum, etc. Estos objetos, así como los usuarios deben estar creados previamente en la instalación de Moodle sobre la que estamos trabajando.

Interacciones con la plataforma

Analizaremos sólo una de las peticiones/respuestas, por ejemplo, la de login. El resto de peticiones son muy similares. Como se ve en la imagen, definimos las variables de la petición en el espacio Parameters. Estos parámetros construyen usando las variables que hemos definido en el grupo de hilos. En la parte superior de la ventana se da el host y el path completo de la petición.



Y ahora podemos comprobar si es usuario se ha identificado correctamente en la plataforma buscando la cadena "you are logged in as", que aparece en cualquier página de Moodle una vez que el usuario se ha identificado. Para ello añadimos un elemento del tipo Response Assertion y la configuramos para que busque la cadena en la respuesta del servidor.


De la respuesta que nos da el servidor también debemos extraer más cosas. Moodle necesita en muchas de las llamadas un id de session sesskey y además nosotros necesitamos el id del curso al que queremos acceder para realizar la próxima llamada que será del tipo

${host}${path}/course/view.php?id=${courseid}

Para obtener el id del curso, por ejemplo, configuramos un elemento de tipo Xpath Extractor que revisará la respuesta del servidor y buscará el id del curso. La expresión que se ha usado es:

substring-after(//*/a[text()='${course_name}']/@href,'=')

Explicación breve:

La función substring-after busca un carácter dentro de una cadena y devuelve la subcadena que hay después de ese carácter.

Lo que hay dentro de la función es una expresión xpath. Estamos diciendo que busque un enlace (tag "a" de HTML) en cualquier parte del documento que tenga como texto el nombre del curso (recordad que lo tenemos definido en las variables) y devuelva el valor de su atributo href. Si el enlace en cuestión es

<a class="" href="http://host/path/course/view.php?id=33">jmeter course</a>

La función devolverá lo que hay después del "=", dentro del atributo href, es decir, 33.



Después se incluyen dos elementos, en elemento de retardo para simular la interacción humana y otro que irá construyendo un gráfico con todas los valores obtenidos en cuando los usuarios ejecuten la tarea en cuestión.

Controladores lógicos

Después de entrar a la plataforma programaremos una serie de tareas que deberán realizar todos los usuarios. Para ello vamos a incluir un controlador lógico de orden aleatorio... ¿Qué quiere decir esto? Las tareas que se incluyen dentro de este controlador serán ejecutadas por las hebras de forma desordenada. Unas hebras entregarán la actividad primero, otras postearán en el foro, etc. Todo para intentar que la actividad sea todo lo "caótica" que podría ser en un periodo de alta actividad en el servidor web.

Subida de ficheros

Además de los parámetros típicos, ya sean vía metodos GET o POST del servidor podemos utilizar ficheros para que sean subidos a la plataforma. En un objeto Request se pueden incluir ficheros dando la ruta al fichero en la sección Send files with the request. Además del MIME/Type y el nombre del parámetro con que se enviará el mismo.



Esto es muy útil cuando estamos probando aplicaciones que previsiblemente recibirán ficheros de cierto tamaño mientras siguen respondiendo a peticiones de otros usuarios.

Depurado

Para intentar detectar fallos en nuestro plan o fallos en nuestra aplicación tenemos dos herramientas básicas que nos ayudarán: El debug sampler y el objeto View Result Tree. Con el primero tendremos acceso a todas las variables y parámetros que hemos definido en el plan. Con el segundo podremos ver el diálogo entre el cliente y el servidor a bajo nivel, es decir, las cabeceras de la petición HTTP, los parámetros que se han enviado y la respuesta del servidor en HTML, los mensajes de error del servidor en caso de que los hubiera, etc. Como vemos en la figura muestra las el resultado de las assertions que hemos definido, para que detectemos fácilmente errores en el script. Si alguna respuesta del servidor no verifica la condición que hemos establecido, en lugar del triángulo verde mostraría un símbolo rojo informando del fallo.


Resultados

Los datos que genera Jmeter serán normalmente el tiempo que ha llevado cada petición contando desde que se ha enviado la misma hasta que se ha recibido la respuesta al completo. Para visualizar estos datos tenemos muchas opciones aunque las más interesantes son el simple data writer que generará un archivo con los datos en crudo para poder ser procesados posteriormente con otra herramienta o cualquiera de las opciones gráficas o de resumen que dan algunas medidas estadísticas. Todas estas opciones pueden ser utilizadas simultáneamente añadiéndolas desde la sección Listeners. Además cualquiera de estos informes pueden ser salvados a fichero para un posterior análisis en un fichero en disco.
En un post siguiente mostraré los resultados de una ejecución contra varias instalaciones de Moodle y lo más interesante y complejo: cómo interpretar los resultados... Pero para eso aún me faltan conos y bastones que quemar.

Descargar fichero de test