Feather Background Waves Background
Aller au contenu
Feather Background Waves Background
Feather Background Waves Background
  1. JMeter en Français/

Utilisateurs aléatoires Uniques

intermédiaire - This article is part of a series.

usuarios

Bonjour à tous, après une absence sans écriture de blog sur le blog, nous sommes revenus. Cette fois-ci je partagerai avec vous une solution à un des problèmes les plus courants lorsqu’on exécute des tests de charge ou de stress : éviter les collisions de données par des sessions concurrentes d’utilisateurs. Allons-en maintenant en détail expliquant le problème et notre solution élégante, car ce que nous cherchons généralement est une rotation régulière de la donnée de test pour éviter l’internal cache.

Hypothèses:>

Hypothèses: #

  1. Nous avons une épreuve de charge avec 100 utilisateurs concurrents.
  2. Nous devons entre 2 et 3 fois plus d’informations pour éviter le caching, entre 200 et 300 utilisateurs différents.
  3. Les noms d’utilisateurs et les mots de passe devraient préférablement suivre un modèle.

Pour cette exemple, nous effectuerons une épreuve de charge avec 100 utilisateurs concurrents, qui peut facilement être étendu à 1,000 ou 10,000. Le test d’informations nécessaires pour éviter la cache dans le serveur application ou la base de données est de 2 à 3 fois, donc nous devons au moins 200 ou 300 informations de test ou pseudonymes. Enfin, pour que ce schéma fonctionne parfaitement, il faut que les noms d’utilisateurs aient une forme et qu’ils soient tous identiques, comme user001, user002,…,user299,user300. Par conséquent, la forme serait user + nombre aléatoire, bien sûr ce nombre aléatoire devrait être un chiffre entre 1 et 300 avec une mask pour ajouter des zéros à gauche pour compléter le format de la forme.

Alors nous avons une expérience aléatoire expérimentale pour obtenir 100 nombres aléatoires, avec un espace de sample de 300 (S={1,2,…,299,300}) et un événement ou résultat d’obtenir ces valeurs pour les utilisateurs de signer. Si l’application permet des sessions multiples, nous pourrions avoir moins de problèmes, car il est valide d’utiliser le même compte plusieurs fois pour signer. Sinon, si non autorisé à utiliser plusieurs sessions, ce serait un problème. Parce que lorsque générer 100 nombres aléatoires, la probabilité d’obtenir des valeurs uniques de l’espace de sample diminue en cours de suite des événements. Ainsi, il est nécessaire d’implémenter une mécanique pour éviter les collisions ou le problème de carrera pour notre test.

Si nous sélectionnons aléatoirement un nombre entre 1 et 300, la probabilité de l’obtention de ce nombre est P(1/300) ou 0.33%, mais pour le deuxième événement, il y a une probabilité croissante d’obtenir cette valeur à répétition avec l’avancement, la probabilité de l’obtention de valeurs uniques diminue car les nombres pseudo-aléatoires générés sont uniformément distribués et par conséquent on peut maintenir que la uniformité dans une certaine itération sera remplacée par un nombre aléatoire répété, par exemple, le premier nombre aléatoire est égal à 344, mais dans l’itération 450, nous obtenons de nouveau cette valeur, donc elles ne sont pas uniques et irréprochables.

Comment éviterons-nous ce problème ?>

Comment éviterons-nous ce problème ? #

La solution est plus facile que vous ne le pensez et facilement scalable si vous utilisez plusieurs generateurs de charge, nous allons d’abord résoudre l’initial problème. La solution consiste à générer une structure de données dans laquelle nous pouvons stocker ces valeurs aléatoires et continuer à les générer jusqu’à obtenir le nombre désiré. Une fois que nous avons obtenu les valeurs suivantes, nous vérifierons si cette valeur existe dans la structure ou non ; si elle n’existe pas, nous l’introduisons, sinon nous l’enleverons et continuons jusqu’à obtenir la quantité nécessaire. Aujourd’hui, cela doit être fait entre chaque itération de la série de threads pour que nous puissions garantir que sur la première itération de la série de threads certaines valeurs aléatoires ont été utilisées, et dans les itérations ou les itérations suivantes, une nouvelle série de valeurs aléatoires complètement neuves sera utilisée.

Le code suivant est documenté pour faciliter la lecture ; il devrait être placé dans un pré-processeur JSR223 sur la première requête de notre script.

ArrayList<Integer> Utilisateurs = new ArrayList<Integer>()         //Liste des utilisateurs
int obtenirIteration = vars.getIteration().toInteger()          //État actuel de l'itération du groupe de thread
Random generateurAleatoire = new Random() 
def itération = props.get("iteration")                           //Propriété pour stocker les itérations
def getUtilisateurs = props.get("Utilisateurs")                  //Propriété pour stocker la liste des utilisateurs
                                                            //Nous utilisons def si nous pouvons obtenir des valeurs NULL
int aleatoire                                                  //Valeur actuelle de l'aléatoire
if (itération == null || itération < getIteration || getUsers().size() < 1) {    //Nous validons si l'itération est null
                                                                                //Que la liste a au moins un élément
        while (Users.size() <= n) {                                             //Taille minimale de la liste
                                                                            // N premiers éléments
        RandUser = randomGenerator.nextInt(n)                               //Générer le nombre aléatoire entre 1 et n
        if (!Users.contains(RandUser)) {                                    //Si le valeur n'est pas dans l'array
            Users.add(RandUser)                                             //Introduire la valeur
        }
}
itération = getIteration                            //Faire de la itération actuelle
props.put("itération",itération)                    //Enregistrer l'itération globale
props.put("Users",Users)                            //Enregistrer la liste globale
log.info("Users: "+props.get("Users").toString())   //Afficher la liste dans le log
}

Une fois que nous avons la liste des valeurs, il ne reste plus qu’à attribuer à chaque thread sa valeur correspondante. Cela peut également être fait via un autre pré-processeur JSR223 dans lequel on assigne la valeur de la liste à une variable locale car rappelons que cette liste est stockée en tant que propriété d’une variable globale.

int threadNum = ctx.getThreadNum().toInteger()
def getUsers = props.get("Users")
vars.put("User",getUsers[threadNum].toString())

Prêt dans la variable Users, accessible via ${User}, nous pouvons remplacer le valeur par un nombre aléatoire non répété. Cette solution est bien meilleure que d’utiliser des fichiers CSV, car l’accès à l’information n’est jamais séquentiel, même si on parle de la base de données. Et cela donne une simplicité et une élégance à nos scripts.

Vous pouvez laisser un lien pour télécharger le script d’exemple ici.

script

Conclusion et Scalabilité>

Conclusion et Scalabilité #

Pour la finalisation, cette mécanique est facilement scalable à générateur de charge avec jusqu’à 1,000 utilisateurs par générateur de charge, mais pour éviter les collisions entre plusieurs générateurs de charge, il suffit simplement d’assigner à chaque un index unique. Par conséquent, le premier générateur de charge serait assigné la valeur de 0 et ainsi de suite jusqu’à la valeur de n. Pour assurer que le générateur de charge avec l’index 0 gère les premiers 2,000 ou 3,000 valeurs en exécutant seulement 1,000 utilisateurs concurrents, comme illustré ci-dessous :

GénérateurConcurrents ActuelsIntervalle
01,0000 - 3,000
11,0003k - 6k
21,0006k - 9k
31,0009k - 12k
n1,000nk

Cela est possible via une exécution centralisée ou décentralisée, de manière que ma recommandation est d’utiliser un propriété dans le fichier users.properties de chaque générateur de chargement avec l’objectif de manuellement attribuer ces valeurs, et à travers la JSR223 en groovy, utiliser cette valeur de propriété comme facteur multiplicateur pour les intervalles.



intermédiaire - This article is part of a series.