MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Écrivez votre premier conseiller

Vous êtes-vous déjà demandé ce qui déclenche l'avis dans ClusterControl indiquant que votre disque est en train de se remplir ? Ou le conseil de créer des clés primaires sur les tables InnoDB si elles n'existent pas ? Ces conseillers sont des mini scripts écrits dans le langage spécifique au domaine ClusterControl (DSL) qui est un langage de type Javascript. Ces scripts peuvent être écrits, compilés, enregistrés, exécutés et planifiés dans ClusterControl. C'est le sujet de la série de blogs ClusterControl Developer Studio.

Aujourd'hui, nous couvrirons les bases de Developer Studio et vous montrerons comment créer votre tout premier conseiller où nous choisirons deux variables de statut et donnerons des conseils sur leur résultat.

Les conseillers

Les conseillers sont des mini scripts qui sont exécutés par ClusterControl, soit à la demande, soit selon un calendrier. Il peut s'agir de simples conseils de configuration, d'avertissements sur les seuils ou de règles plus complexes pour les prédictions ou les tâches d'automatisation à l'échelle du cluster en fonction de l'état de vos serveurs ou bases de données. En général, les conseillers effectuent des analyses plus détaillées et produisent des recommandations plus complètes que les alertes.

Les conseillers sont stockés dans la base de données ClusterControl et vous pouvez ajouter de nouveaux conseillers ou modifier/modifier des conseillers existants. Nous avons également un référentiel Github de conseillers où vous pouvez partager vos conseillers avec nous et d'autres utilisateurs de ClusterControl.

Le langage utilisé pour les conseillers est le soi-disant ClusterControl DSL et est un langage facile à comprendre. La sémantique du langage peut être mieux comparée à Javascript avec quelques différences, où les différences les plus importantes sont :

  • Les points-virgules sont obligatoires
  • Divers types de données numériques comme les entiers et les entiers longs longs non signés
  • Les tableaux sont à deux dimensions et les tableaux à une dimension sont des listes.

Vous pouvez trouver la liste complète des différences dans la référence ClusterControl DSL.

L'interface du studio de développement

L'interface Developer Studio se trouve sous Cluster> Gérer> Developer Studio. Cela ouvrira une interface comme celle-ci :

Conseillers

Le bouton des conseillers générera un aperçu de tous les conseillers avec leur sortie depuis la dernière fois qu'ils ont été exécutés :

Vous pouvez également voir le planning du conseiller au format crontab et la date/heure depuis la dernière mise à jour. Certains conseillers ne sont programmés qu'une fois par jour pour que leurs conseils ne reflètent plus la réalité, par exemple si vous avez déjà résolu le problème pour lequel vous avez été averti. Vous pouvez relancer manuellement le conseiller en le sélectionnant et en l'exécutant. Allez à la section "compiler et exécuter" pour savoir comment procéder.

Conseillers en importation

Le bouton Importer vous permettra d'importer une archive contenant de nouveaux conseillers. L'archive doit être créée par rapport au chemin principal des conseillers, donc si vous souhaitez télécharger une nouvelle version du script de taille du cache de requête MySQL (s9s/mysql/query_cache/qc_size.js), vous devrez faire démarrer l'archive depuis le répertoire s9s.

Conseillers à l'exportation

Vous pouvez exporter les conseillers ou une partie d'entre eux en sélectionnant un nœud dans l'arborescence et en appuyant sur le bouton Exporter. Cela créera une archive tar avec les fichiers dans le chemin complet de la structure présentée. Supposons que nous souhaitions faire une sauvegarde des conseillers s9s/mysql avant d'apporter une modification, nous sélectionnons simplement le nœud s9s/mysql dans l'arborescence et appuyons sur Export :

Remarque :assurez-vous que le répertoire s9s est présent dans /home/myuser/.

Cela créera une archive appelée /home/myuser/s9s/mysql.tar.gz avec une structure de répertoire interne s9s/mysql/*

Créer un nouveau conseiller

Puisque nous avons couvert les exportations et les importations, nous pouvons maintenant commencer à expérimenter. Alors créons un nouveau conseiller ! Cliquez sur le bouton Nouveau pour obtenir la boîte de dialogue suivante :

Dans cette boîte de dialogue, vous pouvez créer votre nouveau conseiller avec un fichier vide ou le pré-remplir avec le modèle spécifique Galera ou MySQL. Les deux modèles ajouteront les inclusions nécessaires (common/mysql_helper.js) et les bases pour récupérer les nœuds Galera ou MySQL et les boucler.

La création d'un nouveau conseiller avec le modèle Galera ressemble à ceci :

#include "common/mysql_helper.js"

Ici, vous pouvez voir que mysql_helper.js est inclus pour fournir la base de connexion et d'interrogation des nœuds MySQL.

Ce fichier contient des fonctions que vous pouvez invoquer si besoin comme par exemple readVariable(,) qui vous permettra d'obtenir la valeur des variables globales ou invoquer readStatusVariable(,) qui vous permettra également pour obtenir les variables d'état globales dans MySQL. Ce fichier peut être situé dans l'arborescence comme indiqué ci-dessous :

var WARNING_THRESHOLD=0;
…
if(threshold > WARNING_THRESHOLD)

Le seuil d'avertissement est actuellement fixé à 0, ce qui signifie que si le seuil mesuré est supérieur au seuil d'avertissement, le conseiller doit avertir l'utilisateur. Notez que le seuil variable n'est pas encore défini/utilisé dans le modèle car il s'agit d'un coup de pouce pour votre propre conseiller.

var hosts     = cluster::Hosts();
var hosts     = cluster::mySqlNodes();
var hosts     = cluster::galeraNodes();

Les instructions ci-dessus récupèrent les hôtes du cluster et vous pouvez les utiliser pour les parcourir en boucle. La différence entre eux est que la première instruction inclut tous les hôtes non-MySQL (également l'hôte CMON), la seconde tous les hôtes MySQL et la dernière uniquement les hôtes Galera. Ainsi, si votre cluster Galera est associé à des esclaves de lecture asynchrones MySQL, ces hôtes ne seront pas inclus.

En dehors de cela, ces objets se comporteront tous de la même manière et auront la possibilité de lire leurs variables, leur statut et leur requête.

Boutons du conseiller

Maintenant que nous avons créé un nouveau conseiller, six nouveaux boutons sont disponibles pour ce conseiller :

Enregistrer enregistrera vos dernières modifications dans le conseiller (stockées dans la base de données CMON), Déplacer déplacera le conseiller vers un nouveau chemin et supprimera supprimera évidemment le conseiller.

Plus intéressant est la deuxième rangée de boutons. La compilation du conseiller compilera le code du conseiller. Si le code se compile bien, vous verrez ce message dans les Messages dialogue sous le code du conseiller :

Alors que si la compilation a échoué, le compilateur vous donnera un indice où il a échoué :

Dans ce cas, le compilateur indique qu'une erreur de syntaxe a été trouvée à la ligne 24.

Le compiler et exécuter non seulement compilera le script mais l'exécutera également et sa sortie sera affichée dans la boîte de dialogue Messages, Graph ou Raw. Si nous compilons et exécutons le script de cache de table à partir des auto_tuners, nous obtiendrons une sortie similaire à celle-ci :

Le dernier bouton est le planning bouton. Cela vous permet de programmer (ou déprogrammer) vos conseillers et d'y ajouter des balises. Nous en parlerons à la fin de cet article lorsque nous aurons créé notre propre conseiller et que nous voudrons le planifier.

Mon premier conseiller

Maintenant que nous avons couvert les bases de ClusterControl Developer Studio, nous pouvons enfin commencer à créer un nouveau conseiller. À titre d'exemple, nous allons créer un conseiller pour examiner le ratio de la table temporaire. Créez un nouveau conseiller comme suit :

La théorie derrière le conseiller que nous allons créer est simple :nous allons comparer le nombre de tables temporaires créées sur disque au nombre total de tables temporaires créées :

tmp_disk_table_ratio = Created_tmp_disk_tables / (Created_tmp_tables + Created_tmp_disk_tables) * 100;

Nous devons d'abord définir certaines bases dans l'en-tête du script, comme les seuils et les messages d'avertissement et ok. Tous les changements et ajouts sont appliqués ci-dessous :

var WARNING_THRESHOLD=20;
var TITLE="Temporary tables on disk ratio";
var ADVICE_WARNING="More than 20% of temporary tables are written to disk. It is advised to review your queries, for example, via the Query Monitor.";
var ADVICE_OK="Temporary tables on disk are not excessive." ;

Nous fixons ici le seuil à 20%, ce qui est déjà considéré comme assez mauvais. Mais plus sur ce sujet une fois que nous aurons finalisé notre conseiller.

Ensuite, nous devons obtenir ces variables d'état à partir de MySQL. Avant de sauter aux conclusions et d'exécuter une requête "SHOW GLOBAL STATUS LIKE 'Created_tmp_%'", il existe déjà une fonction pour récupérer la variable de statut d'une instance MySQL, comme ce que nous avons décrit ci-dessus où cette fonction est située dans common/mysql_helper. js :

statusVar = readStatusVariable(<host>, <statusvariablename>);

Nous pouvons utiliser cette fonction dans notre conseiller pour récupérer les tables Created_tmp_disk_tables et Created_tmp_tables.

    for (idx = 0; idx < hosts.size(); ++idx)
    {
        host        = hosts[idx];
        map         = host.toMap();
        connected     = map["connected"];
        var advice = new CmonAdvice();
        var tmp_tables = readStatusVariable(host, ‘Created_tmp_tables’);
        var tmp_disk_tables = readStatusVariable(host, ‘Created_tmp_disk_tables’);

Et maintenant, nous pouvons calculer le ratio des tables de disques temporaires :

        var tmp_disk_table_ratio = tmp_disk_tables / (tmp_tables + tmp_disk_tables) * 100;

Et alertez si ce ratio est supérieur au seuil que nous avons fixé au départ :

        if(checkPrecond(host))
        {
           if(tmp_disk_table_ratio > WARNING_THRESHOLD) {
               advice.setJustification("Temporary tables written to disk is excessive");
               msg = ADVICE_WARNING;
           }
           else {
               advice.setJustification("Temporary tables written to disk not excessive");
               msg = ADVICE_OK;
           }
        }

Il est important d'assigner l'avis à la variable msg ici car cela sera ajouté plus tard dans l'objet d'avis avec la fonction setAdvice(). Le script complet pour être complet :

#include "common/mysql_helper.js"

/**
 * Checks the percentage of max ever used connections 
 * 
 */ 
var WARNING_THRESHOLD=20;
var TITLE="Temporary tables on disk ratio";
var ADVICE_WARNING="More than 20% of temporary tables are written to disk. It is advised to review your queries, for example, via the Query Monitor.";
var ADVICE_OK="Temporary tables on disk are not excessive.";

function main()
{
    var hosts     = cluster::mySqlNodes();
    var advisorMap = {};

    for (idx = 0; idx < hosts.size(); ++idx)
    {
        host        = hosts[idx];
        map         = host.toMap();
        connected     = map["connected"];
        var advice = new CmonAdvice();
        var tmp_tables = readStatusVariable(host, 'Created_tmp_tables');
        var tmp_disk_tables = readStatusVariable(host, 'Created_tmp_disk_tables');
        var tmp_disk_table_ratio = tmp_disk_tables / (tmp_tables + tmp_disk_tables) * 100;
        
        if(!connected)
            continue;
        if(checkPrecond(host))
        {
           if(tmp_disk_table_ratio > WARNING_THRESHOLD) {
               advice.setJustification("Temporary tables written to disk is excessive");
               msg = ADVICE_WARNING;
               advice.setSeverity(0);
           }
           else {
               advice.setJustification("Temporary tables written to disk not excessive");
               msg = ADVICE_OK;
           }
        }
        else
        {
            msg = "Not enough data to calculate";
            advice.setJustification("there is not enough load on the server or the uptime is too little.");
            advice.setSeverity(0);
        }
        advice.setHost(host);
        advice.setTitle(TITLE);
        advice.setAdvice(msg);
        advisorMap[idx]= advice;
    }
    return advisorMap;
}

Maintenant, vous pouvez jouer avec le seuil de 20, essayer de l'abaisser à 1 ou 2 par exemple et vous pourrez alors probablement voir comment ce conseiller vous donnera des conseils sur la question.

Comme vous pouvez le voir, avec un simple script, vous pouvez vérifier deux variables l'une par rapport à l'autre et rapporter/conseiller en fonction de leur résultat. Mais est-ce tout ? Il y a encore quelques choses que nous pouvons améliorer !

Améliorations sur mon premier conseiller

La première chose que nous pouvons améliorer est que ce conseiller n'a pas beaucoup de sens. Ce que la métrique reflète réellement est le nombre total de tables temporaires sur le disque depuis le dernier FLUSH STATUS ou le dernier démarrage de MySQL. Ce qu'il ne dit pas, c'est à quel taux il crée en fait des tables temporaires sur le disque. Nous pouvons donc convertir les Created_tmp_disk_tables en un taux utilisant la disponibilité de l'hôte :

    var tmp_disk_table_rate = tmp_disk_tables / uptime;

Cela devrait nous donner le nombre de tables temporaires par seconde et combiné avec le tmp_disk_table_ratio, cela nous donnera une vision plus précise des choses. Encore une fois, une fois que nous atteignons le seuil de deux tables temporaires par seconde, nous ne voulons pas envoyer immédiatement une alerte/un conseil.

Une autre chose que nous pouvons améliorer est de ne pas utiliser la fonction readStatusVariable(, ) de la bibliothèque common/mysql_helper.js. Cette fonction exécute une requête à l'hôte MySQL chaque fois que nous lisons une variable d'état, alors que CMON récupère déjà la plupart d'entre eux chaque seconde et nous n'avons de toute façon pas besoin d'un état en temps réel. Ce n'est pas comme si deux ou trois requêtes tuaient les hôtes du cluster, mais si bon nombre de ces conseillers sont exécutés de la même manière, cela pourrait créer des tas de requêtes supplémentaires.

Dans ce cas, nous pouvons optimiser cela en récupérant les variables d'état dans une carte à l'aide de la fonction host.sqlInfo() et en récupérant tout en même temps sous forme de carte. Cette fonction contient les informations les plus importantes de l'hôte, mais elle ne contient pas toutes. Par exemple, la disponibilité variable dont nous avons besoin pour le taux n'est pas disponible dans la carte host.sqlInfo() et doit être récupérée avec la fonction readStatusVariable(, ).

Voici à quoi ressemblera notre conseiller maintenant, avec les modifications/ajouts marqués en gras :

#include "common/mysql_helper.js"

/**
 * Checks the percentage of max ever used connections 
 * 
 */ 
var RATIO_WARNING_THRESHOLD=20;
var RATE_WARNING_THRESHOLD=2;
var TITLE="Temporary tables on disk ratio";
var ADVICE_WARNING="More than 20% of temporary tables are written to disk and current rate is more than 2 temporary tables per second. It is advised to review your queries, for example, via the Query Monitor.";
var ADVICE_OK="Temporary tables on disk are not excessive.";

function main()
{
    var hosts     = cluster::mySqlNodes();
    var advisorMap = {};

    for (idx = 0; idx < hosts.size(); ++idx)
    {
        host        = hosts[idx];
        map         = host.toMap();
        connected     = map["connected"];
        var advice = new CmonAdvice();
        var hostStatus = host.sqlInfo();
        var tmp_tables = hostStatus['CREATED_TMP_TABLES'];
        var tmp_disk_tables = hostStatus['CREATED_TMP_DISK_TABLES'];
        var uptime = readStatusVariable(host, 'uptime');
        var tmp_disk_table_ratio = tmp_disk_tables / (tmp_tables + tmp_disk_tables) * 100;
        var tmp_disk_table_rate = tmp_disk_tables / uptime;
        
        if(!connected)
            continue;
        if(checkPrecond(host))
        {
           if(tmp_disk_table_rate > RATE_WARNING_THRESHOLD && tmp_disk_table_ratio > RATIO_WARNING_THRESHOLD) {
               advice.setJustification("Temporary tables written to disk is excessive: " + tmp_disk_table_rate + " tables per second and overall ratio of " + tmp_disk_table_ratio);
               msg = ADVICE_WARNING;
               advice.setSeverity(0);
           }
           else {
               advice.setJustification("Temporary tables written to disk not excessive");
               msg = ADVICE_OK;
           }
        }
        else
        {
            msg = "Not enough data to calculate";
            advice.setJustification("there is not enough load on the server or the uptime is too little.");
            advice.setSeverity(0);
        }
        advice.setHost(host);
        advice.setTitle(TITLE);
        advice.setAdvice(msg);
        advisorMap[idx]= advice;
    }
    return advisorMap;
}

Planifier mon premier conseiller

Après avoir enregistré ce nouveau conseiller, l'avoir compilé et exécuté, nous pouvons maintenant planifier ce conseiller. Comme nous n'avons pas de charge de travail excessive, nous exécuterons probablement ce conseiller une fois par jour.

Le mode de planification de base est similaire à Cron qui a toutes les minutes, 5 minutes, heure, jour, mois prédéfinis et c'est exactement ce dont nous avons besoin et il est très facile de gérer la planification. Le changer en avancé déverrouillera les autres champs de saisie grisés. Ces champs de saisie fonctionnent exactement de la même manière qu'un crontab, vous pouvez donc même programmer un jour particulier, un jour du mois ou même le définir en semaine.

Suite à ce blog, nous créerons un vérificateur pour SELinux ou des contrôles de sécurité pour Spectre et Meltdown si les nœuds sont affectés. Restez à l'écoute !