Ciao a tutti! Nel mio ho scritto dell'organizzazione di un sistema modulare di monitoraggio per architetture a microservizi. Nulla rimane fermo, il nostro progetto cresce costantemente e anche il numero di metriche memorizzate aumenta. Come abbiamo organizzato la transizione da Graphite+Whisper a Graphite+ClickHouse in condizioni di carico elevato, le aspettative e i risultati della migrazione li puoi leggere qui sotto.

Prima di raccontarvi come abbiamo organizzato il passaggio dalla memorizzazione delle metriche in Graphite+Whisper a Graphite+ClickHouse, vorrei fornire informazioni sulle motivazioni che ci hanno portato a prendere tale decisione e sui problemi di Whisper con cui abbiamo convivido per lungo tempo.
Problemi di Graphite+Whisper
1. Alta pressione sul sottosistema di archiviazione
Quando siamo passati a noi, arrivavano circa 1,5 milioni di metriche al minuto. Con questo volume, l'utilizzo del disco sui server era di circa il 30%. In generale, era piuttosto accettabile: tutto funzionava in modo stabile, si scriveva e si leggeva rapidamente… Fino a quando uno dei team di sviluppo non ha rilasciato una nuova funzionalità, iniziando a inviarci 10 milioni di metriche al minuto. È stato allora che il sottosistema disco ha iniziato a faticare, e abbiamo visto un utilizzo del 100%. Siamo riusciti a risolvere rapidamente il problema, ma è rimasta un'eco di ciò che è accaduto.
2. Mancanza di replicazione e coerenza
Probabilmente, come tutti coloro che utilizzano/hanno utilizzato Graphite+Whisper, inviavamo un flusso di metriche uniforme a più server Graphite per garantire la ridondanza. E non ci sono stati problemi significativi — fino al momento in cui uno dei server si bloccava per qualche motivo. A volte riuscivamo a riavviare il server guasto abbastanza rapidamente, e carbon-c-relay riusciva a inviare le metriche dal proprio cache, altre volte no. E in quel caso, c'era un vuoto nelle metriche che riempivamo con rsync. La procedura era piuttosto lunga. L'unica cosa che ci salvava era che eventi di questo tipo accadevano molto raramente. Inoltre, ogni tanto prendevamo un campione casuale di metriche e le confrontavamo con altre analoghe sui nodi vicini del cluster. In circa il 5% dei casi, alcuni valori differivano, il che non era molto incoraggiante.
3. Grande quantità di spazio occupato
Poiché scriviamo in Graphite non solo metriche infrastrutturali, ma anche metriche aziendali (e ora anche metriche da Kubernetes), ci troviamo spesso nella situazione in cui nella metrica sono presenti solo alcuni valori, e il file .wsp viene creato tenendo conto di tutto il periodo di retention, occupando uno spazio preassegnato che era pari a ~2MB. Il problema è ulteriormente aggravato dal fatto che con il tempo questi file aumentano notevolmente, e la lettura di punti vuoti durante la creazione dei report richiede molto tempo e risorse.
Vorrei subito notare che ci sono diversi metodi per affrontare i problemi descritti sopra, ognuno con un diverso grado di efficacia, ma più dati iniziano a arrivare, più si intensificano.
Considerando tutto quanto sopra (incluso il precedente ), così come la costante crescita del numero di metriche ricevute e il desiderio di ridurre tutte le metriche a un intervallo di conservazione di 30 secondi (se necessario, fino a 10 secondi), abbiamo deciso di provare Graphite+ClickHouse come potenziale alternativa a Whisper.
Graphite+ClickHouse. Aspettative
Dopo aver partecipato a diversi meetup con i ragazzi di Yandex e aver letto , dopo aver esaminato la documentazione e trovato componenti adeguati per l'integrazione di ClickHouse con Graphite, abbiamo deciso di agire!
Volevamo ottenere quanto segue:
- ridurre l'utilizzo del sottosistema di archiviazione dal 30% al 5%;
- ridurre lo spazio occupato da 1TB a 100GB;
- avere la possibilità di accettare 100 milioni di metriche al minuto sul server;
- replicazione dei dati e tolleranza ai guasti out-of-the-box;
- non lavorare su questo progetto per un anno e completare la migrazione in un termine ragionevole;
- passare senza downtime.
Abbastanza ambizioso, vero?
Graphite+ClickHouse. Componenti
Per ottenere dati tramite il protocollo Graphite e successivamente scriverli in ClickHouse, è stato scelto (golang).
Come database per la memorizzazione delle serie temporali è stata scelta l'ultima versione stabile di ClickHouse, la 1.1.54253. Durante l'uso ci sono stati problemi: si sono accumulate molteplici errori nei log e non era chiaro come gestirli. In una discussione con (autore di carbon-clickhouse, graphite-clickhouse e molto altro ancora) è stata scelta una versione più vecchia . Gli errori sono scomparsi — tutto ha cominciato a funzionare alla grande.
Per leggere i dati da ClickHouse è stato scelto (golang). Come interfaccia API per Graphite — (golang). Per organizzare la replica tra le tabelle di ClickHouse è stato utilizzato . Per la gestione delle metriche, abbiamo lasciato il nostro amato (C) .
Graphite+ClickHouse. Struttura delle tabelle
“graphite” — un database creato da noi per le tabelle di monitoraggio.
“graphite.metrics” — tabella con motore ReplicatedReplacingMergeTree (replicato ). In questa tabella sono memorizzati i nomi delle metriche e i percorsi corrispondenti.
CREATE TABLE graphite.metrics ( Data Date, Livello UInt32, Percorso String, Cancellato UInt8, Versione UInt32 ) ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/replicator/graphite.metrics', 'r1', Data, (Livello, Percorso), 8192, Versione);“graphite.data” — tabella con motore ReplicatedGraphiteMergeTree (replicato ). In questa tabella sono memorizzati i valori delle metriche.
CREATE TABLE graphite.data ( Percorso String, Valore Float64, Tempo UInt32, Data Date, Timestamp UInt32 ) ENGINE = ReplicatedGraphiteMergeTree('/clickhouse/tables/replicator/graphite.data', 'r1', Data, (Percorso, Tempo), 8192, 'graphite_rollup')“graphite.date_metrics” — tabella popolata in base a condizione, con motore ReplicatedReplacingMergeTree. In questa tabella vengono registrati i nomi di tutte le metriche che si sono presentate nell'arco di 24 ore. Le ragioni della creazione sono descritte nella sezione alla fine di questo articolo.
CREA UNA VISTA MATERIALIZZATA graphite.date_metrics ( Path String, Level UInt32, Date Date) ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/replicator/graphite.date_metrics', 'r1', Date, (Level, Path, Date), 8192) AS SELECT toUInt32(length(splitByChar('.', Path))) AS Level, Date, Path FROM graphite.data“graphite.data_stat” — una tabella riempita in base a una condizione, con il motore ReplicatedAggregatingMergeTree (replicato ). In questa tabella vengono registrate le metriche in entrata, suddivise fino a 4 livelli di profondità.
CREA UNA VISTA MATERIALIZZATA graphite.data_stat ( Date Date, Prefix String, Timestamp UInt32, Count AggregateFunction(count)) ENGINE = ReplicatedAggregatingMergeTree('/clickhouse/tables/replicator/graphite.data_stat', 'r1', Date, (Timestamp, Prefix), 8192) AS SELECT toStartOfMonth(now()) AS Date, replaceRegexpOne(Path, '^([^.]+.[^.]+.[^.]+).*$', '1') AS Prefix, toUInt32(toStartOfMinute(toDateTime(Timestamp))) AS Timestamp, countState() AS Count FROM graphite.data GROUP BY Timestamp, PrefixGraphite+ClickHouse. Schema di interazione dei componenti

Graphite+ClickHouse. Migrazione dei dati
Come ci ricordiamo dalle aspettative riguardanti questo progetto, la transizione a ClickHouse dovrebbe avvenire senza downtime, pertanto, dovevamo fare in modo di switchare l'intero sistema di monitoraggio sul nuovo storage in modo il più trasparente possibile per i nostri utenti.
L'abbiamo fatto in questo modo.
Nel carbon-c-relay è stata aggiunta una regola per inviare un flusso aggiuntivo di metriche a carbon-clickhouse su uno dei server coinvolti nella replicazione delle tabelle ClickHouse.
Abbiamo scritto un piccolo script in Python che, utilizzando la libreria whisper-dump, leggeva tutti i file .wsp dal nostro archivio e inviava questi dati al carbon-clickhouse descritto sopra in 24 flussi. Il numero di valori delle metriche ricevuti da carbon-clickhouse ha raggiunto i 125 milioni/min, e ClickHouse non ha nemmeno mostrato segni di affaticamento.
Abbiamo creato un DataSource separato in Grafana per il debugging delle funzioni utilizzate nei dashboard esistenti. Abbiamo identificato un elenco di funzioni che utilizzavamo, ma che non erano implementate in carbonapi. Abbiamo scritto queste funzioni e inviato delle PR agli autori di carbonapi (un ringraziamento speciale a loro).
- Per trasferire il carico di lettura, nelle impostazioni dei bilanciatori abbiamo cambiato gli endpoint da graphite-api (interfaccia API per Graphite+Whisper) a carbonapi.
Graphite+ClickHouse. Risultati
ridotto l'utilizzo del sistema di archiviazione da 30% a 1%;

- ridotto lo spazio occupato da 1 TB a 300 GB;
- siamo in grado di ricevere fino a 125 milioni di metriche al minuto nel server (picchi durante la migrazione);
- abbiamo trasferito tutte le metriche a un intervallo di conservazione di trenta secondi;
- abbiamo ottenuto la replica dei dati e la tolleranza agli errori;
- si è spostato senza downtime;
- abbiamo impiegato circa 7 settimane per tutto.
Graphite+ClickHouse. Problemi
Nel nostro caso non sono mancati i problemi. Ecco cosa abbiamo affrontato dopo la transizione.
- ClickHouse non sempre rilegge le configurazioni in tempo reale, a volte deve essere riavviato. Ad esempio, nel caso della descrizione del cluster zookeeper nella configurazione di ClickHouse — non veniva applicata fino al riavvio di clickhouse-server.
- Non riuscivamo a gestire grandi query in ClickHouse, quindi la nostra stringa di connessione a ClickHouse in graphite-clickhouse appare in questo modo:
url = "http://localhost:8123/?max_query_size=268435456&max_ast_elements=1000000" - In ClickHouse escono piuttosto frequentemente nuove versioni di rilasci stabili, che potrebbero riservare sorprese: fate attenzione.
- I contenitori creati dinamicamente in Kubernetes inviano un gran numero di metriche con brevi e casuali periodi di vita. Le occorrenze per queste metriche non sono molte e non ci sono problemi di spazio. Tuttavia, durante la costruzione delle query, ClickHouse recupera un'enorme quantità di queste metriche dalla tabella 'metrics'. Nel 90% dei casi, i dati per esse non sono presenti nella finestra di 24 ore. Il tempo speso per cercare questi dati nella tabella 'data' porta a un timeout. Per risolvere questo problema, abbiamo iniziato a mantenere una vista separata con informazioni sulle metriche incontrate in un giorno. In questo modo, durante la creazione di report (grafici) sui contenitori creati dinamicamente, interroghiamo solo le metriche che sono state registrate all'interno della finestra di tempo specificata, e non per tutto il tempo, il che ha notevolmente accelerato la generazione dei report. , che include l'implementazione del lavoro con la tabella date_metrics.
Graphite+ClickHouse. Tag
A partire dalla versione 1.1.0, Graphite ha iniziato a supportare ufficialmente . Stiamo inoltre pensando attivamente a cosa e come fare per sostenere questa iniziativa nel stack graphite+clickhouse.
Graphite+ClickHouse. Rilevatore di anomalie
Sulla base dell'infrastruttura descritta sopra, abbiamo realizzato un prototipo del rilevatore di anomalie, e funziona! Ma di questo parleremo nel prossimo articolo.
Iscriviti, premi la freccia in su e sii felice!
Fonte: habr.com

