
Siamo il dipartimento di sviluppo delle tecnologie per la rete di vendita al dettaglio. Un giorno la direzione ha dato l'incarico di accelerare i calcoli volumetrici utilizzando Apache Ignite in combinazione con MSSQL, mostrando un sito con splendide illustrazioni ed esempi di codice Java. Il sito è piaciuto subito. , la cui descrizione promette meraviglie: non è necessario distribuire manualmente il codice Java o Scala su ciascun nodo della rete e ripubblicarlo ogni volta che cambia. Durante il lavoro, si è rivelato che Zero Deployment presenta specificità d'uso e peculiarità che desidero condividere. Di seguito, riflessioni e dettagli sull'implementazione.
1. Formulazione del problema
La sostanza del problema è la seguente. Esiste un catalogo di punti vendita SalesPoint e un catalogo di prodotti Sku (Stock Keeping Unit). Ogni punto vendita ha un attributo "tipoNegozio" con i valori "piccolo" e "grande". A ciascun punto vendita viene collegato (caricato dal database) un assortimento (lista dei prodotti del punto vendita) e viene fornita l'informazione che, a partire dalla data indicata, il prodotto specificato
viene escluso dall'assortimento o viene aggiunto all'assortimento.
È necessario organizzare una cache partizionata per i punti vendita e memorizzarvi informazioni sui prodotti connessi fino a un mese in anticipo. La compatibilità con il sistema operativo richiede che il nodo client Ignite carichi i dati, calcoli l'aggregato di tipo (tipoNegozio, codiceProdotto, giorno, numero_punti_vendita) e li esporti nuovamente nel DBMS.
2. Revisione della letteratura
Non ho ancora esperienza, quindi inizio dalle basi. Cioè, da una panoramica delle pubblicazioni.
Articolo del 2016 contiene un rimando alla documentazione del progetto Apache Ignite e insieme una critica alla sua chiarezza. L'ho letta un paio di volte, ma non riesco a chiarirmi le idee. Mi rivolgo al tutorial ufficiale , che
ottimisticamente promette «You’ll be up and running in a jiffy!». Cerco di capire le impostazioni delle variabili d'ambiente, guardo due video su Apache Ignite Essentials, per il mio compito specifico non sono stati molto utili. Riuscire a far partire Ignite dalla riga di comando con il file standard «example-ignite.xml», creando la mia prima applicazione con Maven. L'applicazione funziona e utilizza Zero Deployment, che bellezza!
Continuo a leggere e lì c'è un esempio che utilizza subito affinityKey (creato precedentemente tramite una query SQL), e viene anche applicato il misterioso BinaryObject:
IgniteCache<BinaryObject, BinaryObject> people
= ignite.cache("Person").withKeepBinary(); Ho letto : il formato binario è qualcosa simile a una riflessione, accesso ai campi dell'oggetto per nome. Può leggere il valore di un campo senza una completa deserializzazione dell'oggetto (risparmiando memoria). Ma perché invece di Person viene usato BinaryObject, dato che c'è Zero Deployment? Perché IgniteCache<Key,Person> viene tradotto in IgniteCache<BinaryObject, BinaryObject>? Non è chiaro per ora.
Sto rifacendo l'applicazione Compute secondo il mio caso. La chiave primaria del dizionario dei punti vendita in MSSQL è definita come [id] [int] NOT NULL, sto creando una cache per analogia
IgniteCache<Integer, SalesPoint> salesPointCache=ignite.cache("spCache")Nella configurazione xml indico che la cache è partizionata
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="spCache"/>
<property name="cacheMode" value="PARTITIONED"/>
</bean>La partizione per punti vendita implica che l'aggregato richiesto sarà costruito su ogni nodo del cluster per le registrazioni salesPointCache presenti lì, dopo di che il nodo client eseguirà la somma finale.
Sto leggendo il tutorial , faccio per analogia. Avvio IgniteRunnable() su ciascun nodi del cluster, più o meno così:
@Override
public void run() {
SalesPoint sp=salesPointCache.get(spId);
sp.calculateSalesPointCount();
..
}Aggiungo la logica di aggregazione e di esportazione, eseguo su un set di dati di test. Localmente sul server di sviluppo funziona tutto correttamente.
Avvio due server di test CentOs, specifico gli indirizzi IP in default-config.xml, eseguo su ciascun nodo
./bin/ignite.sh config/default-config.xmlEntrambi i nodi Ignite si avviano e si vedono a vicenda. Specifico gli indirizzi necessari nel xml-config dell'applicazione client, che si avvia, aggiunge un terzo nodo nella topologia e immediatamente i nodi tornano a essere due. Nel log appare "ClassNotFoundException: model.SalesPoint" nella riga
SalesPoint sp=salesPointCache.get(spId);StackOverflow sostiene che la causa dell'errore è che sui server CentOs non c'è la classe custom SalesPoint. Siamo messi male. Come mai "non devi distribuire manualmente il tuo codice Java su ciascun nodo" e così via? Oppure "il tuo codice Java" non si riferisce a SalesPoint?
Probabilmente ho trascurato qualcosa — comincio di nuovo a cercare, leggere e cercare ancora. Dopo un po' mi sembra di aver letto tutto sull'argomento, non c'è più nulla di nuovo. Mentre cercavo, ho trovato alcune osservazioni interessanti.
, Lead Architect di GridGain Systems, su StackOverflow, aprile 2016:
Le classi modello non sono distribuite tra pari, ma puoi utilizzare il flag withKeepBinary()
sulla cache e interrogare i BinaryObjects. In questo modo eviterai la deserializzazione
sul lato server e non riceverai ClassNotFoundException.Un'altra opinione autorevole: , Direttore della gestione prodotto, GridGain Systems.
Articolo su Habr cita tre articoli di Denis Magda: , , 2016-2017. Nel secondo articolo, Denis suggerisce di avviare un nodo del cluster tramite MaintenanceServiceNodeStartup.jar. È possibile anche utilizzare l'avvio con xml-configurazione e riga di comando, ma dovrai caricare manualmente le classi personalizzate su ogni nodo del cluster distribuito:
Ecco fatto. Avvia il nodo utilizzando il file MaintenanceServiceNodeStartup o passa
maintenance-service-node-config.xml agli script ignite.sh/bat di Apache Ignite.
Se preferisci la seconda opzione, assicurati di costruire un file jar che contenga
tutte le classi dalle directory java/app/common e java/services/maintenance.
Il jar deve essere aggiunto al classpath di ogni nodo dove il servizio
potrebbe essere distribuito.Davvero, ecco fatto. Ecco perché esiste questo misterioso formato binario!
3. SingleJar
Denis è arrivato al primo posto nella mia personale classifica, secondo me è il tutorial più utile tra tutti quelli disponibili. Nel suo Su GitHub è presente un esempio completo di configurazione dei nodi di un cluster, che si compila senza alcuna complicazione aggiuntiva.
Seguo il modello e produco un unico file JAR che avvia il 'data node' o il 'client node' a seconda dell'argomento della riga di comando. La build parte e funziona. Zero Deployment è sconfitto.
Il passaggio da megabyte di dati di prova a decine di gigabyte di operazioni ha dimostrato che il formato binario ha una giustificazione. È stato necessario ottimizzare l'uso della memoria sui nodi, e qui BinaryObject si è rivelato molto utile.
4. Conclusioni
La prima obiezione alla chiarezza della documentazione del progetto Apache Ignite si è rivelata giustificata; dal 2016 sono cambiate poche cose. Non è facile per un principiante creare un prototipo funzionante basandosi sul sito e/o sul repository.
Dall'analisi svolta, sembra che Zero Deployment funzioni, ma solo a livello sistemico. In questo modo: BinaryObject viene utilizzato per istruire i nodi remoti del cluster a lavorare con classi personalizzate; Zero Deployment è un meccanismo interno
di Apache Ignite stesso e distribuisce oggetti di sistema attraverso il cluster.
Spero che la mia esperienza possa essere utile ai nuovi utenti di Apache Ignite.
Fonte: habr.com
