Ce talk est un retour d’expérience sur la mise en œuvre de Spark et Streaming Spark. Nous aborderons :
La collecte des données à la volée dans l’application Web avec Akka
La séparation des producteurs et consommateurs avec Kafka
La transformation des données avec Spark et Streaming Spark
Le déploiement sur un cluster avec Apache Mesos
12. #IaaC
Création d’un Acteur
class MonActeur() extends Actor {
def receive = {
case MonMessage(param1: String, param2: String,
param3: String, param4: String) =>
// Code de logging
case
}
}
@jpbunaz
13. #IaaC
Envoi du message à l’acteur
// Initialisation de l’acteur
val monActeur = actorSystem.actorOf(Props[MyActeur])
// Initialisation du message
val monMessage = MonMessage("value1", "value2",
"value3", "value4")
// Envoi aynchrone du message à l’acteur
monActeur ! monMessage
// Code exécution avant traitement du message
ExecuterLaSuiteDansLaFoulée()
@jpbunaz
14. #IaaC
Acteur : Points de vigilance
N’expose pas son état
interne
class UglyActeur() extends Actor {
var variableCanAccess = null
def receive = {
case String =>
// My acteur code…
}
}
@jpbunaz
15. #IaaC
Acteur : Points de vigilance
Les messages doivent
être immuables
case class UglyMessage(
var param1: String,
var param2: String)
@jpbunaz
16. #IaaC
Acteur : Points de vigilance
TASK
Working…
@jpbunaz
• L’acteur ne traite qu’un seul message à la fois
• Les messages sont mis en attente dans une boite aux
lettres
17. #IaaC
Maitriser le nombre d’acteurs
Nombre
d’Acteur !!!
Un message
à la fois !!!
Utiliser un router
@jpbunaz
18. #IaaC
Routeur
• Maîtriser le nombre d’Acteur
• Différents types de routage (RoundRobin, Random …)
• Configuration externalisée dans un fichier de propriétés
@jpbunaz
19. #IaaC
Créer un routeur
val monRouteur = actorSystem.actorOf(
FromConfig.props(routeProps = Props[MonActeur])
, name = "monRouteur"
)
@jpbunaz
21. #IaaC
Conclusion sur les Acteurs
• Simple à mettre en oeuvre
• Contrôle sur les ressources en adéquation avec la
charge
• Gestion multithread transparente, pas de lock, de
synchronized
• Naturellement asynchrone
@jpbunaz
24. #IaaC
Avant les messages groups
U2E3
U1E3
U2E2
U1E2
U2E1
• Solution traditionnelle : Un seul consommateur pour toute la file
U1E1
U2E3
U1E3
U2E2
U1E2
U2E1
U1E1
@hayssams
25. #IaaC
Avec Kafka : partitionnement par clef
U2E3
U2E2
U2E1
U1E3
U1E2
U1E1
U2E3
U2E2
U2E1
U1E3
U1E2
U1E1
Cluster Kafka
P1R1
P2R1
P1R2
P2R2
Pro
Cons
Cons
Avec JMSGroupID
• Un local manager (SPOF) plusieurs remote
• Requiert un serveur de backup
@hayssams
Avec Kafka
• Support natif du partitionnement
• Réplication des messages
• Tolérance au pannes
27. #IaaC
• Récupération du Tuple(request, response, session, url)
• val tuples = kafka.initStream(context, "requests », 2 seconds)"
• Validation des règles
• rdd = tuples.filter( t => RulesHandler.match(t))"
• Transformation du tuple en document JSON
• rdd2 = rdd.map( t => toDocument)"
• Injection dans ES
• rdd2.foreachRDD(doc => es.insert doc)"
• Identification des relations
• rdd3 = rdd.flatMap(_.toRelations)!
• rdd3.foreachRDD(rel => neo4j.insert rel)"
=> Statistiques d’accès en temps réel
Traitement continu des accès utilisateurs
@hayssams
28. #IaaC
Avec Spark: API unique pour la batch et le streaming
Flux continu provevant de réseau
2s
2s
2s
2s
2s
2s
2s
t
t +16
• Découpage du flux en un paquet de données
(RDD) toutes les 2 secondes
• Un RDD est une collection de données
RDD
RDD
RDD
RDD
RDD
RDD
RDD
• Chaque paquet est traité comme un comme
un RDD soumis au batch Spark classique
Out
Out
Out
Out
D
Out
D
Out
Out
• Spark exécute les opérations sur le RDD
comme dans un batch classique et renvoie
le résultat en retour.
Spark
• Exécution de microbatchs
@hayssams
29. #IaaC
Avec Spark: Tolérance aux pannes au coût minimum
val tuples = kafka.initStream(context,"requests », 2 seconds"
!
rdd = tuples.filter( t => RulesHandler.match(t))"
"
rdd2 = rdd.map( t => toDocument)"
"
rdd2.foreachRDD(doc => es.insert doc) // via Kafka"
!
rdd3 = rdd.flatMap(_.toRelations)!
!
rdd3.foreachRDD(rel => neo4j.insert rel) // via Kafka
KafkaInputDStream
FilteredDStream
MappedDStream
ForEachDStream
MappedDStream
ForEachDStream
• Le code ci-dessus ne génère aucun calcul, juste un graphe d’objets
• Le Scheduler Spark va soumettre le graphe d’objets aux workers pour exécution
• J En cas de panne, il suffit juste de soumettre à nouveau le graphe d’objets à un autre worker.
• Pas besoin de réplication des résultats ou d’upstream backup
@hayssams
34. #IaaC
Pourquoi Zookeeper
• Election de leader pour la tolérance au pannes
Maitre
Esclave
Esclave
Esclave
Maitre de secours
Esclave et maitre de secours
Esclave et maitre de secours
Esclave et maitre de secours
Esclave et maitre de secours
Election de leader
Avec Zookeeper
Tout noeud est un master potentiel
@hayssams
35. #IaaC
Pourquoi Zookeeper
• Centralisation de la configuration
/
services
…
master
nodes
es
node1
node2
node1
Zookeeper
Server 1
Server 2
Leader
Service
Service
1.Enregistrementdesservices
Client
2. Récupération de la localisation des workers
4. sollicitation du service
3. Sélection du worker
@hayssams
37. #IaaC
Avant Mesos Démultiplication nombre de VMs
• €€€ Cluster Tomcat : Frontend facing app
• € Cluster Kafka : Middleware de messages
• €€ Cluster Spark
• €€€ Cluster ElasticSearch
• TTT : Compléxité de configuration
• Apache Mesos et Marathon à la rescousse
• Voir l’ensemble des VMs comme une seule machine sur laquelle tournent plusieurs
JVMs
@hayssams
38. #IaaC
Avant Mesos Démultiplication nombre de VMs
Dev.
Int.
PréProd.
Prod.
• Requiert d’exécuter un OS en
entier pour obtenir une isolation
des ressources et de la sécurité
• Temps de démarrage assez long
(5 à 10 minutes par VM)
• Plus d’OS => encore plus de
systèmes à administrer
• Coût de licence des VMs
• Allocation statique => Sous
utilisation de la CPU
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
VM
@hayssams
39. #IaaC
Avec Linux cgroups
OS Hôte
OS Guest
OS Guest
OS Guest
App1
App2
App3
OS Hôte
App1
App2
App3
• Isolation
• CPU
• Mémoire
• I/O
• Réseau
VM
Linux cgroups
@hayssams
40. #IaaC
Avec Mesos
Serveur
Serveur
Serveur
Serveur
80 CPU, 640Go
App
App
App
App
App
App
App
App
App
• J Partage des ressources
• J Tolérant aux pannes
• Pour les applications longue durée (MOM / AS)
• Si vous n’avez jamais cherché à savoir sur quel cœur s’exécute
votre tâche alors vous n’avez probablement pas besoin de
savoir non plus sur quel serveur.
• IaaC : Infrastructure as a (Single) Computer
• Faire fonctionner les différents environnements (dev / Int/
Preprod / Prod) sur la même infrastructure
• Y compris les jobs Jenkins
@hayssams
41. #IaaC
Architecture Mesos
Mesos Master
Mesos Worker
Mesos Worker
MonAppScheduler
MonAppExecutor
MonAppExecutor
2CPUs, 20Go
Tâche
• Pour s’exécuter sur Mesos une application doit
implémenter :
• Un scheduler
• Un Executor
@hayssams
43. #IaaC
Pourquoi Marathon
• Eviter d’avoir à développer un Executor et un Scheduler pour les
applications « longue durée »
• Marathon permet via une API REST de configurer des instances
applicatives au dessus de Mesos en indiquant la commande à
lancer
@hayssams
44. #IaaC
Exemple de commande Marathon
POST /v2/apps HTTP/1.1"
"
{"
"id": "TomcatApp","
"cmd": "/path/bin/catalina.sh run $PORT","
"mem": 1024,"
"cpus": 2.0,"
"instances": 3,"
"constraints": ["
"
"
]"
}"
"
• Marathon utilisé pour lancer
• Kafka
• ElasticSearch
• Tomcat
• Scale up/down par simple appel REST avec une nouvelle configuration
Régulation de charge et découverte
GET /apps/MonApp/tasks
Hot haproxy.cfg reload
@hayssams
["hostname", "UNIQUE", ""],!
["hostname", ”like", ”front{1,2}"]