Hazelcast Jet est un nouveau venu sur le marché des solutions de Stream Processing distribué. Appuyé sur la grille de données en mémoire bien connue Hazelcast In-Memory Data Grid, ce nouveau produit (version 0.3 publiée en février 2017) mérite que l’on s’y intéresse malgré sa jeunesse.
Je vais présenter ses fonctionnalités majeures, ses points forts et faibles actuels, et la roadmap annoncée de ce qui sera peut-être un produit incontournable du Stream Processing dans les années à venir.
Data Creativity, comment interpréter les tendances consommateurs grâce au Dat...
Stream processing en mémoire avec Hazelcast Jet par Claire VILLARD
1. Stream Processing en mémoire avec HazelCast Jet
Claire Villard
neur0nia
leneurone/hz-jet
1 / 14
2. Claire Villard
Développeuse Java depuis 2011
Société V3D
Travaille avec HazelCast IMDG depuis 2 ans
Membre de Duchess France
Organisatrice du LyonJUG
2 / 14
3. Qu'est-ce qu'HazelCast IMDG ?
IMDG = In-Memory Data Grid, Grille de données en mémoire
Stockage distribué de structures de données (Map, List, AtomicLong, ...)
Calcul distribué sur ces structures
Clustering
Java-based
Open-source
3 / 14
4. Qu'est-ce qu'HazelCast Jet ?
Solution de stream et batch processing basée sur HazelCast IMDG
Sauf mention contraire, les schémas proviennent de https://jet.hazelcast.org/
4 / 14
6. Fonctionnalités
Nombreuses entrées / sorties
Faible latence
Contrôle du débit
Support des traitements batchs comme des streams finis
Sliding windows
Facilement extensible
En v0.5 :
Tolérance aux crashs de noeuds avec redémarrage des jobs
Garantie de traitement "au moins 1", "exactement 1" ou "au mieux" des messages
6 / 14
9. DAG
DAG dag = new DAG();
// Création des noeuds de traitement
Vertex source = dag.newVertex("source", Sources.readMap("inputMap"));
Vertex enricher = dag.newVertex("enricher", MetricEnricher::new);
Vertex output = dag.newVertex("output", Sinks.writeMap("outputMap"));
Vertex errorOutput = dag.newVertex("errorOutput", Sinks.writeMap("errorOutputMap"));
// Création des arêtes du graphe entre les noeuds
dag
.edge(Edge.between(source, enricher))
.edge(Edge.from(enricher, 0).to(output))
.edge(Edge.from(enricher, 1).to(errorOutput));
// Démarrage de Jet
JetInstance jet = Jet.newJetInstance();
// Démarrage du Job et attente du résultat
jet.newJob(dag).execute().get();
9 / 14
10. Processor
public class MetricEnricher extends AbstractProcessor {
private IMap<Integer, Customer> customerMap; // IMap des Customers
@Override
protected void init(@Nonnull Context context) throws Exception {
// Utilisation de l'instance HazelCast sous-jacente
customerMap = context.jetInstance().getHazelcastInstance().getMap("customers");
}
@Override
protected boolean tryProcess0(@Nonnull Object item) throws Exception {
Metric metric = (Metric) item;
// On tente de trouver le customer associé à la métrique dans une IMap
Customer customer = customerMap.get(metric.getCustomerId());
// On choisit l'arête du graphe à utiliser
if (customer != null) {
return tryEmit(0, new EnrichedMetric(metric, customer));
} else {
return tryEmit(1, metric);
}
}
}
10 / 14
11. Stream Processing
public class QueuePoller extends AbstractProcessor {
private IQueue<Metric> inputQueue; // Queue d'entrée
@Override
protected void init(@Nonnull Context context) throws Exception {
inputQueue = context.jetInstance().getHazelcastInstance().getQueue("inputQueue");
}
// Utilisation d'un thread dédié obligatoire car poll(int, TimeUnit) est bloquante
public QueuePoller() { setCooperative(false); }
@Override
public boolean complete() {
try {
Metric metric = inputQueue.poll(20, TimeUnit.MILLISECONDS);
if(metric != null) {
tryEmit(metric);
}
return false; // execution infinie tant que complete() retourne false
} catch (Exception e) {
return true; // arrêt de l'exécution
}
}
}
11 / 14
12. Performances
Intel® Core™ i7-5600U CPU @ 2.60GHz × 4
16Go RAM
Fedora 26 64 bits
JVM Oracle HotSpot 1.8.0_121
Configuration de Jet par défaut, 2 noeuds locaux
Batch processing - 1 million de Metric
Temps moyen d'exécution du Job : 22s, soit environ 45 400 items / seconde
Stream processing
Injection de Metric dans la queue et calcul de la latence totale
Latence moyenne : 2 ms, latence max. sur 100 000 éléments : 27 ms
12 / 14
13. Limitations
Qualité de la documentation...
Pas de typage des entrées, sorties, ou arêtes entre noeuds, tout est Object.
13 / 14