S'abonner au Flux RSS

mardi, février 4 2014

Montée en charge de Wordpress

Dans la famille des tests de performance, le test de montée en charge consiste à tester un système avec un volume de données croissant afin de déterminer son comportement dans le temps, il est parfois aussi appelé test de vieillissement mais quelque soit son nom il a pour but de rassurer l'utilisateur sur l'utilisation à venir d'un outil. Tout ceux qui ont fait du développement et de l'exploitation de système d'information comportant une base de données savent bien ce qu'implique une augmentation du volume de donnée traité. Un index mal placé ou non utilisé et les temps de réponses croissent au fil des jours pour arriver parfois à un blocage complet du système. Il est pourtant simple de se protéger de cela en effectuant en pré-production des tests de montée en charge afin de mesurer les temps de réponse en fonction du volume de donnée dans le système.

Lire la suite...

vendredi, octobre 11 2013

Présentations OSDCfr 2013

J'ai eu le plaisir d'être invité à présenter les tests de performance avec Tsung lors de la dernière session de l'OSDC fr à Paris, en attendant la vidéo qui sera publiée ultérieurement les diapositives de la présentation ont été publiées sur Slideshare.

mardi, mai 28 2013

Tsung 1.5.0

La version 1.5.0 de Tsung est sortie vendredi 24 mai (1), celle-ci corrige quelques bugs, améliore certain points et contient également des nouvelles fonctionnalités. Ci-dessous la liste de tous les tickets clos sur le bugtrack du projet (2), avec quelques bugfix/amélioration qui me semble important.

Dans les corrections de bugs on notera la correction des dynvars mal définies qui empêchait certain test sur des valeurs lues depuis des modules externes.

  • TSUN-208 - in the jabber plugin, substitutions for raw request doesn't work in some cases.
  • TSUN-209 - If tag doesn't work with Tsung 1.4.2
  • TSUN-212 - Incorrect ERTS version being set on build.
  • TSUN-215 - normal ack timeout shouldn't used for global ack
  • TSUN-217 - If statement breaks on empty string
  • TSUN-218 - Race condition in tsung-recorder
  • TSUN-219 - Site fails to load via proxy recorder
  • TSUN-220 - Large configuration files trigger error
  • TSUN-229 - compatibility with erlang R15B
  • TSUN-230 - can't connect with TLS + ejabberd
  • TSUN-232 - Tsung for bosh protocol doesn't send a empty request to keep the user session alive.
  • TSUN-234 - Error encoding json string with escape_uri
  • TSUN-238 - Content-Length parsing broken
  • TSUN-241 - Invalid link Other in the graph.html
  • TSUN-245 - Message when dtd is not found not trivial

Le format du fichier de dump se voit compléter de 2 nouveaux champs, la substitution dans les cookies est désormais supportée. La commande PATCH est maintenant supportée dans le protocole HTTP, et quelques autres, l'intégralité étant listées ci-dessous.

  • TSUN-174 - add an option to set resource in XMPP
  • TSUN-222 - Support unsubscribe operation for Jabber pubsub module
  • TSUN-228 - allow substitutions on cookies
  • TSUN-236 - Add probability support for servers
  • TSUN-242 - add timestamp and request duration in dump=protocol for http
  • TSUN-246 - http PATCH support

Dans les nouvelles fonctionnalités on notera plus particulièrement le support de BOSH pour le plugin Jabber et le nouveau plugin pour tester les serveurs de files de type AMQP. Il est désormais possible définit également un poids pour chaque session plutôt qu'un pourcentage. Un script perl est désormais inclus afin de calculer les percentile sur les temps de requêtes et de transaction.

  • TSUN-214 - Ability to pass attributes for node creation for XMPP pubsub protocol.
  • TSUN-227 - add new dynamic variable to get server hostname and port
  • TSUN-231 - add option to use weights instead of probabilities for sessions
  • TSUN-239 - add BOSH support
  • TSUN-240 - add websocket support
  • TSUN-244 - Percentile computation
  • TSUN-248 - add AMQP support

Egalement non listée un nouveau type pour les dynvars qui permet de définir une valeur directement sans passer par une évaluation de code.

Dans le fonctionnement interne on notera un changement de format pour ts_file_server, cela fera l'objet d'un autre billet qui proposera une méthode pour supporter la lecture de fichier .csv en 1.4.2 et 1.5.0

Je ne peux que vous encourager à passer à cette nouvelle version dès que possible.

jeudi, mai 23 2013

Modules externes dans Tsung

Une fonctionnalité aussi intéressante que puissante de Tsung est de permetre de générer des paramètres ou des urls depuis des modules externes écrits en erlang. La documentation (1) officielle indique que les modules doivent être déployés dans le répertoire ebin de Tsung qui est généralement un répertoire système non accessible en écriture aux utilisateurs non privilégiés. Il existe une méthode alternative pour ceux qui ne possèdent pas les permissions root sur leurs machines, cela consiste à indiquer le chemin des librairies au niveau erlang en déclarant la variable ERL_LIBS qui contiendra le nom du répertoire contenant vos modules. Les fichiers .beam seront copiés dans un répertoire nommé obligatoirement ebin qui sera placé dans le répertoire indiqué dans ERL_LIBS. A noter que l'on peut indiquer plusieurs répertoires en les séparant par des virgules comme souvent pour les PATH.

Exemple :

ERL_LIBS=/home/rodo/modules

Les fichiers .beam seront dans

/home/rodo/modules/ebin/

jeudi, avril 11 2013

Module tsung de coordonnées aléatoires

Après avoir traité le cas des numéros de tuiles aléatoires j'ai écrit un module de génération d'url géographiques aléatoires.

De nombreux services géographiques utilisent la syntaxe lat=X&lon=Y&zoom=Z dans leur interface, c'est ce cas de figure que va permettre de traiter le module wms_randomcoord présenté ici, le module génére automatiquement la partie lat,lon de l'url et ce de façon aléatoire. Son utilisation dans un scénario Tsung se fait au travers de l'appel de la fonction url/1.

<setdynvars sourcetype="erlang" callback="wms_randomcoord:url">
   <var name="lonlat" />
</setdynvars>

<request subst="true">
    <http url="/?%%_lonlat%%&amp;zoom=12" method="GET" version="1.1"/>
 </request>

Pour ajouter de l'aléatoire au niveau du zoom on pourra jouter une session dans le scénario où on le fera varier entre deux bornes finies.

<session name='zoomrandom' probability='90'  type='ts_http'>
  <setdynvars sourcetype="erlang" callback="wms_randomcoord:url">
    <var name="lonlat" />
  </setdynvars>

  <setdynvars sourcetype="random_number" start="1" end="18">
    <var name="zoom" />
  </setdynvars>

  <request subst="true">
    <http url="/?%%_lonlat%%&amp;zoom=%%_zoom%%" method="GET" version="1.1"/>
  </request>
</session>

Des scenarii d'exemples sont disponibles dans le dépôt github tsung-tricks, voir les fichiers lonlat.xml et lonlat2.xml.

jeudi, avril 4 2013

Test de charge sur un serveur de tuile

J'ai eu par le passé à effectuer des tests de charge sur des serveurs de tuiles comme ceux mis en oeuvre sur le projet OpenStreetMap. Afin d'assurer des requêtes aléatoires sur tous les niveaux de zoom j'avais écrit à l'époque un plugin pour Tsung que je n'avais pas encore pris le temps de publier, voilà qui est chose faite.

Le plugin se nomme wmsosm.erl et est publié sur github en licence GPLv3. Il permet de générer la partie finale de l'url en z/x/y afin de pouvoir l'intégrer dans la balise request du scénario Tsung. L'utilisation se fait en appelant la fonction urlzxy du module wmsosm, voir l'exemple ci-dessous. Le détail de la mise en oeuvre d'un plugin Tsung est décrit dans la [documentation du projet| http://tsung.erlang-projects.org/user_manual.html] je ne m'étendrais pas sur le sujet.

<request subst="true">
  <http url='/%%wmsosm:urlzxy%%.png' version='1.1' method='GET'></http>
</request>

Le choix de la tuile dans un niveau de zoom donné est aléatoire. le choix du niveau de zoom est aléatoire mais avec pondération, le choix est fait de telle sorte que les niveaus de zooms élevés sortent plus souvent, techniquement le tirage est fait dans une liste qui contient 2 fois le zoom 2, 3 fois le zoom 3 et ainsi de suite.

Ci-dessous un exemple d'un extrait d'utilisation du plugin

"GET /7/88/93.png HTTP/1.1"
"GET /16/17017/19589.png HTTP/1.1"
"GET /11/1791/1872.png HTTP/1.1"
"GET /17/47098/51507.png HTTP/1.1"
"GET /17/40683/45092.png HTTP/1.1"
"GET /17/47025/51434.png HTTP/1.1"
"GET /17/38091/42500.png HTTP/1.1"
"GET /3/4/4.png HTTP/1.1"
"GET /10/839/874.png HTTP/1.1"
"GET /15/6096/7382.png HTTP/1.1"
"GET /18/114432/123250.png HTTP/1.1"
"GET /18/139028/149316.png HTTP/1.1"
"GET /3/4/4.png HTTP/1.1"
"GET /16/17609/19814.png HTTP/1.1"
"GET /12/39/200.png HTTP/1.1"
"GET /18/129410/138228.png HTTP/1.1"
"GET /18/117680/126498.png HTTP/1.1"
"GET /4/9/9.png HTTP/1.1"
"GET /10/836/865.png HTTP/1.1"
"GET /6/40/42.png HTTP/1.1"

Je travaille sur une version améliorée du plugin afin de tirer des blocs aléatoires de tuiles plutôt que des tuiles uniques, ce qui se rapprochera plus des cas réels d'utilisation. On déterminera de façon aléatoire une première tuile et des requêtes seront générées de façon ordonnées dans un ensemble de tuiles voisines paramétrable.

mercredi, avril 3 2013

Créer un lot de User dans Django

Lors d'un récent test de charge sur une application Django j'ai eu à créer 10K utilisateurs pour tester la charge sur le processus de login. Ce besoin de création d'utilisateur de test étant récurrent j'ai écrit une commande manage (1) afin de créer facilement un grand nombre d'utilisateurs mais également de conserver leur id pour suppression ultérieure. La liste des ids est affichée sur stdout pour faire au plus simple.

Par défaut on crée 10 utilisateurs et on spécifie comme premier argument le nombre total souhaité.

Le code de la classe, simple et efficace :

"""                                                                                                       
Create users in batch                                                                                     
"""
import json
from django.core.management.base import BaseCommand
from django.contrib.auth.models import User

class Command(BaseCommand):
    help = 'Create test accounts'

    def handle(self, *args, **options):
        nb_accounts = 10
        mac = 0
        userids = []

        if len(args) > 0:
            nb_accounts = int(args[0])

        while mac < nb_accounts:
            username = 'tsung-%04d' % (mac)
            email = 'tsung-%04d@example.com' % (mac)
            password = 'password-%04d' % (mac)
            user = User.objects.create(username=username,
                                       email=email)
            user.set_password(password)
            user.save()
            userids.append(user.id)
            mac += 1

        print json.dumps(userids)