Quando sviluppiamo una applicazione Web, abbiamo di fronte un incognita, che solo l'esperienza e l'uso di tool appropriati ci permette di chiarire: come si comporterà la nostra applicazione sotto carico? La domanda non ha facile risposta, in quanto tutto dipende da diverse variabili in gioco: il numero simultaneo di accessi, le risorse dedicate alla stessa applicazione e non da meno, come le componenti dell'applicazione (accesso a file, database, socket, ecc) sono state sviluppate.
Prima del rilascio di un'applicazione è sempre bene effettuare delle sessioni di stress test in modo da non avere sorprese una volta che l'applicazione sarà on line. L'obiettivo principale di uno stress test è quello di simulare un grande numero di richieste simultanee verso l'applicazione e valutarne i tempi di risposta. Un servizio opportunamente configurato dovrebbe avere un tempo di risposta accettabile, viceversa, l'aumento dei tempi o il blocco dell'applicazione ci indica che le risorse a disposizione non sono ben dimensionate (o che l'applicazione fa un cattivo uso delle risorse).
Simulare un numero sufficientemente alto di richieste verso un server può essere fatto da Java ricorrendo alla programmazione concorrete (thread programming). Ogni thread simula il comportamento di un utente, e misurando i tempi di risposta possiamo ottenere il risultato desiderato. Lo sviluppo di un siffatto stress test è peraltro da prendere in considerazione solo in casi estremi, in quanto è un evidente spreco di tempo da dedicare allo sviluppo di un tool dedicato ad una singola specifica operazione. Riutilizzare strumenti già sviluppati e testati è invece la strategia che adotteremo, in particolare per una attività (stress test di web server) ripetitiva e facilmente configurabile.
JMeter è un progetto opensource della fondazione Apache (del quale avevamo già parlato) sviluppato per automatizzare le operazioni di test di carico su macchine remote (web server, application server, database). Il progetto si è evoluto nel tempo diventando uno degli strumenti del suo genere più utilizzati, e per facilità d'uso e per la possibilità di essere integrato in altri test. Al momento in cui scrivo la versione di riferimento è la 2.3.1.
L'applicazione è un programma standalone sviluppato in Java. Come abbiamo detto è possibile configurare i test anche grazie all'interfaccia programmatica (API) possibilmente per integrarli all'interno della suite di test sviluppati per l'applicazione. Noi ci occuperemo di fare una panoramica delle più comuni funzionalità, mostrando come poter immediatamente effettuare il test delle vostre applicazioni da interfaccia grafica.
Test web application
Tra le diverse opzioni che JMeter presenta, questa è quella più interessante, in quanto ci consente testare un generico web server (indipendente dalla tecnologia utilizzata). La maggior parte delle volte, quello che vogliamo testare è proprio la velocità di risposta di un web server in particolari situazioni di traffico, ad esempio un picco di accesso al login di una intranet aziendale (1'000 dipendenti che effettuano il login tra le 8:00 e le 8:05).
Attraverso JMeter, vediamo come sia possibile simulare siffatta situazione.
Abbiamo già detto che l'applicazione si presenta come un'applicazione desktop, quindi (dopo aver effettuato il download) dobbiamo lanciare il programma (bin/jmeter.bat).
La principale entità che definiamo è il Thread Group, che rappresenta il gruppo di richieste simulanee:
Figure 1. Creazione di un Thread Group
Per aggiungere un nuovo gruppo, selezioniamo "add Thread Group" dal menu di Test Plan. Ad esso gli diamo un nome e lo configuriamo secondo il nostro test, settando il numero di operazioni concorrenti (users), 1000 nel nostro caso ed il tempo entro cui farle partire tutte (300 secondi, cioè 5 minuti nel nostro caso). Infine definiamo il numero di cicli (loop count) che devono essere effettuati (noi ne effettuiamo 2) oppore settiamo il flag per un ciclo infinito. Di fatto stiamo spalmando su 300 secondi 2*1000 richieste (una ogni 0,15 secondi).
Possiamo identificare uno o più Thread Group per gestire diverse attività all'interno della web application. Il thread group, rappresenta il comportamento, ora al suo interno definiamo l'azione (o le azioni) da effettuare.
Per fare ciò aggiungiamo dal pannello del Thread Group un elemento Sampler, un HTTP Request, che rappresenta la chiamata ad una pagina Http:
Figure 2. Creazione di un Sampler HTTP Request
Oltre al nome, ogni richiesta deve definire il server ed il numero della porta a cui il servizio Web risponde (intranet.application:8080, nel nostro caso). Segue la definizione del protocollo (http, come default) ed il metodo (get o post). Infine il percorso della pagina web da testare (login.jsp).
A questo punto la configurazione potrebbe essere terminata, se non avessimo la necessità di definire dei parametri (utilizzati dalla pagina login.jsp). Facilmente di aggiungiamo col pulsante di Add, specificando la coppia nome/valore. Interessante notare come sia possibile includere come parte della http request anche un valore complesso definito in un file (che specifichiamo aprendo la finestra di dialogo).
Come avete avuto modo di vedere ci sono decine di sampler che vi consentono di effettuare diverse tipologie di test. Il relativo modo di utilizzo è altrettanto semplice ed intuitivo, quindi utilizzate questi strumenti per ogni vostra specifica esigenza. A seguire, potremmo aggiungere altre attività al nostro gruppo di thread, in modo da simulare un comportamento utente più complesso: noi ci limitiamo a questo test diretto.
Ultimo elemento che ci serve è quello per misurare le prestazioni, quindi aggiungiamo (dal pannello del thread group) un Listener. Esistono anche qui decine di diverse tipologie di listener, alcuni che ci mostreranno il riassunto in forma tabellare, altri in forma grafica. Il più semplice è il Summary report, che mostra in forma tabellare i risultati dell'esecuzione.
Figure 3. Creazione di un Listener
Nell'immagine d'esempio vediamo il risultato temporaneo di una generica esecuzione, errori, throughput medie varie, ... Ogni listener vi darà dati più o meno dettagliati.
Test web service
Dei diversi Sampler presenti, sicuramente quello citato nel paragrafo superiore è il più interessante, per ovvie ragioni di utilizzo. Vediamo qualche altro esempio. Utilizzando architetture SOA avrete senz'altro l'esigenza di "stressare" i vostri web service, e JMeter ve ne da la possibilità con il sampler WebService (SOAP) request.
Figure 4. Creazione di un WebService Request
A differenza del sampler precedente questo fa tutto da solo caricando l'URL WSDL. Automaticamente i parametri di configurazione verranno caricati dalla lettura del WSDL, a voi non vi resta che scegliere il metodo WebMethods che si caricherà con i metodi esposti dal WSDL.
L'operazione successiva è quella di costruire il messaggio XML SOAP di request, oppure definire un file che ne contenga la sua sintassi (come in questo caso). Il resto delle operazioni è identico. Anzi, in questo caso vi suggerisco di utilizzare il Listener "View Result Tree" che vi da la possibilità di navigare i messaggi SOAP di richiesta e di risposta.
Test Database
Oltre ad effettuare test di carico su web application, un altro interessante uso che può essere fatto di JMeter è per stressare le connessioni sui database. Per configurare un test su un database dovremo utilizzare il Sampler JDBC request, preceduto però da un altro elemento per definire la configurazione del database.
Aggiungiamo tale elemento al Thread, questa volta selezionando tra gli elementi Config, JDBC Connection Configuration.
Figure 5. Creazione di una configurazione JDBC
Definiamo opportunamente i parametri di configurazione, il cui significato si intuisce dalle etichette. A questo punto abbiamo pronta una connessione chiamata MyConnection che si riferisce al database in oggetto. A partire da questa possiamo inserire uno o più Sampler JDBC request, che rappresentano le query SQL al nostro database.
Ognuna di essa si presenta come di seguito:
Figure 6. Creazione di un JDBC Request
Il nome della connessione identifica quale di esse utilizzare (quella creata nella precedente configurazione), dopodichè potrà essere selezionato il tipo di query e nel pannello potremo definire la stessa query (select, update, call, ...) da effettuare.
Attraverso questo strumento possiamo comprendere quanto realmente la base di dati influisca sulle performance dell'applicazione e come poterla dimensionare correttamente.
Conclusioni
In questo articolo abbiamo visto alcune delle innumerevoli opportunità che JMeter ci permette di testare, soffermandoci sull'utilizzo più generale. Questa applicazione è indipendente dal servizio di cui vogliamo misurare le prestazione, ma abbiamo detto può essere integrata all'interno della suite di test di una web application java based attraverso le API esposte. Per maggiori dettagli su questa funzionalità vi rimandiamo al sito (il link nell'introduzione) dove effettuare il download del sorgente ed approfondire il discorso pratico di tutte le sue componenti.