3. •Les besoins du projet AFP twitter-foot
•Présentation de Redis
•Manipuler des tweets avec Storm
•Implémenter des fenêtres glissantes
•Testabilité du cluster
•Monitoring et supervision
•Débogage et bonnes pratiques
4. •Plus de 7000 comptes twitter référencés par l’AFP
•5 ligues de football suivies
•Jusqu’à 170 tweets par seconde
•Recherche de tendances sur les hashtags
•Classements de popularité de joueurs / équipes et panelistes
•Des timelinesde tweets par ligue, par équipe et par matches en live
7. •Utilisation de Storm pour le tri des tweets reçus, et la recherche de mots clé
•Utilisation de Redis comme queue pour le flux d’entrée
•Utilisation de Redis pour la gestion et le stockage des timelines
•Serveur Web Services REST (Jetty)
Cluster de 7 serveurs en toutpour le backend
9. •Datastorede type Key / Value
•Données en RAM uniquement
•Implémentation en C ANSI
•Monothreadé
•Support de publish/ subscribe
•Communication sur TCP avec protocole spécifique
•Nombreux clients disponibles en divers langages
•Sponsorisé par Pivotal
10. Parmi les applications reposant sur redis on retrouve: StackOverflow, Github, Pinterest, Flickr, Snapchat… et Twitter!
Redis est notamment utile pour
•Améliorer les performances d'une base de données (MySQL, MongoDB…)
•Gérer finement un cache applicatif
•Traiter des statistiques et des classements
•Servir de Message Broker et gérer des notifications entre applications
Redis est un vrai couteau suisse!
11. "Bad programmers worry about the code. Good programmers worry about data structures and their relationships." L. Torvalds
Structures disponibles
•Les sets
•Les listes
•Les hashes
•Les strings
•Les bitmaps
•Les HyperLogLogs
•Les Sorted Sets
12. •Notion de score par élément (stocké en tant que "double" soit 64 bits mais 53 bits significatifs seulement)
•Récupération d’un ensemble d’éléments par leurs positions ou leurs scores
•Implémentation via des skip-listset des hashsetsassurant des performances élevées
•Utilisation documentée permettant notamment de calculer avec précision le coût des requêtes effectuées
•La performance élevée implique néanmoins une occupation mémoire supérieure aux structures classiques
13. •ZADD ajoute un élément à un ZSET avec un score
•ZINCRBY incrémente le score d'une valeur choisie
•ZRANGE récupère une plage d'éléments par leur index défini par leur score (plus petit au plus grand): idéal pour un classement (les 10 meilleurs par exemple)
•ZRANGEBYSCORE récupère une plage d'éléments dans un intervalle de scores (score entre 5 et 10…)
15. •Utilisation de tweets comme valeurs dans un ZSET et utilisation du Tweet ID comme score
•Timelinesde tweet ordonnancées par tweetid: chronologie respectée
•Plus récent: tweet id le plus élevé (snowflakele garantit)
•Utilisation de tweets comme valeurs dans un ZSET et du nombre de retweets comme score
•Classement des tweets les plus retweetés
16. 22:04:41:524652515665915905:nicolas_vilas:RTcount=0:Une action de David Luiz qu'on risque de revoir... en boucle #APOELPSG
profiles=["JRNL"] teams=["NEUTRAL"] leagues=["FRAL1"]
22:04:33:524652479569752065:NikoB19:RTcount=0:Tous les matchs sur Bein(sauf Porto -Bilbao) sont joués, je file à la douche en espérant un but parisien.
profiles=["BLOG"] teams=["LENS"] leagues=["FRAL1"]
22:04:23:524652438729416704:PSG_inside:RTcount=31:57' Sauvetage de @DavidLuiz_4 sur la ligne Parisienne ! Corner pour l'@apoelfcofficial. #APOELPSG
profiles=["TEAM"] teams=["PSG"] leagues=["FRAL1"]
22:04:11:524652387664158720:Gibney_A:RTcount=1:WOW. So close to a goal. David Luiz clearsa header off hisownline.
profiles=["JRNL"] teams=["LILL"] leagues=["FRAL1"]
22:04:08:524652374439493632:RemDenjean:RTcount=0:#Maxwell est vraiment un très grand footballeur: professionnel, classe, talentueux, combattif... L'une des meilleures recrues du PSG 2.0! profiles=["TEAM"] teams=["TOUL"] leagues=["FRAL1"]
Score
524652515665915905
Score
524652479569752065
Score
524652438729416704
Score
524652387664158720
Score
524652374439493632
ZSET "timeline"
Les valeurs contiennent le JSON
Les scores sont les tweet ids
17. Les opérations sur ZSET sont majoritairement en O(log(N))
•ZSCORE est en O(1)
•ZADD est en O(log(N)) avec N le nombre d'éléments dans le ZSET
•ZINCRBY est en O(log(N)) avec N le nombre d'éléments dans le ZSET
•ZRANGE est en O(log(N) + M) avec N le nombre d'éléments dans le ZSET et M le nombre d'éléments retournés
18. •Clusterisationen beta ou à faire manuellement, difficile à réaliser
•Pas de "rollbacks" de transactions
•La persistance des données a un impact sur les performances dans les deux modes proposés
•Le mode par défaut de persistance peut perdre des données en cas de crash
•Tout est en mémoire RAM, attention aux leakset aux Out-of-memory!
•Pas de version windowsofficielle (mais il existe un port)
•Intégration à Java minimale mais suffisante (Jedis, Spring-redis)
19. •Les tweets idssont ordonnancés chronologiquement (snowflake), les timelinessont faciles à gérer via des SortedSet
•Utilisation du tweet id comme score pour les timelines
•Utilisation du tweet id comme valeur pour les autres classements (retweets, mots-clé…)
•Performances élevées en accès aux données et en débit
•Un datastoreà la complexité modérée et au coût d'entrée faible
•Intégration facile avec Storm
•Perdre quelques tweets n'est pas (si) important
21. 1.Utilisation de la connexion hosebirdvers twitter alimentant une queue redis
2.Récupération des messages twitter depuis Redis via un Spoutdédié
3.Définition de divers streamsen Storm pour le traitement des tweets
4.Stockage des résultats dans Redis
Twitter-feeder
Hosebird
Redis
SpoutStorm
"Raw" BoltStorm
Alimentation
Queue
Dirty check queue
Emission des tuples
Twitter
Création des streams
23. •Recherche de mots-clédivers
•Classement de joueurs via liste de mots clé
•Classement d'équipes
•Classements des hashtags populaires
•Classements des tweets les plus retweetés
•Classements des comptes twitter les plus actifs
•Recherche de médias: images / vidéos
•Croisement avec des données journalistiques du bureau des sports
24. •Configuration stockée en JSON dans Redis
•Spoutsde configuration sur divers thèmes
•Dirty check de clés de configuration sur Redis
•Envoi de la nouvelle configuration en tant que tuplesi changement détecté
Redis
Spoutde configuration
Boltsabonnés au Stream
de configuration
Dirty check
de la configuration
Serveur manager des configurations
Changement de la configuration
dans redis
25.
26.
27. Pour améliorer les performances, plusieurs solutions:
•Augmenter le nombre d'Executors
•Augmente le nombre de threads s'exécutant sur le Bolt/ Spoutconcerné dans le cluster
•Limitation par le nombre de CPU disponibles sur le cluster avec / sans Hyperthreading
•Augmenter le nombre de Tasks
•Revient à augmenter le nombre d'instances du Bolt/ Spoutconcerné dans le cluster
•Changer le design applicatif / algorithmes utilisés
28. Le livrable de Storm est simple: Jar contenant la topologie
•Peu lié aux spécificités du runtimedu cluster Storm
•Corriger une erreur de design interne est donc plus facile lors des montées de version
•Le refactoringest donc encouragé
La difficulté dans l'usage de Storm se trouve autant dans le développement que dans l'administration du cluster. Plusieurs options (cumulables):
•Soyez / devenez DevOps
•Chouchoutez votre administrateur système / réseau
•Optez pour une solution Cloud
30. •Parcours d'un itérablesur un nombre fixe de n éléments
•Cet itérableest peuplé de nouvelles données au fur et à mesure
•Eviction des données trop anciennes
•Utilisation possible pour le calcul de débits en "live"
•Bande passante utilisée
•Occurrence de mots clé
31. •Choix d'une durée pour la fenêtre
•les 15 dernières minutes
•Choix d'une fréquence de calcul
•MAJ toutes les 5 secondes
•Comptage du nombre de tweets dans une structure adaptée
•Rolling buffers, zsets…
•Le résultat donne un quotient de tweets par seconde
•débit "live" de 35 tweets par seconde basé sur le nombre de tweets reçus des 15 dernières minutes, recalculé toutes les 5 secondes
32. Storm peut servir à calculer des fenêtres glissantes (SlidingWindow)
•Chaque donnée possède un timestampqui permet de calculer son éligibilité aux fenêtres glissantes
•Un buffer en mémoire représentant la fenêtre glissante compte les occurrences d'une donnée choisie sur une période donnée
•Une tâche calcule le débit à intervalle régulier
Deux outils sont fournis et documentés avec Storm pour cet effet
•Les Ticktuples
•Les rollingbuffers
33.
34. •Un Boltde type "Map" émet des éléments individuellement
•Un Boltde type "Reduce" s'abonne au Bolt"Map" en fieldgrouping
•Stockage dans un buffer in-memory des éléments reçus et du nombre de leurs occurrences
•Emission d'un Tuple"résumé" périodiquement grâce aux TickTuples
•Un Boltde type "Ranker" récupère les résultats de tous les types "Reduce" et calcule le résultat
35. Pour réaliser une SlidingWindowen Redis, il suffit de stocker les données brutes de comptage en tant que ZSET sur une unité de temps choisie (minute, heure, jour…)
Quand on désire calculer les valeurs finales, il suffit de réaliser un ZUNION qui additionne les clés ZSET choisies en produisant un ZSET des résultats
Ronaldo:1
Ribery:2
Messi:1
Ronaldo:3
Messi:2
Ronaldo:4
Messi:3
Ribery:2
players:23h00
players:23h01
players:23h02
players:current-ranking
ZUNION des 3 dernières minutes
Exécution toutes les minutes
36. Implémentation Storm
•Permet de faire du Map-Reduceefficacement
•Nettoyage des buffers auto-gérépar les structures fournies
•Utilise la RAM JVM, ce qui peut donner un Out-of-memory détruisant le Workeret pouvant perdre les données du buffer en cours
Implémentation Redis
•Données brutes dans Redis: facilement auditable
•Pas de pertes de buffers lors d'un crash de workerStorm
•Utilise la RAM Redis, attention au Out-of-memory
•Nettoyage des valeurs dans Redis manuel
•Ajoute de la charge sur Redis
38. •Technique permettant de valider une fonctionnalité par l'exécution de tests (avec succès)
•S'apparente à un test de type "boîte noire" en mode End-to-End
•Il est possible d'intégrer ce mode de validation dans un processAgile
39. •Framework de tests permettant la mise en place de tests d'acceptance
•Ecrit originellement en Ruby mais porté en Java (entre autres)
•Utilisation de Domain SpecificLanguage(DSL) pour décrire les tests
•Fonctionne avec JUnit, Mockito
40. Feature: Top N of playersin the global timeline.
Scenario Outline: : Player appearsin the tweet.
Givena panelistfor the league"<League>"
And the playerkeyword is"<Keyword>"
Whenthe panelisttweets "<Tweet>"
Thenthe global playercounterof "<Keyword>" is1
Examples:
| League | Keyword | Tweet |
| FRAL1 | Lucas Deaux| Le milieu Lucas Deauxest la révélation de cette année |
| ENGL1 | ZatKnight | The best central defender isZatKnight |
Scenario: Player appearsin the beginningof the tweet.
Givena panelist
And the playerkeyword is"Djordjevic"
Whenthe panelisttweets "Djordjevicne restera malheureusement pas nantais l'an prochain"
Thenthe global playercounterof "Djordjevic" is1
41. •Cucumberest appelé depuis un Test JUnit(Runnerspécifique)
•La featureCucumberest parsée
•Une classe "StepDefs" Java est appelée par Cucumber
•Cucumbermatche les phrases du scénario à des méthodes Java
•Via des annotations: @Given@When@Then
•Utilisation de RegExp: "^the global player counter of "([^"]*)" is (d+)$"
•Cucumberexécute les méthodes et injecte les paramètres définis dans le scénario
•JUnitdonne le résultat du test
42. Le déroulement d'un test donne
1.Une phase de préparation démarre la topologie et initialise les données dans le Redis de test
2.L'exécution du scénario de test simule l'arrivée d'un tweet forgé dans Redis
3.L'application Storm dans le cluster local de test traite le tweet et stocke le résultat dans le Redis de test
4.L'assertion définie dans Cucumberest exécutée et donne un reporting, par exemple un polling sur Redis vérifiant la valeur d'un compteur
5.Si la featureCucumbercontient d'autres scénarios ils sont exécutés 1 à 1
6.La phase terminale du test stoppe le cluster et nettoie le redis de test
La topologie de test n'est donc pas redémarrée à chaque test ("scenario") pour diminuer le temps d'exécution
43. Il est souhaitable d'avoir des tests End-to-End dans une application Storm pour
•Faciliter le débogage
•Documenter les fonctionnalités
•Eviter les régressions
Néanmoins les tests sont coûteux à maintenir au fil des évolutions de l'applicatif
•Les tests avec mockscomplexes sont "fragiles"
•La non maintenance des tests signifie leurs morts
•Sans implication d'un membre de la partie métier, cela ne restera qu'un outil de développeur
46. •Création d’artifactszip via Mavenpour chaque serveur
•Scripts pour toutes les tâches courantes (MAJ configuration, restart, etc)
47. •Scripts de redémarrage de process
•Supervision du CPU et de la RAM
•DSL avancé de configuration
check processredis-server
withpidfile"/var/run/redis.pid"
startprogram = "/etc/init.d/redis-server start"
stop program = "/etc/init.d/redis-server stop"
if 2 restartswithin3 cycles thentimeout
if totalmem> 7000 Mb thenalert
if cpuusage > 95% for 3 cycles thenrestart
if failedhost 127.0.0.1 port 6379 thenrestart
if 5 restartswithin5 cycles thentimeout
48.
49. Redis-rdb-toolsest un parserde dump Redis de type "RDB"
•Permet l'audit des clés d'une instance en mode "offline"
•Calcul approximatif de l'espace occupé de chaque clé de l'instance
50. Redmonet RedisLivesont des outils de monitoring de Redis en live
•Accès au slowlog(requêtes les plus longues)
•Informations sur la mémoire (occupation, fragmentation)
•Aperçu des structures de données utilisées dans l'instance
52. L'architecture Storm + Redis est très distribuée, par conséquent fixer (trouver) un bug peut devenir un vrai challenge
Pour éviter un coût de maintenance élevé et s'assurer la pérennité de l'application, il faut éviter de cumuler les problématiques au même endroit
L'outil Sonar est un moyen utile de surveiller le projet
53. •Séparer l'action (Boltd'action) de la condition (Boltde contrôle)
•Séparer l'insertion de résultat dans Redis de son nettoyage
•Utiliser des design patterns: Strategy, Chain of Responsibility…
Une séparation plus extrême consiste à définir plusieurs topologies
•Communication entre topologies assurées par un élément externe (Redis par exemple)
•Audit facilité des problèmes
•Meilleure testabilité
•Meilleure maintenabilité
•Meilleure robustesse
•Nécessite plus de workersStorm (1 workerne sert qu'une seule topologie)
•Permet de faire de la pseudo QoSsur des topologies
54. •Tracer les tuplesnaviguant dans une topologie est utile
•Débogage plus facile
•Audit de performances
•Ajouter un objet "espion" dans chaque streampeut servir à cet effet
•Ajouter le nom de chaque Bolttraversé
•Chronométrer le temps passé dans chaque Boltou méthode de Bolt
•Garder une trace de certains tests métier
•Certains bugs sont difficiles à reproduire avec Storm, aussi, avoir de bons logs peut grandement aider aux fixes
55. •Redis est un stockage temporaire dans notre modélisation
•Chaque entrée doit être nettoyée à un moment donné
•Il est important d'être rigoureux dans le référencement de clés afin d'éviter les leakset de faciliter le débogage
•Le format des données insérées est aussi important, l'utilisation de standards peut grandement aider: json-schema, XSD, DTD…
•Une bonne méthode est de séparer les tâches d'insertion des tâches de suppression
•Bolts/ Spoutsdifférents
•Topologies différentes
56. •Redis supporte Luanativement
•Comme Redis est monothreadé, aucune requête redis n'est effectuée pendant l'exécution d'un script Luaen parallèle
•Un script Luaest donc atomique sur une instance Redis
•Luapermet d'éviter des round-trips réseau
•Possibilité d'utiliser la librairie cjsonen Luaainsi que MSGPACK qui permet de compresser les données JSON