Ti sei mai chiesto cosa fa scattare il consiglio in ClusterControl che il tuo disco si sta riempiendo? O il consiglio di creare chiavi primarie su tabelle InnoDB se non esistono? Questi advisor sono mini script scritti in ClusterControl Domain Specific Language (DSL) che è un linguaggio simile a Javascript. Questi script possono essere scritti, compilati, salvati, eseguiti e programmati in ClusterControl. Questo è ciò di cui parlerà la serie di blog ClusterControl Developer Studio.
Oggi tratteremo le basi di Developer Studio e ti mostreremo come creare il tuo primo consulente in cui sceglieremo due variabili di stato e daremo consigli sul loro risultato.
I Consiglieri
Gli advisor sono mini script eseguiti da ClusterControl, su richiesta o dopo una pianificazione. Possono essere qualsiasi cosa, da semplici consigli di configurazione, avvisi sulle soglie o regole più complesse per previsioni o attività di automazione a livello di cluster in base allo stato dei server o dei database. In generale, i consulenti eseguono analisi più dettagliate e producono raccomandazioni più complete rispetto agli avvisi.
Gli advisor sono archiviati all'interno del database ClusterControl ed è possibile aggiungere nuovi advisor o alterare/modificare quelli esistenti. Abbiamo anche un repository Github di consulenti in cui puoi condividere i tuoi consulenti con noi e altri utenti ClusterControl.
Il linguaggio utilizzato per gli advisor è il cosiddetto ClusterControl DSL ed è un linguaggio di facile comprensione. La semantica del linguaggio può essere paragonata al meglio a Javascript con un paio di differenze, dove le differenze più importanti sono:
- Il punto e virgola è obbligatorio
- Vari tipi di dati numerici come interi e interi long long senza segno.
- Gli array sono bidimensionali e gli array monodimensionali sono elenchi.
Puoi trovare l'elenco completo delle differenze nel riferimento ClusterControl DSL.
L'interfaccia di Developer Studio
L'interfaccia di Developer Studio si trova in Cluster> Gestisci> Developer Studio. Si aprirà un'interfaccia come questa:
Consiglieri
Il pulsante degli advisor genererà una panoramica di tutti gli advisor con il loro output dall'ultima volta che sono stati eseguiti:
Puoi anche vedere la pianificazione dell'advisor in formato crontab e la data/ora dall'ultimo aggiornamento. Alcuni consulenti sono programmati per essere eseguiti solo una volta al giorno, quindi i loro consigli potrebbero non riflettere più la realtà, ad esempio se hai già risolto il problema di cui sei stato avvisato. È possibile rieseguire manualmente l'advisor selezionando l'advisor ed eseguirlo. Vai alla sezione "compila ed esegui" per leggere come farlo.
Consulenti per l'importazione
Il pulsante Importa ti consentirà di importare un tarball con nuovi advisor al suo interno. Il tarball deve essere creato rispetto al percorso principale degli advisor, quindi se desideri caricare una nuova versione dello script della dimensione della cache delle query MySQL (s9s/mysql/query_cache/qc_size.js) dovrai far partire il tarball dalla directory s9s.
Consulenti per l'esportazione
È possibile esportare gli advisor o una parte di essi selezionando un nodo nell'albero e premendo il pulsante Esporta. Questo creerà un tarball con i file nel percorso completo della struttura presentata. Supponiamo di voler eseguire un backup degli advisor s9s/mysql prima di apportare una modifica, selezioniamo semplicemente il nodo s9s/mysql nell'albero e premiamo Esporta:
Nota:assicurati che la directory s9s sia presente in /home/mioutente/.
Questo creerà un tarball chiamato /home/myuser/s9s/mysql.tar.gz con una struttura di directory interna s9s/mysql/*
Creazione di un nuovo consulente
Dal momento che abbiamo coperto le esportazioni e le importazioni, ora possiamo iniziare a sperimentare. Quindi creiamo un nuovo consulente! Fare clic sul pulsante Nuovo per ottenere la seguente finestra di dialogo:
In questa finestra di dialogo, puoi creare il tuo nuovo advisor con un file vuoto o precompilarlo con il modello specifico di Galera o MySQL. Entrambi i modelli aggiungeranno le inclusioni necessarie (common/mysql_helper.js) e le nozioni di base per recuperare i nodi Galera o MySQL e passarci sopra.
La creazione di un nuovo advisor con il modello Galera è simile a questa:
#include "common/mysql_helper.js"
Qui puoi vedere che mysql_helper.js viene incluso per fornire la base per la connessione e l'esecuzione di query sui nodi MySQL.
Questo file contiene funzioni che puoi richiamare se necessario come ad esempio readVariable(
var WARNING_THRESHOLD=0;
…
if(threshold > WARNING_THRESHOLD)
La soglia di avviso è attualmente impostata su 0, il che significa che se la soglia misurata è maggiore della soglia di avviso, l'advisor deve avvisare l'utente. Nota che la soglia variabile non è ancora impostata/utilizzata nel modello poiché è un kickstart per il tuo consulente.
var hosts = cluster::Hosts();
var hosts = cluster::mySqlNodes();
var hosts = cluster::galeraNodes();
Le istruzioni precedenti recupereranno gli host nel cluster e potrai utilizzarli per eseguire il loop su di essi. La differenza tra loro è che la prima istruzione include tutti gli host non MySQL (anche l'host CMON), la seconda tutti gli host MySQL e l'ultimo solo i padroni di casa Galera. Quindi, se il tuo cluster Galera ha slave di lettura asincroni MySQL collegati, quegli host non saranno inclusi.
A parte questo, questi oggetti si comporteranno tutti allo stesso modo e avranno la possibilità di leggere le loro variabili, lo stato e interrogarli.
Pulsanti del consulente
Ora che abbiamo creato un nuovo advisor, sono disponibili sei nuovi pulsanti per questo advisor:
Salva salverà le ultime modifiche nell'advisor (memorizzato nel database CMON), Sposta sposterà l'advisor in un nuovo percorso e Rimuovi rimuoverà ovviamente l'advisor.
Più interessante è la seconda fila di pulsanti. La compilazione dell'advisor compilerà il codice dell'advisor. Se il codice viene compilato correttamente, vedrai questo messaggio nei Messaggi dialogo sotto il codice dell'advisor:
Mentre se la compilazione fallisce, il compilatore ti darà un suggerimento dove ha fallito:
In questo caso il compilatore indica che è stato trovato un errore di sintassi alla riga 24.
Il compila ed esegui Il pulsante non solo compilerà lo script ma lo eseguirà anche e il suo output verrà mostrato nella finestra di dialogo Messaggi, Grafico o Raw. Se compiliamo ed eseguiamo lo script della cache della tabella da auto_tuners, otterremo un output simile a questo:
L'ultimo pulsante è il programma pulsante. Ciò ti consente di programmare (o annullare la programmazione) i tuoi consulenti e aggiungervi tag. Ne tratteremo alla fine di questo post quando avremo creato il nostro consulente personale e vorremo programmarlo.
Il mio primo consigliere
Ora che abbiamo coperto le basi di ClusterControl Developer Studio, possiamo finalmente iniziare a creare un nuovo advisor. Ad esempio creeremo un advisor per esaminare il rapporto della tabella temporanea. Crea un nuovo consulente come segue:
La teoria alla base dell'advisor che creeremo è semplice:confronteremo il numero di tabelle temporanee create su disco con il numero totale di tabelle temporanee create:
tmp_disk_table_ratio = Created_tmp_disk_tables / (Created_tmp_tables + Created_tmp_disk_tables) * 100;
Per prima cosa dobbiamo impostare alcune nozioni di base nell'intestazione dello script, come le soglie e i messaggi di avviso e ok. Tutte le modifiche e le aggiunte vengono applicate di seguito:
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." ;
Abbiamo impostato la soglia qui al 20 percento, che è già considerato piuttosto negativo. Ma di più su questo argomento una volta che avremo finalizzato il nostro consulente.
Successivamente abbiamo bisogno di ottenere queste variabili di stato da MySQL. Prima di saltare alle conclusioni ed eseguire alcune query "SHOW GLOBAL STATUS LIKE 'Created_tmp_%'", esiste già una funzione per recuperare la variabile di stato di un'istanza MySQL, come descritto sopra in cui questa funzione si trova in common/mysql_helper. js:
statusVar = readStatusVariable(<host>, <statusvariablename>);
Possiamo usare questa funzione nel nostro advisor per recuperare le tabelle Created_tmp_disk_tables e 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’);
E ora possiamo calcolare il rapporto delle tabelle del disco temporaneo:
var tmp_disk_table_ratio = tmp_disk_tables / (tmp_tables + tmp_disk_tables) * 100;
E avvisa se questo rapporto è maggiore della soglia che abbiamo impostato all'inizio:
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;
}
}
È importante assegnare qui l'Advice alla variabile msg poiché questa verrà aggiunta in seguito nell'oggetto dell'avviso con la funzione setAdvice(). Lo script completo per completezza:
#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;
}
Ora puoi giocare con la soglia di 20, prova ad abbassarla a 1 o 2 per esempio e poi probabilmente vedrai come questo consulente ti darà effettivamente consigli in merito.
Come puoi vedere, con un semplice script puoi confrontare due variabili l'una con l'altra e segnalare/consigli in base al loro risultato. Ma è tutto? Ci sono ancora un paio di cose che possiamo migliorare!
Miglioramenti al mio primo consulente
La prima cosa che possiamo migliorare è che questo consulente non ha molto senso. Ciò che la metrica riflette effettivamente è il numero totale di tabelle temporanee su disco dall'ultimo FLUSH STATUS o dall'avvio di MySQL. Quello che non dice è a quale tasso in realtà crea tabelle temporanee su disco. Quindi possiamo convertire le Created_tmp_disk_tables in una tariffa utilizzando il tempo di attività dell'host:
var tmp_disk_table_rate = tmp_disk_tables / uptime;
Questo dovrebbe darci il numero di tabelle temporanee al secondo e combinato con tmp_disk_table_ratio, questo ci darà una visione più accurata delle cose. Anche in questo caso, una volta raggiunta la soglia di due tabelle temporanee al secondo, non vogliamo inviare immediatamente un avviso/consiglio.
Un'altra cosa che possiamo migliorare è non usare la funzione readStatusVariable(
In questo caso possiamo ottimizzarlo recuperando le variabili di stato in una mappa usando la funzione host.sqlInfo() e recuperando tutto in una volta come mappa. Questa funzione contiene le informazioni più importanti dell'host, ma non tutte. Ad esempio, il tempo di attività variabile di cui abbiamo bisogno per la velocità non è disponibile nella mappa host.sqlInfo() e deve essere recuperato con la funzione readStatusVariable(
Ecco come apparirà ora il nostro consulente, con le modifiche/aggiunte contrassegnate in grassetto:
#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;
}
Pianificazione del mio primo consulente
Dopo aver salvato questo nuovo advisor, averlo compilato ed eseguito, ora possiamo pianificare questo advisor. Dal momento che non abbiamo un carico di lavoro eccessivo, probabilmente eseguiremo questo advisor una volta al giorno.
La modalità di pianificazione di base è simile a Cron che ha ogni minuto, 5 minuti, ora, giorno, mese preimpostati e questo è esattamente ciò di cui abbiamo bisogno ed è molto facile gestire la pianificazione. Cambiando questo in avanzato sbloccherai gli altri campi di input in grigio. Questi campi di input funzionano esattamente come un crontab, quindi puoi persino programmare un determinato giorno, giorno del mese o persino impostarlo nei giorni feriali.
Seguendo questo blog, creeremo un controllo per SELinux o controlli di sicurezza per Spectre e Meltdown se i nodi sono interessati. Resta sintonizzato!