User Action Service: du Monolith au Cloud

(Souhaib Guitouni) (23 juin 2020)

Introduction

Historiquement, le backend de BlaBlaCar était un gros monolithe PHP. Cela nous a permis ditérer et de créer des fonctionnalités rapidement, mais à long terme, ce nétait pas facile à appréhender, à maintenir et à faire évoluer. Au cours des dernières années, nous avons démantelé ce vieux monolithe et évolué vers une architecture orientée services.

Cet article est lune des histoires de la façon dont nous gérons cette transition, avec quelques détails sur la des outils qui nous ont aidés en cours de route. Il couvrira les choix de la pile technique, larchitecture générale et le retour dexpérience sur les outils que nous avons utilisés.

I – Les pourquoi

À mesure que lactivité de BlaBlaCar se développe, avoir une architecture monolithique devient de plus en plus limitant, principalement parce que:

  • À mesure quils vivent, les monolithes tombent en couplage;
  • Il est difficile dorganiser des équipes sur des backlogs séparés sur la même base de code;
  • Les monolithes sont difficiles à appréhender pour les nouveaux arrivants;
  • Pour tout ce qui précède, toute nouvelle fonctionnalité devient extrêmement coûteuse.

Cest pourquoi, ces dernières années, nous avons repensé notre plateforme vers une architecture SOA, recherche:

  • Serveurs fonctionnellement étendus: un service gère une seule fonctionnalité et est entièrement responsable de la façon dont il limplémente.
  • Services faiblement couplés qui peuvent évoluer indépendamment. Les équipes peuvent travailler et se déployer à leur propre rythme.
  • Plus de propriété du code, donc les services ont une portée définie et plus réduite, ce qui permet aux équipes de les maintenir et de les exploiter plus facilement.

II – Portée et historique des actions des utilisateurs

Le dernier en date à être transformé en service indépendant était les actions de lutilisateur. Ils aident notre équipe des relations avec la communauté à diagnostiquer et à résoudre les problèmes des utilisateurs, tels que les remboursements et la détection danomalies, ou le suivi des comportements frauduleux.

Le nombre dactions des utilisateurs, comme vous pouvez vous y attendre, est colossal. Historiquement, en tant que table SQL, cette partie du code avait des problèmes de performances. Nous avons trouvé des solutions à chaque fois, mais avec notre expansion, les problèmes sont devenus de plus en plus importants:

  • Une première solution était de créer des index pour accélérer les requêtes;
  • Une autre était de fragmenter la base de données en plusieurs tables.

Pourtant, ces solutions ont atteint leur limite et avec le temps, nous avons commencé à avoir des problèmes de performances.

III – Stockage des données

1 – La route vers NoSQL

Le choix du magasin de données sest principalement exigences:

  • Il y a dénormes quantités de données
  • Grand volume dinsertions
  • Plusieurs lectures par seconde, avec le besoin de nouvelles données et de performances
  • Possibilité de filtrer dans un délai raisonnable

Nous recherchions évidemment une base de données NoSQL, car la distribution nous permettrait de stocker et de manipuler de grandes quantités de données et d’évoluer lorsque nécessaire.

2 – Service géré

Nous voulions aussi y aller avec un service géré pour réduire le coût de la maintenance. Les bases de données distribuées comme Hbase et Cassandra sont réputées pour les difficultés quelles provoquent pour les équipes de gestion de bases de données. Plus important encore, pour léquipe de développement dapplications, nous voulions nous concentrer sur la production de la logique de gestion des actions des utilisateurs plutôt que de passer notre temps à résoudre des problèmes avec linfrastructure de la base de données. Cétait aussi loccasion de tester un nouveau produit, car le champ dapplication nest pas trop large. Nous voulions essayer quelque chose de nouveau!

3 – Choix final

Le choix a atterri sur Bigtable pour les raisons suivantes:

  • Volume: Il a été conçu pour gérer de grandes quantités de données, contrairement à la plupart des bases de données SQL, une instance peut gérer 10 000 insertions par seconde, nous avons donc choisi la configuration minimale avec seulement trois nœuds.
  • Évolutivité: il est évolutif et facile à répliquer, vous pouvez également gérer les versions de données.
  • Coût de gestion: cest un service géré.
  • Performances: cest un service GCP, qui nous permettra davoir dexcellentes performances car il sera dans la même infrastructure que le service déployé dans GKE.

III – Sauter dun train en mouvement à un autre

Le plus difficile passer dun monolithe à un service, cest assurer une continuité de service dun point de vue externe et ne pas avoir de perte de données.

Pour fournir cela, nous avons décidé dexécuter le nouveau service, de maintenir lancien système en état de marche et décrire les nouvelles actions via REST dans les deux. La prochaine étape consistera à déplacer les données historiques du monolithe vers le nouveau service. Cette opération peut créer des doubles, de sorte que le chargement initial des données doit gérer la déduplication. Une troisième étape consistera à lire à partir du nouveau service au lieu de lancien système. Une dernière étape serait darrêter la partie monolithique et la base de données SQL héritée une fois que tout fonctionne dans le service.

IV – Déplacement des données

1 – De MySQL à Bigtable

Maintenant que nous avons décidé quelle sera notre banque de données cible et comment elle sera déployée, nous avons commencé à réfléchir les moyens de déplacer les données du monolithe vers la nouvelle base de données. Une telle opération est critique et le travail de migration doit être:

  • Simple et facile à développer: la complexité étant les connecteurs de bases de données
  • Très performant: car il lira énormément quantités de données, nous voulons avoir le résultat le plus rapidement possible
  • Fiable: nous ne voulions aucune perte de données
  • Facile à redémarrer: en cas de problème, nous voulions quelque chose que nous pouvions il suffit de redémarrer sans beaucoup dactions manuelles, avec des scripts shell partout et une procédure complexe
  • Permettre les transformations: nous devions joindre les données de plusieurs bases de données et tables MySQL pour obtenir les dernières Bigtable, cela pourrait être difficile si scripté manuellement.

2 – Apache Beam et Dataflow

Nous avons choisi dutiliser Dataflow, un service géré distribué fourni par Google Cloud, qui permet aux gens de déplacer des données en mode batch et en streaming.

Apache Beam, dautre part, est un Framework utilisé pour coder des scripts distribués . Vous pouvez ensuite lexécuter sur de nombreux moteurs distribués comme Dataflow, Spark, Flink… En dautres termes, cest une couche dabstraction pour définir vos transformations qui peut être comprise par plusieurs moteurs.

Une autre chose intéressante à propos dApache Beam est quil dispose de connecteurs prêts à lemploi vers plusieurs sources de données, parmi lesquelles MySQL et Bigtable. Nous avons donc créé les transformations de données, en lisant les anciennes tables Mysql, en les joignant et en plaçant le résultat dans Bigtable.

2 – Comment ça sest passé?

Nous avons fait quelques observations lors de lexécution de la migration:

  • Cétait une tâche épuisante pour MySQL: éviter les problèmes de performances, vous devez par tous les moyens éviter de lexécuter sur une base de données critique. Pour éviter ce problème, nous lavons exécuté sur une base de données réplique conçue pour de telles tâches. Nous avons suivi lexécution sur notre service de surveillance (Prometheus / Grafana) qui montrait que les machines parallèles Dataflow épuisaient MySQL.
  • Ce nétait pas non plus facile pour Bigtable: nous avions une petite instance de 3 machines, capable de donner 30.000 insertions par seconde. Si vous exécutez plusieurs tâches Dataflow, vous allez bien au-delà. Alors, réfléchissez bien au nombre de machines que vous souhaitez avoir en parallèle, car avoir le nombre maximum vous fera perdre de largent.
  • Le connecteur MySQL Beam ne diffuse pas de données: le connecteur MySQL exécute une instruction SQL et attend pour charger toute la réponse pour continuer. Cela vous posera des problèmes de RAM si vous chargez beaucoup de données. Il faut donc tester et définir les plages dutilisateurs pour éviter de se retrouver avec une exception mémoire.

V – Le service backend

Plusieurs modèles darchitecture étaient possibles, nous voulait aller avec une architecture qui peut évoluer dans le futur, et que nous pouvons construire étape par étape, avec du trafic en direct dès la première étape.

Nous avons décidé de créer un service avec Spring WebFlux, le framework réactif , pour avoir des demandes non bloquantes et ensuite de meilleures performances avec des points de terminaison fonctionnels. Nous avons utilisé Reactor pour la meilleure intégration avec Spring.

1 – Test dintégration avec Bigtable

Les tests dintégration appellent lAPI avec plusieurs charges utiles / en-têtes et vérifient si la réponse est celle attendue. Pour ce faire, nous avions besoin dune instance Bigtable derrière notre service, car nous voulions des tests réels.

Cette instance doit être nettoyée à chaque exécution pour démarrer à chaque fois dans le même état.

La solution était dutiliser lémulateur Bigtable présent dans le SDK client Bigtable. Le SDK est très riche et dispose de plus de fonctionnalités telles que la gestion et la surveillance des administrateurs.

2 – Déploiement et infrastructure

Notre infrastructure GCP est au-dessus de Google Kubernetes et Istio. Nous gérons le tout avec Helm et Flux. Dautres articles arrivent sur notre blog pour entrer dans plus de détails sur notre infrastructure!

Bien sûr, notre service avait des fins classiques de surveillance, de journalisation et dalerte, sans eux, nous ne pourrions pas lexécuter en direct , basé sur Prometheus / Grafana et ELK.

Réflexions finales

Afin de gérer les grandes quantités de données, nous nous sommes tournés vers Bigtable grâce à sa capacité à évoluer.Nous avons eu plusieurs défis comme la définition du schéma de données avec le modèle de clé Bigtable, le déplacement de grandes quantités de données dune base de données SQL sur site vers un NoSQL géré, le test et la surveillance de lensemble.

Au début, nous avons déployé le service. sur notre centre de données sur site, et en passant à GCP, nous avons divisé la latence par trois. Nos équipes de relations communautaires ont désormais des temps de réponse plus rapides et sont ravies.