
Noi siamo il reparto sviluppo tecnologie per la rete di vendita al dettaglio. Una volta la dirigenza ha posto l'obiettivo di accelerare i calcoli complessi grazie all'utilizzo di Apache Ignite in combinazione con MSSQL, mostrando un sito con splendide illustrazioni ed esempi di codice Java. Il sito mi ha subito colpito , la cui descrizione promette meraviglie: non è necessario eseguire manualmente il deployment del proprio codice Java o Scala su ogni nodo della griglia e rieseguire il deployment ogni volta che cambia. Durante il lavoro si è rivelato che Zero Deployment ha specificità d'uso, di cui voglio condividere le peculiarità. Di seguito riflessioni e dettagli sull'implementazione.
1. Formulazione del problema
Il problema è il seguente. Esiste un catalogo di punti vendita SalesPoint e un catalogo di prodotti Sku (Stock Keeping Unit). Il punto vendita ha l'attributo "tipoNegozio" con valori "piccolo" e "grande". A ciascun punto vendita viene collegato (caricato dal DBMS) un assortimento (elenco prodotti del punto vendita) e viene fornita l'informazione che a partire dalla data indicata il prodotto specificato
viene escluso dall'assortimento o aggiunto all'assortimento.
È necessario organizzare una cache partizionata dei punti vendita e memorizzarvi informazioni sui prodotti collegati per un mese in avanti. La compatibilità con il sistema operativo richiede che il nodo cliente Ignite carichi i dati, calcoli l'aggregato di tipo (tipoNegozio, codiceProdotto, giorno, numero_punti_vendita) e lo scarichi nuovamente nel DBMS.
2. Studio della letteratura
Non ho ancora esperienza, quindi inizio col piede sbagliato. Cioè con una rassegna delle pubblicazioni.
Articolo del 2016 contiene un collegamento alla documentazione del progetto Apache Ignite e allo stesso tempo una critica alla poca chiarezza di tale documentazione. L'ho riletto un paio di volte, ma la chiarezza non arriva. Mi rivolgo al tutorial ufficiale , che
che promete ottimisticamente "Sarai operativo in un batter d'occhio!". Lavoro con le impostazioni delle variabili ambientali, guardo due video su Apache Ignite Essentials e per il mio compito specifico si sono rivelati poco utili. Avvio con successo Ignite dalla linea di comando con il file standard "example-ignite.xml", creo la mia prima applicazione utilizzando Maven. L'applicazione funziona e utilizza Zero Deployment, che bellezza!
Continuo a leggere e lì c'è un esempio che utilizza subito affinityKey (creato in precedenza tramite una query SQL), e viene applicato anche il misterioso BinaryObject:
IgniteCache persone
= ignite.cache("Person").withKeepBinary(); Ho letto : il formato binario è qualcosa come la riflessione, accesso ai campi dell'oggetto per nome. Può leggere il valore di un campo senza una completa deserializzazione dell'oggetto (risparmio di memoria). Ma perché invece di Person viene usato BinaryObject, visto che c'è Zero Deployment? Perché IgniteCache viene tradotto in IgniteCache? Non è chiaro al momento.
Sto adattando l'applicazione Compute al mio caso. La chiave primaria del catalogo dei punti vendita in MSSQL è definita come [id] [int] NOT NULL, creo una cache per analogia
IgniteCache salesPointCache=ignite.cache("spCache")Nella configurazione xml indico che la cache è partizionata
La partizione per i punti vendita prevede che l'aggregato richiesto venga costruito su ciascun nodo del cluster per i record salesPointCache presenti, dopodiché il nodo del client eseguirà il riepilogo finale.
Leggo il tutorial , faccio per analogia. Su ciascun nodo del cluster avvio IgniteRunnable(), più o meno in questo modo:
@Override
public void run() {
SalesPoint sp=salesPointCache.get(spId);
sp.calculateSalesPointCount();
..
}Aggiungo la logica di aggregazione e esportazione, avvio su un set di dati di test. In locale sul server di sviluppo funziona tutto.
Avvio due server di test CentOs, indico gli indirizzi IP in default-config.xml, eseguo su ciascuno
./bin/ignite.sh config/default-config.xmlEntrambi i nodi Ignite si avviano e vedono l'uno l'altro. Indico gli indirizzi necessari nella configurazione xml dell'applicazione client, si avvia, aggiunge un terzo nodo nella topologia e subito i nodi tornano a essere due. Nel log si segnala «ClassNotFoundException: model.SalesPoint» alla riga
SalesPoint sp=salesPointCache.get(spId);StackOverflow dice che la causa dell'errore è che sui server CentOs non c'è la classe personalizzata SalesPoint. Siamo messi male. E come è possibile che «non devi distribuire manualmente il tuo codice Java su ciascun nodo» e così via? O «il tuo codice Java» non si riferisce a SalesPoint?
Probabilmente ho trascurato qualcosa — ricomincio a cercare, leggere e cercare di nuovo. Dopo un po' ho la sensazione di aver letto tutto sull'argomento, non c'è più nulla di nuovo. Mentre cercavo, ho trovato alcune osservazioni interessanti.
, Lead Architect presso GridGain Systems, su StackOverflow, aprile 2016:
Le classi modello non vengono distribuite dai peer, ma puoi usare il flag withKeepBinary() sulla cache e interrogare gli BinaryObjects. In questo modo eviterai la deserializzazione sul lato server e non otterrai ClassNotFoundException.Un ulteriore parere autorevole: , Direttore della gestione del prodotto, GridGain Systems.
Articolo su Habr fa riferimento a tre articoli di Denis Magda: , , Negli anni 2016-2017. Nel secondo articolo, Denis propone di avviare il nodo del cluster tramite MaintenanceServiceNodeStartup.jar. Puoi anche utilizzare l'avvio con una configurazione XML e la riga di comando, ma in quel caso dovrai posizionare manualmente le classi utente su ogni nodo del cluster distribuito:
Questo è tutto. Avvia (..) il nodo utilizzando il file MaintenanceServiceNodeStartup o passa maintenance-service-node-config.xml agli script ignite.sh/bat di Apache Ignite. Se preferisci quest'ultimo, assicurati di costruire un file jar che contenga tutte le classi delle directory java/app/common e java/services/maintenance. Il jar deve essere aggiunto al classpath di ogni nodo in cui il servizio potrebbe essere distribuito.In effetti, questo è tutto. Ecco quindi a cosa serve, questo misterioso formato binario!
3. SingleJar
Denis ha occupato il primo posto nel mio ranking personale; imho è il tutorial più utile di tutti quelli disponibili. Nel suo su GitHub è contenuto un esempio completamente pronto per la configurazione dei nodi del cluster, che viene compilato senza alcun problema.
Faccio a imitazione e ottengo un unico file jar, che lancia il "data node" o il "client node" a seconda dell'argomento della riga di comando. La compilazione si avvia e funziona. Zero Deployment è stato superato.
Il passaggio da megabyte di dati di test a decine di gigabyte di produzione ha dimostrato che il formato binario esiste per un motivo. È stato necessario ottimizzare l'uso della memoria sui nodi e qui BinaryObject si è rivelato molto utile.
4. Conclusioni
La prima critica alla scarsa chiarezza della documentazione del progetto Apache Ignite si è rivelata fondata; dal 2016 non è cambiato molto. Per un principiante è difficile creare un prototipo funzionante basato sul sito e/o sul repository.
Alla fine del lavoro svolto, ho avuto l'impressione che Zero Deployment funzioni, ma solo a livello di sistema. Più o meno: BinaryObject viene utilizzato per insegnare ai nodi cluster remoti a lavorare con le classi utente; Zero Deployment è un meccanismo interno
di Apache Ignite stesso e distribuisce nel cluster oggetti di sistema.
Spero che la mia esperienza possa essere utile ai nuovi utenti di Apache Ignite.
Fonte: habr.com
