sql >> Databáze >  >> NoSQL >> MongoDB

Napište svého prvního poradce

Napadlo vás někdy, co spouští radu v ClusterControl, že se váš disk zaplňuje? Nebo radu vytvořit primární klíče v tabulkách InnoDB, pokud neexistují? Tito poradci jsou mini skripty napsané v jazyce ClusterControl Domain Specific Language (DSL), což je jazyk podobný Javascriptu. Tyto skripty lze psát, kompilovat, ukládat, spouštět a plánovat v ClusterControl. O tom bude série blogů ClusterControl Developer Studio.

Dnes si probereme základy Developer Studio a ukážeme vám, jak vytvořit svého úplně prvního poradce, kde vybereme dvě stavové proměnné a poskytneme rady ohledně jejich výsledku.

Poradci

Poradci jsou mini skripty, které spouští ClusterControl, buď na vyžádání, nebo podle plánu. Mohou to být cokoli od jednoduchých konfiguračních rad, upozornění na prahové hodnoty nebo složitějších pravidel pro předpovědi nebo úloh automatizace v celém clusteru na základě stavu vašich serverů nebo databází. Obecně platí, že poradci provádějí podrobnější analýzy a vytvářejí komplexnější doporučení než upozornění.

Poradci jsou uloženi v databázi ClusterControl a můžete přidávat nové nebo měnit/upravovat stávající poradce. Máme také poradní úložiště Github, kde můžete sdílet své poradce s námi a dalšími uživateli ClusterControl.

Jazyk používaný pro poradce je tzv. ClusterControl DSL a je snadno srozumitelným jazykem. Sémantiku jazyka lze nejlépe přirovnat k Javascriptu s několika rozdíly, kde nejdůležitější rozdíly jsou:

  • Středníky jsou povinné
  • Různé číselné datové typy, jako jsou celá čísla a dlouhá dlouhá celá čísla bez znaménka.
  • Pole jsou dvourozměrná a jednorozměrná pole jsou seznamy.

Úplný seznam rozdílů naleznete v referenci ClusterControl DSL.

Rozhraní Developer Studio

Rozhraní Developer Studio najdete v části Cluster> Manage> Developer Studio. Otevře se rozhraní jako toto:

Poradci

Tlačítko poradců vygeneruje přehled všech poradců s jejich výstupem od posledního spuštění:

Můžete také vidět plán poradce ve formátu crontab a datum/čas od poslední aktualizace. Někteří poradci jsou naplánováni pouze jednou denně, takže jejich rady již nemusí odrážet realitu, například pokud jste již vyřešili problém, na který jste byli upozorněni. Poradce můžete znovu spustit ručně tak, že jej vyberete a spustíte. Přejděte do části „kompilovat a spustit“ a přečtěte si, jak to provést.

Import poradců

Tlačítko Import vám umožní importovat tarball s novými poradci. Tarball musí být vytvořen relativně k hlavní cestě poradců, takže pokud chcete nahrát novou verzi skriptu velikosti mezipaměti dotazů MySQL (s9s/mysql/query_cache/qc_size.js), budete muset spustit tarball z adresáře s9s.

Poradci pro export

Poradce nebo jejich část můžete exportovat výběrem uzlu ve stromu a stisknutím tlačítka Export. Tím se vytvoří tarball se soubory v celé cestě prezentované struktury. Předpokládejme, že si přejeme provést zálohu poradců s9s/mysql před provedením změny, jednoduše vybereme uzel s9s/mysql ve stromu a stiskneme Export:

Poznámka:Ujistěte se, že adresář s9s je přítomen v /home/myuser/.

Tím vytvoříte tarball s názvem /home/myuser/s9s/mysql.tar.gz s vnitřní adresářovou strukturou s9s/mysql/*

Vytvoření nového poradce

Protože jsme pokryli export a import, můžeme nyní začít experimentovat. Pojďme tedy vytvořit nového poradce! Kliknutím na tlačítko Nový získáte následující dialog:

V tomto dialogu můžete vytvořit svého nového poradce buď s prázdným souborem, nebo jej předem vyplnit šablonou specifickou pro Galera nebo MySQL. Obě šablony přidají nezbytné součásti (common/mysql_helper.js) a základy pro načtení uzlů Galera nebo MySQL a jejich smyčkování.

Vytvoření nového poradce pomocí šablony Galera vypadá takto:

#include "common/mysql_helper.js"

Zde můžete vidět, že je zahrnut soubor mysql_helper.js, který poskytuje základ pro připojení a dotazování uzlů MySQL.

Tento soubor obsahuje funkce, které můžete v případě potřeby vyvolat, jako například readVariable(,), která vám umožní získat hodnotu globálních proměnných, nebo vyvolat readStatusVariable(,), což vám také umožní získat globální stavové proměnné v MySQL. Tento soubor může být umístěn ve stromu, jak je vidět níže:

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

Varovný práh je aktuálně nastaven na 0, což znamená, že pokud je naměřený práh vyšší než varovný práh, poradce by měl varovat uživatele. Všimněte si, že práh proměnné není v šabloně zatím nastaven/použit, protože je to začátek pro vašeho vlastního poradce.

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

Výše uvedené příkazy načtou hostitele v klastru a můžete je použít k opakování. Rozdíl mezi nimi je v tom, že první příkaz zahrnuje všechny hostitele mimo MySQL (také hostitel CMON), druhý všechny hostitele MySQL a poslední pouze hostitelé Galery. Pokud má tedy váš cluster Galera připojené podřízené jednotky pro asynchronní čtení MySQL, tito hostitelé nebudou zahrnuti.

Kromě toho se budou všechny tyto objekty chovat stejně a budou mít schopnost číst jejich proměnné, stav a dotazovat se na ně.

Tlačítka poradce

Nyní, když jsme vytvořili nového poradce, je pro tohoto poradce k dispozici šest nových tlačítek:

Uložit uloží vaše poslední úpravy v poradci (uložené v databázi CMON), Přesunout přesune poradce na novou cestu a Odstraní zjevně odstraní poradce.

Zajímavější je druhá řada tlačítek. Sestavení poradce sestaví kód poradce. Pokud se kód zkompiluje v pořádku, uvidíte tuto zprávu v části Zprávy dialog pod kódem poradce:

Zatímco pokud se kompilace nezdařila, kompilátor vám dá nápovědu, kde selhala:

V tomto případě kompilátor indikuje, že na řádku 24 byla nalezena syntaktická chyba.

Zkompilujte a spusťte tlačítko skript nejen zkompiluje, ale také spustí a jeho výstup se zobrazí v dialogu Zprávy, Graf nebo Raw. Pokud zkompilujeme a spustíme skript mezipaměti tabulky z auto_tunerů, dostaneme výstup podobný tomuto:

Poslední tlačítko je plán knoflík. To vám umožní naplánovat (nebo zrušit plán) své poradce a přidat k nim štítky. Tomu se budeme věnovat na konci tohoto příspěvku, až si vytvoříme vlastního poradce a budeme ho chtít naplánovat.

Můj první poradce

Nyní, když jsme probrali základy ClusterControl Developer Studio, můžeme nyní konečně začít vytvářet nového poradce. Jako příklad vytvoříme poradce, který se podívá na poměr dočasné tabulky. Vytvořte nového poradce následovně:

Teorie v pozadí poradce, kterého se chystáme vytvořit, je jednoduchá:porovnáme počet dočasných tabulek vytvořených na disku s celkovým počtem vytvořených dočasných tabulek:

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

Nejprve musíme v hlavě skriptu nastavit některé základy, jako jsou prahové hodnoty a varovná a ok. Všechny změny a doplňky jsou použity níže:

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

Zde jsme nastavili práh na 20 procent, což je již nyní považováno za dost špatné. Ale více o tomto tématu, až dokončíme našeho poradce.

Dále potřebujeme získat tyto stavové proměnné z MySQL. Než uděláme ukvapené závěry a provedeme nějaký dotaz „SHOW GLOBAL STATUS LIKE 'Created_tmp_%'“, existuje již funkce pro načtení stavové proměnné instance MySQL, jak jsme popsali výše, kde se tato funkce nachází v common/mysql_helper. js:

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

Tuto funkci můžeme použít v našem poradci k načtení Created_tmp_disk_tables a 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’);

A nyní můžeme vypočítat poměr tabulek dočasných disků:

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

A upozornit, pokud je tento poměr větší než práh, který jsme nastavili na začátku:

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

Zde je důležité přiřadit Advice do proměnné msg, protože tato bude později přidána do objektu avíza pomocí funkce setAdvice(). Úplný skript pro úplnost:

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

Nyní si můžete pohrát s prahovou hodnotou 20, zkusit ji snížit například na 1 nebo 2 a pak pravděpodobně uvidíte, jak vám tento poradce skutečně poradí v této záležitosti.

Jak vidíte, pomocí jednoduchého skriptu můžete porovnávat dvě proměnné proti sobě a na základě jejich výsledku hlásit/poradit. Ale je to všechno? Stále existuje několik věcí, které můžeme zlepšit!

Vylepšení mého prvního poradce

První věc, kterou můžeme zlepšit, je, že tento poradce nedává moc smysl. Metrika ve skutečnosti odráží celkový počet dočasných tabulek na disku od posledního FLUSH STATUS nebo spuštění MySQL. Neříká, za jakou sazbu ve skutečnosti vytváří dočasné tabulky na disku. Můžeme tedy převést Created_tmp_disk_tables na rychlost pomocí doby provozu hostitele:

    var tmp_disk_table_rate = tmp_disk_tables / uptime;

To by nám mělo poskytnout počet dočasných tabulek za sekundu a v kombinaci s tmp_disk_table_ratio nám to poskytne přesnější pohled na věci. Opět platí, že jakmile dosáhneme prahu dvou dočasných tabulek za sekundu, nechceme okamžitě posílat upozornění/radu.

Další věc, kterou můžeme zlepšit, je nepoužívat funkci readStatusVariable(, ) z knihovny common/mysql_helper.js. Tato funkce provádí dotaz na hostitele MySQL pokaždé, když čteme stavovou proměnnou, zatímco CMON již většinu z nich načítá každou sekundu a stejně nepotřebujeme stav v reálném čase. Není to tak, že dva nebo tři dotazy zabijí hostitele v clusteru, ale pokud bude mnoho z těchto poradců spuštěno podobným způsobem, mohlo by to vytvořit hromadu dalších dotazů.

V tomto případě to můžeme optimalizovat načtením stavových proměnných v mapě pomocí funkce host.sqlInfo() a získat vše najednou jako mapu. Tato funkce obsahuje nejdůležitější informace o hostiteli, ale neobsahuje všechny. Například proměnná doba provozu, kterou potřebujeme pro rychlost, není k dispozici v mapě host.sqlInfo() a je třeba ji získat pomocí funkce readStatusVariable(, ).

Takto bude nyní vypadat náš poradce se změnami/doplněními označenými tučně:

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

Plánování mého prvního poradce

Poté, co jsme tohoto nového poradce uložili, zkompilovali a spustili, můžeme nyní tohoto poradce naplánovat. Vzhledem k tomu, že nemáme nadměrnou pracovní zátěž, pravděpodobně budeme tohoto poradce spouštět jednou denně.

Základní režim plánování je podobný Cron, který má přednastavenou každou minutu, 5 minut, hodinu, den, měsíc, a to je přesně to, co potřebujeme a je velmi snadné plánování spravovat. Změnou na pokročilé odemknete ostatní šedá vstupní pole. Tato vstupní pole fungují úplně stejně jako crontab, takže je můžete dokonce naplánovat na konkrétní den, den v měsíci nebo dokonce nastavit na pracovní dny.

Po tomto blogu vytvoříme kontrolu pro SELinux nebo bezpečnostní kontroly pro Spectre a Meltdown, pokud jsou uzly ovlivněny. Zůstaňte naladěni!


  1. Jak se mám připojit k instanci Redis z funkce AWS Lambda?

  2. Redis - Připojení ke vzdálenému serveru

  3. Celery/Redis stejná úloha se provádí vícekrát paralelně

  4. Co je třída Hadoop Reducer v MapReduce?