Cluster Elasticsearch da 200 TB+

Cluster Elasticsearch da 200 TB+

Molti si confrontano con Elasticsearch. Ma cosa succede quando desideri usarlo per memorizzare log in "grandi quantità"? E come affrontare senza problemi il fallimento di uno dei diversi data center? Quale architettura dovresti adottare e quali insidie potresti incontrare?

Noi di Odnoklassniki abbiamo deciso di affrontare il problema della gestione dei log usando Elasticsearch e ora condividiamo con Habr la nostra esperienza: sia riguardo all'architettura che alle insidie.

Io sono Petr Zaytsev, lavoro come amministratore di sistema in Odnoklassniki. Prima di questo, ero anche amministratore e ho lavorato con Manticore Search, Sphinx search ed Elasticsearch. Probabilmente, se emerge un altro …search, lavorerò anche con quello. Partecipo inoltre a diversi progetti open source su base volontaria.

Quando sono arrivato in Odnoklassniki, ho imprudentemente affermato durante il colloquio che sapevo usare Elasticsearch. Dopo essermi ambientato e aver svolto alcune semplici attività, mi è stata affidata una grande operazione di riforma del sistema di gestione dei log esistente.

Requisiti

I requisiti per il sistema sono stati formulati come segue:

  • Come frontend doveva essere utilizzato Graylog. Perché in azienda avevano già esperienza con questo prodotto, i programmatori e i tester lo conoscevano, era familiare e comodo per loro.
  • Volume di dati: in media 50-80 mila messaggi al secondo, ma se qualcosa si rompe, il traffico non è limitato, può arrivare a 2-3 milioni di righe al secondo
  • Discutendo con i clienti i requisiti per la velocità di elaborazione delle query, ci siamo resi conto che il modello tipico di utilizzo di un sistema simile è il seguente: le persone cercano i log della loro applicazione negli ultimi due giorni e non vogliono aspettare più di un secondo per il risultato della query formulata.
  • Gli amministratori insistettero affinché il sistema potesse essere facilmente scalabile se necessario, senza richiedere loro una profonda comprensione di come fosse strutturato.
  • L'unico compito di manutenzione che questi sistemi necessitavano periodicamente era sostituire qualche hardware.
  • Inoltre, in Odnoklassniki esiste una meravigliosa tradizione tecnica: ogni servizio che lanciamo deve sopportare il guasto di un data center (improvviso, non pianificato e in qualsiasi momento).

L'ultima richiesta per l'implementazione di questo progetto ci è costata molto, di cui parlerò più in dettaglio.

Ambiente

Lavoriamo su quattro data center, ma i nodi dati di Elasticsearch possono trovarsi solo in tre (per una serie di motivi non tecnici).

In questi quattro data center ci sono circa 18.000 diverse fonti di log — hardware, contenitori, macchine virtuali.

Una caratteristica importante: l'avvio del cluster avviene nei contenitori Podman non su macchine fisiche, ma su prodotto cloud proprietario one-cloud. Ai contenitori vengono garantiti 2 core, equivalenti a 2.0Ghz v4, con la possibilità di utilizzare i restanti core in caso di inattività.

In altre parole:

Cluster Elasticsearch da 200 TB+

Topologia

L'aspetto generale della soluzione mi è sembrato inizialmente il seguente:

  • 3-4 VIP sono dietro il record A del dominio Graylog, questo è l'indirizzo al quale vengono inviati i log.
  • Ogni VIP è un bilanciatore LVS.
  • Dopo di ciò, i log arrivano a un'unità Graylog, parte dei dati va nel formato GELF e parte nel formato syslog.
  • Successivamente, tutto questo viene scritto in grandi batch a un'unità di coordinatori Elasticsearch.
  • E loro, a loro volta, inviano richieste di scrittura e lettura ai nodi dati pertinenti.

Cluster Elasticsearch da 200 TB+

Terminologia

Forse non tutti hanno familiarità con la terminologia, quindi vorrei soffermarmi un attimo su di essa.

In Elasticsearch ci sono diversi tipi di nodi: master, coordinator, data node. Ci sono anche altri due tipi per diverse trasformazioni dei log e per la comunicazione tra diversi cluster, ma noi abbiamo utilizzato solo quelli elencati.

Master
Pinge tutti i nodi presenti nel cluster, mantiene aggiornata la mappa del cluster e la distribuisce tra i nodi, gestisce la logica degli eventi e si occupa di diverse operazioni di housekeeping su scala cluster.

Coordinator
Svolge un'unica funzione: accetta richieste dai clienti per la lettura o la scrittura e instrada questo traffico. Nel caso di una richiesta di scrittura, probabilmente chiederà al master in quale shard dell'indice pertinente deve essere inserita e reindirizzerà la richiesta.

Data node
Conserva i dati e gestisce le query di ricerca e le operazioni sugli shard in essa collocati.

Graylog
È una sorta di fusione tra Kibana e Logstash nel stack ELK. Graylog combina un'interfaccia utente e un pipeline per la gestione dei log. Sotto il cofano, Graylog utilizza Kafka e Zookeeper, che garantiscono la connettività di Graylog come cluster. Graylog può memorizzare nella cache i log (Kafka) in caso di indisponibilità di Elasticsearch e ripetere le richieste di lettura e scrittura non riuscite, raggruppando e contrassegnando i log secondo le regole impostate. Come Logstash, Graylog ha funzionalità di modifica delle stringhe prima di scriverle in Elasticsearch.

Inoltre, Graylog dispone di un servizio di discovery integrato che consente di ottenere l'intera mappa del cluster sulla base di un nodo Elasticsearch disponibile e di filtrarla in base a un tag specifico, consentendo di indirizzare le richieste verso contenitori specifici.

Visivamente, appare più o meno così:

Cluster Elasticsearch da 200 TB+

Questo è uno screenshot di un'istanza specifica. Qui costruiamo un istogramma sulla base di una query di ricerca, mostrando righe pertinenti.

Indici

Tornando all'architettura del sistema, vorrei entrare nei dettagli su come abbiamo costruito il modello degli indici affinché tutto funzionasse correttamente.

Nello schema precedente, questo è il livello più basso: i nodi dati di Elasticsearch.

Un indice è una grande entità virtuale composta da shard di Elasticsearch. Ogni shard è, in effetti, un indice Lucene. Ogni indice Lucene, a sua volta, è composto da uno o più segmenti.

Cluster Elasticsearch da 200 TB+

Nella progettazione, avevamo previsto che per soddisfare i requisiti di velocità di lettura su un grande volume di dati, fosse necessario "spalmare" equamente questi dati sui nodi dati.

Questo ha portato a stabilire che il numero di shard per indice (con repliche) dovesse essere esattamente uguale al numero di nodi dati. In primo luogo, per garantire un fattore di replica pari a due (ciò significa che possiamo perdere metà del cluster). In secondo luogo, per gestire le richieste di lettura e scrittura su almeno metà del cluster.

Il tempo di conservazione è stato inizialmente fissato a 30 giorni.

La distribuzione degli shard può essere rappresentata graficamente come segue:

Cluster Elasticsearch da 200 TB+

L'intero rettangolo grigio scuro è l'indice. Il quadrato rosso a sinistra è il primary shard, il primo nell'indice. E il quadrato blu è il replica shard. Si trovano in diversi data center.

Quando aggiungiamo un altro shard, esso finisce nel terzo data center. E, alla fine, otteniamo una struttura del genere, che consente la perdita di un DC senza compromettere la consistenza dei dati:

Cluster Elasticsearch da 200 TB+

Abbiamo impostato la rotazione degli indici, ovvero la creazione di un nuovo indice e l'eliminazione del più vecchio, a 48 ore (in base al pattern di utilizzo dell'indice: negli ultimi 48 ore si cercano più frequentemente).

Questo intervallo di rotazione degli indici è legato alle seguenti ragioni:

Quando un nodo di data riceve una richiesta di ricerca, dal punto di vista delle prestazioni è più vantaggioso interrogare un solo shard, se la sua dimensione è comparabile con quella della memoria della macchina. Questo permette di mantenere la parte "calda" dell'indice nella memoria e di accedervi rapidamente. Quando ci sono molte "parti calde", la velocità di ricerca per l'indice degrada.

Quando un nodo inizia a eseguire una richiesta di ricerca su uno shard, assegna un numero di thread pari al numero di core fisici nella macchina attivata per l'hyper-threading. Se la richiesta di ricerca coinvolge un gran numero di shard, il numero di thread aumenta in proporzione. Questo ha un effetto negativo sulla velocità di ricerca e influisce negativamente sull indicizzazione di nuovi dati.

Per garantire la latenza necessaria nella ricerca, abbiamo deciso di utilizzare SSD. Per una rapida elaborazione delle richieste, le macchine su cui erano ospitati questi container dovevano avere almeno 56 core. Il numero 56 è stato scelto come una dimensione condizionatamente sufficiente, che determina il numero di thread che Elasticsearch genererà durante il lavoro. In Elasticsearch, molti parametri del thread pool dipendono direttamente dal numero di core disponibili, che a sua volta influisce direttamente sul numero necessario di nodi nel cluster secondo il principio "meno core - più nodi".

Alla fine, abbiamo ottenuto che in media uno shard pesa circa 20 gigabyte e per 1 indice ci sono 360 shard. Di conseguenza, se li ruotiamo ogni 48 ore, ne abbiamo 15. Ogni indice contiene dati per 2 giorni.

Schemi di scrittura e lettura dei dati

Analizziamo come vengono scritti i dati in questo sistema.

Supponiamo che riceviamo una richiesta da Graylog nel coordinatore. Ad esempio, vogliamo indicizzare 2-3 mila righe.

Il coordinatore, ricevuto il comando da Graylog, interroga il master: «Nella richiesta di indicizzazione abbiamo specificato esattamente l'indice, ma non è stato indicato in quale shard scrivere».

Il master risponde: «Scrivi queste informazioni nello shard numero 71», dopodiché viene indirizzato direttamente al nodo dati rilevante, dove si trova il primary-shard numero 71.

Successivamente, il log delle transazioni viene replicato sul replica-shard, che si trova già in un'altra data center.

Cluster Elasticsearch da 200 TB+

Da Graylog arriva una richiesta di ricerca al coordinatore. Il coordinatore la reindirizza in base all'indice, mentre Elasticsearch distribuisce le richieste tra primary-shard e replica-shard secondo il principio round-robin.

Cluster Elasticsearch da 200 TB+

I nodi, per un totale di 180, rispondono in modo non uniforme e, mentre stanno rispondendo, il coordinatore accumula le informazioni che i nodi dati più veloci hanno già «espulso» in lui. Dopo di che, quando tutte le informazioni sono arrivate o quando è scaduto il timeout della richiesta, restituisce tutto direttamente al cliente.

Tutto questo sistema gestisce in media richieste di ricerca degli ultimi 48 ore in 300-400ms, escludendo quelle richieste con leading wildcard.

«Fioriture» con Elasticsearch: configurazione di Java

Cluster Elasticsearch da 200 TB+

Affinché tutto questo funzionasse come volevamo all'inizio, abbiamo a lungo affinato le più varie cose nel cluster.

La prima parte dei problemi riscontrati era legata a come Java è preconfigurata per impostazione predefinita in Elasticsearch.

Primo problema
Abbiamo osservato un numero molto elevato di messaggi che indicavano che a livello di Lucene, quando vengono eseguiti job in background, le fusioni dei segmenti Lucene terminano con un errore. Nei log era evidente che si trattava di un errore OutOfMemoryError. Dalla telemetria abbiamo visto che l'heap era libero e non era chiaro perché questa operazione fallisse.

Si è scoperto che le fusioni degli indici Lucene avvengono fuori dall'heap. E i contenitori sono piuttosto rigidi in termini di risorse consumate. Queste risorse erano accessibili solo all'heap (il valore heap.size era circa uguale alla RAM), mentre alcune operazioni off-heap fallivano con un errore di allocazione di memoria se per qualche motivo non rientravano nei ~500MB che restavano prima del limite.

La soluzione era piuttosto semplice: abbiamo aumentato la quantità di RAM disponibile per il contenitore, dopo di che abbiamo dimenticato che avevamo mai avuto tali problemi.

Secondo problema
Dopo circa 4-5 giorni dal lancio del cluster, abbiamo notato che i nodi dati iniziano a uscire periodicamente dal cluster e ad entrarvi dopo circa 10-20 secondi.

Quando abbiamo iniziato a indagare, è emerso che la memoria off-heap in Elasticsearch non era praticamente controllata. Quando abbiamo allocato più memoria al contenitore, abbiamo ottenuto la possibilità di riempire i pool di buffer diretti con diverse informazioni, e questi venivano ripuliti solo dopo che un GC esplicito veniva attivato da Elasticsearch.

In alcuni casi, questa operazione richiedeva molto tempo, e durante questo periodo il cluster riusciva a contrassegnare questo nodo come già non disponibile. Questo problema è ben documentato. qui.

La soluzione è stata la seguente: abbiamo limitato a Java la possibilità di utilizzare la maggior parte della memoria al di fuori dell'heap per queste operazioni. Abbiamo limitato questa memoria a 16 gigabyte (-XX:MaxDirectMemorySize=16g), ottenendo che il GC esplicito fosse invocato molto più frequentemente e funzionasse significativamente più velocemente, stabilizzando così il cluster.

Problema tre
Se pensi che i problemi con "i nodi che lasciano il cluster nel momento più imprevisto" siano finiti qui, ti sbagli.

Quando abbiamo configurato il lavoro con gli indici, abbiamo scelto mmapfs per ridurre i tempi di ricerca sui nuovi shard con una forte segmentazione. È stato un errore piuttosto grossolano, perché usando mmapfs il file viene mappato nella memoria RAM, e poi lavoriamo già con il file mappato. Di conseguenza, quando il GC cerca di fermare i thread nell'applicazione, impieghiamo molto tempo per arrivare al safepoint, e durante il tragitto l'applicazione smette di rispondere alle richieste del master su se sia viva o meno. Di conseguenza, il master pensa che il nodo non sia più presente nel cluster. Dopo circa 5-10 secondi il garbage collector entra in azione, il nodo si riattiva, rientra nel cluster e inizia l'inizializzazione degli shard. Tutto ciò somigliava molto a "un sistema di produzione che abbiamo meritato" e non era adatto per qualcosa di serio.

Per eliminare tale comportamento, inizialmente siamo passati a standard niofs, e poi, quando siamo migriati dalle versioni cinque di Elastic alle sei, abbiamo provato hybridfs, dove questo problema non si è presentato. Maggiori dettagli sui tipi di storage possono essere letti. qui.

Problema quattro
Poi c'era un altro problema molto interessante, che abbiamo risolto in tempi record. L'abbiamo affrontato per 2-3 mesi, perché il suo schema era completamente incomprensibile.

A volte i nostri coordinatori andavano in Full GC, di solito dopo pranzo, e non tornavano mai indietro. Durante il log delle latenze GC, appariva così: tutto va bene, bene, bene e poi all'improvviso — tutto va a rotoli.

Inizialmente pensavamo che ci fosse un utente cattivo che avviava qualche richiesta che portava il coordinatore a uscire dalla modalità operativa. Abbiamo loggato a lungo le richieste cercando di capire cosa stesse succedendo.

Alla fine si è scoperto che nel momento in cui un utente lanciava una grande richiesta e questa arrivava a un coordinatore Elasticsearch specifico, alcuni nodi rispondevano più lentamente degli altri.

E mentre il coordinatore attendeva la risposta da tutti i nodi, accumulava i risultati inviati dai nodi che avevano già risposto. Per il GC questo significa che il nostro modello di utilizzo dell'heap cambia rapidamente. E il GC che stavamo utilizzando non riusciva a gestire questo compito.

L'unica soluzione che abbiamo trovato per cambiare il comportamento del cluster in questa situazione è stata la migrazione a JDK13 e l'uso del garbage collector Shenandoah. Questo ha risolto il problema, i nostri coordinatori hanno smesso di cadere.

Così i problemi con Java sono finiti e sono iniziate le problematiche di throughput.

"Frutti" con Elasticsearch: throughput

Cluster Elasticsearch da 200 TB+

I problemi di throughput significano che il nostro cluster funziona in modo stabile, ma nei picchi di documenti indicizzati e durante le operazioni, le prestazioni non sono sufficienti.

Primo sintomo riscontrato: durante alcuni "esplosioni" in produzione, quando viene generata improvvisamente una grande quantità di log, su Graylog inizia a comparire frequentemente l'errore di indicizzazione es_rejected_execution.

Questo accadeva perché thread_pool.write.queue su un dato nodo, fino a quando Elasticsearch non è in grado di elaborare la richiesta di indicizzazione e inviare le informazioni nel shard su disco, per impostazione predefinita può memorizzare solo 200 richieste. E nella documentazione di Elasticsearch si parla molto poco di questo parametro. Viene indicato solo il numero massimo di thread e la dimensione predefinita.

Naturalmente, abbiamo iniziato a modificare questo valore e abbiamo scoperto che nel nostro setup si possono memorizzare abbastanza bene fino a 300 richieste, e valori maggiori comportano che torniamo a Full GC.

Inoltre, poiché si tratta di pacchetti di messaggi che arrivano all'interno di una singola richiesta, è stato necessario ottimizzare Graylog affinché scriva non frequentemente e in piccoli batch, ma in enormi batch o ogni 3 secondi, se il batch non è ancora pieno. In questo modo, l'informazione che scriviamo in Elasticsearch diventa disponibile non dopo due secondi, ma dopo cinque (il che ci va bene), ma diminuisce il numero di retry necessari per inoltrare un grande pacchetto di informazioni.

Questo è particolarmente importante nei momenti in cui abbiamo qualche malfunzionamento e lo segnala vigorosamente, per non ricevere Elastic completamente intasato di spam e, dopo un po', nodi Graylog non funzionanti a causa dei buffer pieni.

Inoltre, quando si verificavano queste esplosioni in produzione, ricevevamo lamentele da programmatori e tester: nel momento in cui avevano veramente bisogno di questi log, venivano loro forniti molto lentamente.

Abbiamo iniziato a indagare. Da un lato, era chiaro che sia le query di ricerca che le richieste di indicizzazione venivano elaborate, in sostanza, sulle stesse macchine fisiche e che, in un modo o nell'altro, ci sarebbero stati determinate fluttuazioni.

Ma questo poteva essere parzialmente aggirato grazie al fatto che nelle versioni sei di Elasticsearch è stato introdotto un algoritmo che consente di distribuire le richieste tra i nodi dati rilevanti non secondo il principio casuale round-robin (il contenitore che si occupa dell'indicizzazione e detiene il primary-shard potrebbe essere molto occupato e non avere la possibilità di rispondere rapidamente), ma indirizzare questa richiesta a un contenitore meno sovraccarico con replica-shard, che risponderà in modo significativamente più veloce. In altre parole, siamo giunti all'uso di use_adaptive_replica_selection: true.

L'immagine di lettura inizia a apparire così:

Cluster Elasticsearch da 200 TB+

La transizione a questo algoritmo ha notevolmente migliorato il tempo di query nei momenti in cui abbiamo avuto un grande flusso di log in scrittura.

Infine, il problema principale era l'uscita indolore del data center.

Cosa volevamo dal cluster subito dopo la perdita di connessione con un DC:

  • Se nel data center disconnesso si trova l'attuale master, questo verrà riassegnato e trasferito come ruolo su un'altra node in un altro DC.
  • Il master espellerà rapidamente dal cluster tutti i nodi non disponibili.
  • In base ai dati rimanenti, capirà: nel data center perso avevamo determinati shard primari, promuoverà rapidamente gli shard replica complementari nei data center rimanenti e continueremo con l indicizzazione dei dati.
  • Di conseguenza, la capacità di scrittura e lettura del cluster degraderà gradualmente, tuttavia, in generale, tutto continuerà a funzionare, anche se lentamente, ma in modo stabile.

Come abbiamo scoperto, volevamo qualcosa di simile:

Cluster Elasticsearch da 200 TB+

E abbiamo ottenuto quanto segue:

Cluster Elasticsearch da 200 TB+

Come è potuto succedere?

Nel momento in cui è crollato il data center, il nostro collo di bottiglia è stato il master.

Perché?

Il fatto è che nel master c'è un TaskBatcher, responsabile della diffusione nel cluster di determinate attività ed eventi. Qualsiasi uscita di un nodo, qualsiasi promozione di uno shard da replica a primario, qualsiasi compito di creazione di uno shard altrove — tutto questo passa prima nel TaskBatcher, dove viene elaborato in sequenza e in un solo thread.

Nel momento in cui un data center veniva disattivato, risultava che tutti i data node nei data center sopravvissuti si sentivano in dovere di comunicare al master "ci sono mancati determinati shard e determinati data node".

Nel frattempo, i data node sopravvissuti inviavano tutte queste informazioni all'attuale master e cercavano di attendere una conferma che lui le avesse ricevute. Non attendevano questa conferma, poiché il master riceveva i compiti più velocemente di quanto potesse rispondere. I nodi ripetevano le richieste dopo un timeout, e il master nel frattempo non cercava nemmeno di rispondere, ma era completamente assorbito dal compito di ordinare le richieste in base alla priorità.

In forma terminale risultava che i data node spamavano il master fino a farlo andare in full GC. Dopo questo, il compito del master passava a un altro nodo, e succedeva esattamente la stessa cosa, e in definitiva il cluster si distruggeva completamente.

Effettuavamo misurazioni e fino alla versione 6.4.0, dove questo è stato corretto, ci bastava disattivare contemporaneamente solo 10 data node su 360 per far collassare completamente il cluster.

Questo si presentava all'incirca così:

Cluster Elasticsearch da 200 TB+

Dopo la versione 6.4.0, dove è stato risolto questo brutto bug, i data node hanno smesso di far morire il master. Ma non è diventato "più intelligente" in questo modo. Cioè: quando disattiviamo 2, 3 o 10 (un qualsiasi numero diverso da uno) data node, il master riceve un primo messaggio che dice che il nodo A è uscito e cerca di comunicare di questo al nodo B, nodo C, nodo D.

Attualmente, l'unico modo per affrontare questa situazione è impostare un timeout per tentativi di comunicazione che durino circa 20-30 secondi, gestendo così la velocità di uscita del data center dal cluster.

Fondamentalmente, questo rientra nei requisiti inizialmente posti al prodotto finale all'interno del progetto, ma dal punto di vista della 'scienza pura' è un bug. Che, tra l'altro, è stato risolto con successo dagli sviluppatori nella versione 7.2.

In effetti, quando un certo nodo dati andava offline, risultava che diffondere informazioni sulla sua uscita fosse più importante che informare tutto il cluster su quali primary-shard fossero presenti su di esso (per promuovere la replica-shard in un altro data center a primary, permettendo così di scrivere informazioni).

Pertanto, quando tutto è finito, i nodi dati usciti non vengono immediatamente contrassegnati come obsoleti. Di conseguenza, dobbiamo aspettare che tutti i ping ai nodi dati non più attivi scadano, e solo dopo il nostro cluster inizia a comunicare che in tal punto, tal altro punto e in tal altro punto è necessario continuare a registrare informazioni. Per maggiori dettagli, puoi leggere qui. qui.

Di conseguenza, l'operazione di uscita dal data center oggi ci richiede circa 5 minuti durante le ore di punta. Per una macchina così grande e poco agile, è un risultato piuttosto buono.

Alla fine, siamo giunti alla seguente soluzione:

  • Abbiamo 360 nodi dati con dischi da 700 gigabyte.
  • 60 coordinatori per instradare il traffico su questi nodi dati.
  • 40 nodi master, rimasti come un certo eredità dalle versioni precedenti alla 6.4.0 — per affrontare l'uscita dal data center, eravamo psicologicamente pronti a perdere alcune macchine, per garantire di avere sempre un quorum di master anche nel peggior scenario.
  • Qualsiasi tentativo di combinare ruoli in un unico contenitore si è scontrato con il fatto che, prima o poi, il nodo si rompeva sotto carico.
  • In tutto il cluster è impostato un heap.size pari a 31 gigabyte: ogni tentativo di ridurre la dimensione portava al fatto che, durante le ricerche pesanti con un leading wildcard, qualche nodo veniva ucciso oppure si attivava il circuit breaker in Elasticsearch stesso.
  • Inoltre, per garantire le prestazioni di ricerca, abbiamo cercato di mantenere il numero di oggetti nel cluster al minimo possibile, per elaborare il minor numero di eventi possibile nel punto più critico che abbiamo individuato nel master.

Infine, parliamo del monitoraggio.

Affinché tutto funzioni come previsto, monitoriamo quanto segue:

  • Ogni nodo di data comunica al nostro cloud che esiste e su di esso ci sono determinati shard. Quando spegniamo qualcosa, il cluster riporta dopo 2-3 secondi che nel centro A abbiamo spento i nodi 2, 3 e 4 — questo significa che negli altri data center non possiamo assolutamente spegnere quei nodi su cui sono rimasti shard in esemplare unico.
  • Conoscendo il comportamento del master, poniamo molta attenzione al numero di task in attesa. Perché anche un solo task bloccato, se non viene esaurito in tempo, può teoricamente in una situazione di emergenza diventare la causa per cui il nostro processo di promozione dello shard replica nel primario non va a buon fine, causando l'arresto dell'indicizzazione.
  • Inoltre, monitoriamo attentamente i ritardi del garbage collector, poiché abbiamo già avuto grandi difficoltà con questo durante l'ottimizzazione.
  • Rifiuti per i thread, per comprendere in anticipo dove si trova il collo di bottiglia.
  • E le metriche standard, come heap, RAM e I/O.

Quando costruiamo il monitoraggio, è fondamentale tenere conto delle caratteristiche del Thread Pool in Elasticsearch. La documentazione di Elasticsearch descrive le possibilità di configurazione e i valori predefiniti per la ricerca e l'indicizzazione, ma omette completamente il thread_pool.management. Questi thread gestiscono, tra l'altro, richieste tipo _cat/shards e altre simili, che sono comode da usare per scrivere il monitoraggio. Più grande è il cluster, più richieste di questo tipo vengono eseguite in unità di tempo, e il thread_pool.management menzionato sopra, non solo non è presentato nella documentazione ufficiale, ma è anche limitato di default a 5 thread, che vengono rapidamente esauriti, dopo di che il monitoraggio smette di funzionare correttamente.

In conclusione, ci tengo a dire: ce l'abbiamo fatta! Siamo riusciti a fornire ai nostri programmatori e sviluppatori uno strumento che è in grado di fornire rapidamente e in modo affidabile informazioni su ciò che accade in produzione in praticamente qualsiasi situazione.

Sì, è stata un'impresa piuttosto complessa, ma, tuttavia, siamo riusciti a integrare le nostre esigenze nei prodotti esistenti, senza doverli patchare o riscrivere per adattarli.

Cluster Elasticsearch da 200 TB+

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster