MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Schreiben Sie Ihren ersten Berater

Haben Sie sich jemals gefragt, was den Hinweis in ClusterControl auslöst, dass Ihre Festplatte voll wird? Oder der Rat, Primärschlüssel für InnoDB-Tabellen zu erstellen, wenn sie nicht existieren? Diese Advisors sind Miniskripts, die in der ClusterControl Domain Specific Language (DSL) geschrieben sind, einer Javascript-ähnlichen Sprache. Diese Skripte können in ClusterControl geschrieben, kompiliert, gespeichert, ausgeführt und terminiert werden. Darum geht es in der ClusterControl Developer Studio-Blogserie.

Heute behandeln wir die Grundlagen von Developer Studio und zeigen Ihnen, wie Sie Ihren allerersten Ratgeber erstellen, in dem wir zwei Statusvariablen auswählen und Ratschläge zu deren Ergebnis geben.

Die Berater

Advisors sind Mini-Skripte, die von ClusterControl entweder bei Bedarf oder nach einem Zeitplan ausgeführt werden. Dies kann alles sein, von einfachen Konfigurationshinweisen, Warnungen zu Schwellenwerten oder komplexeren Regeln für Vorhersagen bis hin zu clusterweiten Automatisierungsaufgaben, die auf dem Status Ihrer Server oder Datenbanken basieren. Im Allgemeinen führen Berater detailliertere Analysen durch und erstellen umfassendere Empfehlungen als Warnungen.

Die Berater werden in der ClusterControl-Datenbank gespeichert und Sie können neue hinzufügen oder bestehende Berater ändern/modifizieren. Wir haben auch ein Github-Repository für Berater, in dem Sie Ihre Berater mit uns und anderen ClusterControl-Benutzern teilen können.

Die für die Berater verwendete Sprache ist die sogenannte ClusterControl DSL und ist eine leicht verständliche Sprache. Die Semantik der Sprache lässt sich mit ein paar Unterschieden am besten mit Javascript vergleichen, wobei die wichtigsten Unterschiede sind:

  • Semikolons sind obligatorisch
  • Verschiedene numerische Datentypen wie Ganzzahlen und unsigned long long integers.
  • Arrays sind zweidimensional und eindimensionale Arrays sind Listen.

Die vollständige Liste der Unterschiede finden Sie in der ClusterControl DSL-Referenz.

Die Developer Studio-Oberfläche

Die Developer Studio-Oberfläche finden Sie unter Cluster> Manage> Developer Studio. Dies öffnet eine Schnittstelle wie diese:

Berater

Die Schaltfläche „Berater“ generiert eine Übersicht aller Berater mit ihren Ergebnissen seit ihrer letzten Ausführung:

Sie können auch den Zeitplan des Beraters im Crontab-Format und das Datum/die Uhrzeit seit der letzten Aktualisierung sehen. Einige Ratgeber werden nur einmal am Tag ausgeführt, sodass ihre Ratschläge möglicherweise nicht mehr der Realität entsprechen, z. B. wenn Sie das Problem, vor dem Sie gewarnt wurden, bereits gelöst haben. Sie können den Advisor manuell erneut ausführen, indem Sie den Advisor auswählen und ausführen. Gehen Sie zum Abschnitt „Kompilieren und Ausführen“, um zu erfahren, wie das geht.

Berater importieren

Mit der Schaltfläche Import können Sie einen Tarball mit neuen Advisors darin importieren. Der Tarball muss relativ zum Hauptpfad der Advisor erstellt werden. Wenn Sie also eine neue Version des Skripts für die Größe des MySQL-Abfrage-Cache (s9s/mysql/query_cache/qc_size.js) hochladen möchten, müssen Sie den Tarball starten aus dem s9s-Verzeichnis.

Exportberater

Sie können die Berater oder einen Teil davon exportieren, indem Sie einen Knoten in der Baumstruktur auswählen und auf die Schaltfläche Exportieren klicken. Dadurch wird ein Tarball mit den Dateien im vollständigen Pfad der präsentierten Struktur erstellt. Angenommen, wir möchten eine Sicherungskopie der s9s/mysql-Berater erstellen, bevor wir eine Änderung vornehmen, wählen wir einfach den s9s/mysql-Knoten in der Baumstruktur aus und drücken Exportieren:

Hinweis:Stellen Sie sicher, dass das s9s-Verzeichnis in /home/myuser/ vorhanden ist.

Dadurch wird ein Tarball namens /home/myuser/s9s/mysql.tar.gz mit einer internen Verzeichnisstruktur s9s/mysql/*

erstellt

Erstellen eines neuen Beraters

Da wir Exporte und Importe abgedeckt haben, können wir jetzt mit dem Experimentieren beginnen. Erstellen wir also einen neuen Berater! Klicken Sie auf die Schaltfläche Neu, um den folgenden Dialog zu erhalten:

In diesem Dialog können Sie Ihren neuen Berater entweder mit einer leeren Datei erstellen oder ihn mit der Galera- oder MySQL-spezifischen Vorlage vorbefüllen. Beide Vorlagen fügen die notwendigen Includes (common/mysql_helper.js) und die Grundlagen hinzu, um die Galera- oder MySQL-Knoten abzurufen und sie zu durchlaufen.

Das Erstellen eines neuen Beraters mit der Galera-Vorlage sieht folgendermaßen aus:

#include "common/mysql_helper.js"

Hier können Sie sehen, dass mysql_helper.js eingebunden wird, um die Grundlage für die Verbindung und Abfrage von MySQL-Knoten bereitzustellen.

Diese Datei enthält Funktionen, die Sie bei Bedarf aufrufen können, wie zum Beispiel readVariable(,), die es Ihnen ermöglichen, den Wert der globalen Variablen abzurufen, oder readStatusVariable(,) aufrufen, was Ihnen ebenfalls erlaubt um die globalen Statusvariablen in MySQL zu erhalten. Diese Datei kann wie unten gezeigt im Baum lokalisiert werden:

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

Der Warnschwellenwert ist derzeit auf 0 eingestellt, was bedeutet, dass der Berater den Benutzer warnen sollte, wenn der gemessene Schwellenwert größer als der Warnschwellenwert ist. Beachten Sie, dass der variable Schwellenwert noch nicht in der Vorlage festgelegt/verwendet wird, da dies ein Kickstart für Ihren eigenen Berater ist.

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

Die obigen Anweisungen rufen die Hosts im Cluster ab, und Sie können diese verwenden, um sie zu durchlaufen. Der Unterschied zwischen ihnen besteht darin, dass die erste Anweisung alle Nicht-MySQL-Hosts (auch den CMON-Host), die zweite alle MySQL-Hosts und die letzte nur enthält die Galera-Gastgeber. Wenn Ihr Galera-Cluster also asynchrone MySQL-Lese-Slaves angehängt hat, werden diese Hosts nicht eingeschlossen.

Abgesehen davon verhalten sich diese Objekte alle gleich und verfügen über die Fähigkeit, ihre Variablen und ihren Status zu lesen und sie abzufragen.

Berater-Schaltflächen

Nachdem wir nun einen neuen Berater erstellt haben, stehen sechs neue Schaltflächen für diesen Berater zur Verfügung:

Speichern speichert Ihre letzten Änderungen im Advisor (gespeichert in der CMON-Datenbank), Move verschiebt den Berater in einen neuen Pfad und Entfernen wird den Berater natürlich entfernen.

Interessanter ist die zweite Tastenreihe. Das Kompilieren des Advisors wird den Code des Advisors kompilieren. Wenn der Code gut kompiliert wird, sehen Sie diese Nachricht in den Nachrichten Dialog unter dem Code des Beraters:

Wenn die Kompilierung fehlgeschlagen ist, gibt Ihnen der Compiler einen Hinweis, wo es fehlgeschlagen ist:

In diesem Fall zeigt der Compiler in Zeile 24 an, dass ein Syntaxfehler gefunden wurde.

Das kompilieren und ausführen Die Schaltfläche kompiliert das Skript nicht nur, sondern führt es auch aus, und seine Ausgabe wird im Dialogfeld „Meldungen“, „Graph“ oder „Raw“ angezeigt. Wenn wir das Tabellen-Cache-Skript von den auto_tuners kompilieren und ausführen, erhalten wir eine Ausgabe ähnlich der folgenden:

Die letzte Schaltfläche ist der Zeitplan Taste. Auf diese Weise können Sie Ihre Berater planen (oder entplanen) und Tags hinzufügen. Wir werden dies am Ende dieses Beitrags behandeln, wenn wir unseren eigenen Berater erstellt haben und ihn planen möchten.

Mein erster Berater

Nachdem wir nun die Grundlagen des ClusterControl Developer Studio behandelt haben, können wir nun endlich damit beginnen, einen neuen Advisor zu erstellen. Als Beispiel werden wir einen Ratgeber erstellen, um das temporäre Tabellenverhältnis zu betrachten. Erstellen Sie wie folgt einen neuen Berater:

Die Theorie hinter dem Advisor, den wir erstellen werden, ist einfach:Wir vergleichen die Anzahl der auf der Festplatte erstellten temporären Tabellen mit der Gesamtzahl der erstellten temporären Tabellen:

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

Zuerst müssen wir einige Grundlagen im Kopf des Skripts festlegen, wie die Schwellenwerte und die Warn- und Ok-Meldungen. Alle Änderungen und Ergänzungen werden unten angewendet:

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." ;

Wir setzen die Schwelle hier auf 20 Prozent, was schon ziemlich schlecht ist. Aber dazu mehr, sobald wir unseren Berater fertiggestellt haben.

Als nächstes müssen wir diese Statusvariablen von MySQL abrufen. Bevor wir voreilige Schlüsse ziehen und eine „SHOW GLOBAL STATUS LIKE 'Created_tmp_%'“-Abfrage ausführen, gibt es bereits eine Funktion zum Abrufen der Statusvariablen einer MySQL-Instanz, wie oben beschrieben, wo sich diese Funktion in common/mysql_helper befindet. js:

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

Wir können diese Funktion in unserem Ratgeber verwenden, um die Created_tmp_disk_tables und Created_tmp_tables abzurufen.

    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’);

Und jetzt können wir das Verhältnis der temporären Festplattentabellen berechnen:

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

Und warnen Sie, wenn dieses Verhältnis größer als der Schwellenwert ist, den wir am Anfang festgelegt haben:

        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;
           }
        }

Es ist wichtig, den Hinweis hier der Variablen msg zuzuweisen, da dieser später mit der Funktion setAdvice() in das Hinweisobjekt eingefügt wird. Der Vollständigkeit halber das vollständige Skript:

#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;
}

Jetzt können Sie mit der Schwelle von 20 herumspielen, versuchen, sie zum Beispiel auf 1 oder 2 zu senken, und dann können Sie wahrscheinlich sehen, wie dieser Berater Sie in dieser Angelegenheit tatsächlich beraten wird.

Wie Sie sehen können, können Sie mit einem einfachen Skript zwei Variablen gegeneinander prüfen und basierend auf ihrem Ergebnis Berichte/Ratschläge erstellen. Aber ist das alles? Es gibt noch ein paar Dinge, die wir verbessern können!

Verbesserungen an meinem ersten Berater

Das erste, was wir verbessern können, ist, dass dieser Ratgeber nicht viel Sinn macht. Was die Metrik tatsächlich widerspiegelt, ist die Gesamtzahl der temporären Tabellen auf der Festplatte seit dem letzten FLUSH STATUS oder dem letzten Start von MySQL. Was es nicht sagt, ist zu welcher Rate es erstellt tatsächlich temporäre Tabellen auf der Festplatte. So können wir die Created_tmp_disk_tables anhand der Betriebszeit des Hosts in eine Rate umwandeln:

    var tmp_disk_table_rate = tmp_disk_tables / uptime;

Dies sollte uns die Anzahl der temporären Tabellen pro Sekunde geben und in Kombination mit tmp_disk_table_ratio wird uns dies eine genauere Sicht auf die Dinge geben. Auch hier möchten wir, sobald wir den Schwellenwert von zwei temporären Tabellen pro Sekunde erreichen, nicht sofort eine Warnung/einen Rat versenden.

Eine andere Sache, die wir verbessern können, ist, die Funktion readStatusVariable(, ) aus der Bibliothek common/mysql_helper.js nicht zu verwenden. Diese Funktion führt jedes Mal, wenn wir eine Statusvariable lesen, eine Abfrage an den MySQL-Host aus, während CMON die meisten davon bereits jede Sekunde abruft und wir sowieso keinen Echtzeitstatus benötigen. Es ist nicht so, dass zwei oder drei Abfragen die Hosts im Cluster töten, aber wenn viele dieser Advisors auf ähnliche Weise ausgeführt werden, könnte dies zu einer Menge zusätzlicher Abfragen führen.

In diesem Fall können wir dies optimieren, indem wir die Statusvariablen in einer Karte mit der Funktion host.sqlInfo() abrufen und alles auf einmal als Karte abrufen. Diese Funktion enthält die wichtigsten Informationen des Gastgebers, aber nicht alle. Beispielsweise ist die Variable uptime, die wir für die Rate benötigen, nicht in der host.sqlInfo()-Map verfügbar und muss mit der Funktion readStatusVariable(, ) abgerufen werden.

So sieht unser Ratgeber jetzt aus, wobei die Änderungen/Ergänzungen fett markiert sind:

#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;
}

Planung meines ersten Beraters

Nachdem wir diesen neuen Ratgeber gespeichert, kompiliert und ausgeführt haben, können wir diesen Ratgeber jetzt einplanen. Da wir keine übermäßige Arbeitsbelastung haben, werden wir diesen Ratgeber wahrscheinlich einmal täglich ausführen.

Der Basis-Planungsmodus ähnelt Cron, der jede Minute, 5 Minuten, Stunde, Tag, Monat voreingestellt hat, und das ist genau das, was wir brauchen, und es ist sehr einfach, die Planung zu verwalten. Wenn Sie dies auf Erweitert ändern, werden die anderen ausgegrauten Eingabefelder entsperrt. Diese Eingabefelder funktionieren genauso wie ein Crontab, sodass Sie sogar für einen bestimmten Tag, Tag des Monats oder sogar Wochentage planen können.

Im Anschluss an diesen Blog werden wir einen Checker für SELinux oder Sicherheitschecks für Spectre und Meltdown erstellen, wenn Nodes betroffen sind. Bleiben Sie dran!