À l’automne 2014, M6 décide d’adapter le programme Rising Star en France, un concours de chant en direct, mais dont le jury est le public, qui vote en direct depuis son application mobile.
A travers cette conférence, je me propose de vous présenter l’architecture mise en place pour être capable de traiter plusieurs dizaines de millions de votes dans un délais de quelques secondes, tout en se synchronisant avec une émission de télé en direct.
Le groupe M6 est le second groupe de télévision privé français.
5 chaines TV principales (M6, W9, 6ter, Paris Première et Téva)
3 stations de radio (RTL, RTL2, Fun Radio)
Le groupe M6 est la propriété de RTL Group (Luxembourg), qui possède également des chaines en Allemagne (nous y reviendrons)
Je suis actuellement en délégation auprès de la société Elephorm, en tant que CTO suite à la prise de participation de M6
Elephorm est une société spécialisée dans le e-learning. Nous produisons et diffusion nos formations.
Nous sommes spécialisés dans les métiers créatifs (Photographie, Vidéo, DAO, MAO, BIM, …)
Pour ceux qui veulent en savoir plus, je vais faire une présentation de Sylius vendredi, utilisé lors de la refonte de la plateforme.
Si nous revenons à nos moutons, en 2014, je travaillais sur le service de télévision de rattrapage du groupe, nommé 6play.
Présentation de 6play
Télé de rattrapage (catchup TV)
multi-écran (9 écrans)
Pour les 5 chaines du groupe (3 gratuites, 2 à péage)
12M de comptes (66M d’habitants, 52M de plus de 14 ans), soit 25% de la population de plus de 14 ans
En 2013, le groupe M6 acquiert les droits du programme RisingStar.
Le concept d’origine est Israëlien est a connu de très fortes audience lors de la saison 1
Plusieurs chaînes de différents pays ont rachetés le concept pour une diffusion locale, dont RTL Group pour une diffusion en France sur M6 et en Allemagne sur la chaine RTL
Le principe de RisingStar est assez semblable à celui de La Voix.
Les candidats se présentent, chantent derrière un mur.
Ils disposent du temps de leur prestation pour obtenir suffisamment de vote.
Si le candidat atteint un certain seuil de vote positif, le mur se lève et le candidat est qualifié.
La principale différence est que tout le monde peut devenir jury, depuis son canapé, devant sa télévision, et agir en direct sur la jauge.
Une fois connecté, chaque prestation se découpe en 3 phase :
enregistrement (je désire voter) : pendant la présentation du candidat, permet de déterminer la base 100
vote : pendant la prestation l’utilisateur peux dire “oui” ou “non”. Seuls les votes positifs sont comptabilisés, tous sont loggés
résultat : confirmation de la prise en compte du vote, affichage du résultat
Vu les audiences télé atteintes en Israel, le ambitions étaient importantes pour la diffusion française.
Nous devions être capable de gérer 10M de votants connectés.
Les périodes de checkin et de vote étant de 2mn, nous devions être capable de gérer des pics de 100k votes seconde.
Le mur de connexion : une décharge très brutale de requêtes, sans possibilité de chauffe
Nous avions également 2 contraintes importantes :
Il existe un différé de 30s entre le direct et la diffusion (contrainte légale)
Il faut garder la trace de tout les votes, pour validation par un huissier de justice
Au moment où le projet nous était annoncé, nous avions 8 mois pour nous préparer.
Le backend de notre plateforme technique est en PHP, et les développements les plus récents étaient basés sur Symfony.
Nous avions soit le choix de prendre le langage le plus adapté à la problématique, mais devoir monter en compétence sur le sujet
Soit de voir comment l’outil que nous maîtrisons peux répondre aux problématiques
Pour l’anecdote, nos collègues allemands, également spécialisés en PHP, ont fait le choix de Java, alors que nous choisissons PHP.
Ils ont éprouvés plus de difficultés que nous car la montée en compétence a été dure, là où nous parlions juste d’architecture.
Plus le processus est complexe, plus il sera long à s’exécuter.
De la même manière, plus le processus dépend de services externes, plus il va attendre
Sur des fortes volumétries, l’attente, c’est un goulot d’étranglement : une machine occupée qui ne fait rien.
Il faut découper les traitements au maximum- Permet de scaler les parties lentes- Permet de traiter en asynchrones les traitements longs
Le secret ? Les files de messages
Permet de répondre rapidement “on a pris en compte le message”, puisque le traitement “J’ai mis le message dans la queue est très rapide”.
Permet de scaller très facilement, en augentant les subscribers
Un surcapacité se traduit en retard de traitement, pas en augmentation des temps de réponse brutes
Nous avons beaucoup utilisé ce paradigme et nous mis à disposition un Bundle Symfony pour répondre à ce besoin
Mais nous sommes sur de telles volumétries que nous avons tenté d’isoler les SPOF/goulots d’étranglements.
Nous avons donc décider de se baser sur des services concus pour gérer de très fortes charges.
En 2014, AWS était la solution la plus crédibles :
surcouche pour gérer la forte charge et la scalabilité
possibilité de scaller on demand
Lors de la répétition générale, nous avons lancé le provisionnement de 264 VM S … et nous avons été contacté par un technicien de AWS pour nous dire qu’ils n’avaient pas la capacité de livrer autant de machine sur le moment.
Ne pas oublier que le “cloud”, c’est surtout le système de quelqu’un d’autre, qui n’est pas sans craindre des pannes (AWS Outage de mardi 28/02)
Notre secret, c’est de ne pas mettre PHP directement devant le client.Nous avons fait en sorte que les outils reconnus comme étant très adaptés aux fortes charges soient directement devant.Les devices communiquent directement les infrastructures AWS.
PHP est utilisé pour le code métier qui dépile les messages.En cas d’erreur, tout sera silencieux.En cas de dépassement de capacité, les messages seront traités en retard, mais pris en compte.
En travaillant autant sur les workers, nous avons gagné de l’expérience sur ce fonctionnement, et nous avons investi sur 2 bundles autour de ces concepts
Le Daemon bunde permet de transformer une commande Symfony en boucle infinie, principe de base d’un daemon.
On dispose ainsi de tout le projet Symfony, de tout son paramétrage, de tout son code, mais on peut lancer une commande “daemonisée”.
Il est possible de mettre en place des limitations de nombre d’itérations, d’empreinte mémoire, …
Couplé à supervisord pour relancer les processus qui s’éteignent, cela nous permet de toujours avoirs des daemon actifs.
Et avec PHP 5.6+ et Symfony 2.7, pas de fuite mémoire … sauf si le debugger Symfony est actif ;)
Ce bundle permet de définir des producers/consumers as a service dans Symfony, pour les Broker respectant le standard AMQP.
Nous avons voulu bénéficier de certaines techniques en place sur la chaine, à savoir les événements synchronisés.
L’antenne nous émet des signaux au cours de la diffusion, nous permettant d’automatiser le déroulement.
Le device pool régulièrement un statut mis à disposition dans un bucket S3 pour connaître l’état du jeu.Nous avons rencontré des soucis à cette étape pour vraiment éviter tout les caches.
Nous avons réussi à nous en sortir en publiant les événements connus à venir avec un peu d’avance.
Le device se connecte normalement, et communique ensuite directement avec STS pour l’obtention d’un token lui permettant de discuter directement avec les outils AWS.
Nous ne validons pas ici que nous connaissons le device. Juste qu’il dispose d’un token STS
Nous avons un premier worker, qui se “réveille” quand le statut est “checkin” (enregistrement)
Ici, vous pouvez noter la présence d’un cache Redis pour le statut. Ce cache, de 1s, permet de réduire drastiquement la pression sur le bucket S3, tout en conservant une forte réactivité.
Le workers ont une temporisation lorsqu’ils ne sont pas sur “leur” statut”, qui les forcent à ralentir.
Dès qu’ils ont détectés qu’ils sont dans “leur” statut, ils se mettent à boucler sans temporisation, pour donner pleine puissance.
La première étape est de dépiler un message dans la file adhok SQS.
Ensuite, le worker va stocker localement l’état des personnes enregistrée, puis publier dans le DynamoDB, et dans une batterie de Redis, en utilisant une technique de consistant hashing sur le token STS
Nous avons un second worker, qui se “réveille” quand le statut est “voting” (vote)
Ce worker, pour chaque message, va vérifier dans une batterie de Redis partagés, que le message n’a pas déjà été vu.
Si le message est bien considéré comme non traité, le worker incrémente un redis local, et pousse un log dans DynamoDB, en long pooling
Ce troisième worker fonctionne de pair avec celui de vote, et est destiné à consolider les votes, pour réduire la pression en écriture sur DynamoDB.
Sa vélocité est volontairement réduite par rapport à celui qui gère les votes.
A chaque itération, il prend le compteur courant dans le Redis local, et incrémente le compteur global dans DynamoDB, puis modifie le fichier dans S3.
Et la finalité de tout est de publier un fichier JSON contenant la valeur de la jauge.
Toute la mécanique que je viens de vous présenter à pour but de générer un fichier de 3 lignes.
Le soucis des workers, c’est qu’ils tournent en background.
Du coup, si vous n’avez pas de système de monitoring efficace, vous ne pouvez suivre leur fonctionnement.
Et le monitoring ne sert pas que à détecter des erreurs, mais à valider le dimensionnement de vos serveurs, de suivre le temps de rafraîchissement d’une données (durée de traversée d’un message), ..
Le monitoring est intégré dans notre Definition Of Done courant, nous utilisons StatsD, et nous avons un bundle facilitant l’intégration dans Symfony
Pour RisingStar, le monitoring était notre seul regard sur le fonctionnement des workers qui n’ont pas de sortie
Tout ça pour en arriver à un lancement en grande pompe.
Nous avons 7 épisodes au lieu des 10 prévus initialement, faute d’audience.
Nous avons une des pointes à 2M de personnes connectées, mais jamais les 10M prévus.
Le système a très bien tenu la charge.
Le seul incident notoire a été une perte de connexion Internet de l’antenne, qui n’a plus eu de mise à jour de la jauge pendant 10s, et qui a décidé de basculer sur le panel.
Si vous désirez rester informé des actualités de l’équipe technique de M6Web, il y a un twitter et un site web dédié.
Les mots clés sont #architecture, #PHP, #Symfony, #JS, #polymorphisme, #React, #Webperf, ...