Dépasser 15 000 requêtes/seconde avec le géomarketing et Kuzzle

English version

Dans cet article, vous allez découvrir une des fonctionnalités phare de notre backend: le géorepérage en temps réel.

Dans un premier temps, nous découvrirons ce qu’est le géorepérage et ses applications possibles, puis nous verrons ensemble comment mesurer les performances de Kuzzle sur un cas d’usage concret : le géomarketing.

Qu’est-ce que le géorepérage ?

Le géorepérage est une technique qui consiste à enregistrer des zones géographiques pour être en mesure par la suite de déclencher des notifications lorsqu’un document associé à des coordonnées géographiques entre ou sort d’une zone.

 

Ses utilisations sont multiples, de la gestion de flottes de véhicules comme les poids lourds ou les taxis en passant par la localisation de stocks de marchandise ou la diffusion de publicités géolocalisées.

 

geofencing

 

Géomarketing en temps réel, le graal publicitaire

Le géomarketing propose de diffuser des annonces en fonction de l’emplacement géographique.

 

Ainsi un territoire va être découpé en zones géographiques correspondant à une annonce ou catégorie d’annonces pour un consommateur se trouvant à proximité.

 

Cela peut représenter plusieurs centaines de milliers de zones différentes et des dizaines de milliers de tests à effectuer par seconde.

 

De plus, dans le cadre d’enchères en temps réel il est capital d’obtenir de très faibles latences pour que les annonces soient rapidement diffusées au consommateur.

 

Aujourd’hui bien que de nombreux éditeurs proposent des solutions sur étagère pour réaliser du géomarketing, aucune de ces solutions ne permet d’atteindre un niveau de performance acceptable pour des enchères en temps réel.

 

Ici chez Kuzzle nous sommes toujours curieux de savoir comment se comporte notre produit dans un environnement impliquant de gros volumes de données et des temps de réponse rapides.

 

Les problématiques du géomarketing en temps réel nous ont paru intéressantes pour réaliser quelques tests de performance de notre solution.

Implémentation du géomarketing en temps réel avec un plugin Kuzzle

Kuzzle est un backend open source offrant des fonctionnalités avancées dont le géorepérage en temps réel.

Il offre toutes les fonctionnalités nécessaires au développement d’application, authentification, persistance, API, tout en offrant de très bonnes performances pour un coût réduit.

 

Son utilisation permet d’atteindre un haut niveau de personnalisation des applications tout en réduisant les coûts de développement backend.

 

Il se base sur des technologies modernes ayant fait leurs preuves: Node.js, Elasticsearch et Redis.

 

Nous avons donc développé un plugin de géomarketing en temps réel afin de réaliser des tests de charge et voir comment notre produit se comporte face à de fortes problématiques de performances.

 

Ce plugin étend l’API de Kuzzle en permettant d’associer des documents à des polygones de géorepérage. Lorsqu’une coordonnée GPS est envoyée à Kuzzle, un test est réalisé afin de savoir si elle s'inclut à l’intérieur d’un ou plusieurs de ces polygones. Si c’est le cas, le ou les documents correspondants sont retournés au client.

 

Pour notre démonstration, nous enregistrerons 300 000 polygones à 6 faces pouvant se superposer.

Le géorepérage de Kuzzle est précis jusqu’à une distance inférieure à un mètre.

 

exemple de polygones

 

Bien sûr chaque requête sera authentifiée grâce à notre système de permissions.

Gatling, un framework de test de charge

Les tests de performance sont réalisés avec Gatling, un logiciel écrit en Scala pour évaluer les performances des applications face à un grand nombre de requêtes.

gatling

 

Gatling propose nativement une implémentation du protocol Websocket que nous allons utiliser pour nos tests.

 

Les benchmarks Gatling se composent de 3 parties :

  1. Définition du protocole de communication et de ses options ;
  2. Définition du scénario de test ;
  3. Définition de la fréquence d’apparition des utilisateurs.

Un scénario de test correspond à une suite d’actions exécutées par un utilisateur virtuel.

Notre scénario de test comportera les étapes suivantes :

  1. Ouverture d’une connexion Websocket ;
  2. Authentification à Kuzzle ;
  3. Envoi d’un document géolocalisé ;
  4. Fermeture de la connexion.

L’étape n°3 sera rejouée 2000 fois afin de simuler un gros volume de données.

 

L’arrivée de nouveaux utilisateurs se fera progressivement afin de pouvoir étudier les courbes de montée en charge et les temps de réponse en fonction du nombre d’utilisateurs et de requêtes par secondes.

 

Maintenant que nous avons notre plugin et notre scénario, il va nous falloir un cluster de Kuzzle !

Kuzzle en mode cluster

Lorsque nous avons développé Kuzzle, nous avons bien sûr porté une attention particulière à la performance globale de notre backend.

 

Cependant dans le contexte actuel d’un nombre d’utilisateurs d’internet toujours croissant et de l’arrivée massive de données au travers notamment de l’IoT, il est nécessaire de pouvoir assurer une scalabilité horizontale des infrastructures.

 

C’est dans cette optique que nous avons développé un plugin activant un mode cluster masterless pour Kuzzle. Ce plugin répartit la charge sur plusieurs instances de Kuzzle afin de lui permettre de supporter plusieurs dizaines de milliers de requêtes par seconde.

 

De leur côté, Elasticsearch et Redis sont des produits connus pour leur mode cluster natif et pour leur capacité à traiter de très gros volumes de données.

 

Elasticsearch-redis-cluster-natif

 

Dans un cluster de Kuzzle, chaque nœud communique et découvre les nouveaux nœuds automatiquement. Grâce à ce système, il est possible de rajouter à chaud autant de nœuds que nécessaire pour supporter la charge.

 

Pour nos tests, le cluster sera déployé dans un environnement AWS mais Kuzzle est hébergeable sur n’importe quelle infrastructure, que ce soit du cloud privé ou publique, ou sur ses propres serveurs.

Atteindre 15 000 requêtes par seconde

Pour ce test de performance, nous utiliserons un cluster de 2 à 4 nœuds Kuzzle.

 

Les instances choisies sont les plus petites de la gamme m5 d’Amazon EC2, des instances m5.large avec 2 vCPU et 8 Go de RAM.

 

Lorsque l’on fait des tests de performance, il est très important que le serveur hébergeant Gatling soit le plus puissant possible afin qu’il ne soit pas le facteur limitant du test.

Nous avons donc choisi une instance optimisée pour le calcul de la gamme c5 d’Amazon EC2, une instance

c5.2xlarge avec 8 vCPU et 16 Go de RAM.

 

Le premier scénario consiste à l’arrivée de 200 utilisateurs en 20 secondes sur un cluster de 2 noeuds.

Au maximum de sa charge, Kuzzle a été capable de répondre à 7000 requêtes par secondes avec un temps de réponse inférieur à 19 ms pour 75% des requêtes.

 

premier-scenario-2-noeuds

 

Le deuxième scénario simule l’arrivée de 200 utilisateurs en 10 secondes sur un cluster de 3 noeuds.

Cette fois-ci, Kuzzle a été capable de répondre à un maximum de 10 000 requêtes par secondes avec un temps de réponse inférieur à 16 ms pour 75% des requêtes.

 

deuxième-scenario-3-noeuds

 

Le dernier scénario simule l'arrivée de 400 utilisateurs en 20 secondes sur un cluster de 4 noeuds.

Kuzzle a été capable de soutenir plus de 15 000 requêtes par secondes avec un temps de réponse inférieur à 15 ms pour 50% des requêtes.

 

dernier-scenario-4-noeuds

 

On observe que Kuzzle est capable de tenir une charge élevée sur un cas d’usage aussi complexe que le géorepérage en temps réel sur de gros volumes.

 

De plus en analysant les résultats, on constate que le nombre de requêtes par seconde que Kuzzle est capable de gérer croît de façon linéaire avec le nombre de nœuds du cluster. Ainsi pour gérer de plus gros volumes de données, il suffit de rajouter des nœuds !

 

L’ensemble du code utilisé dans ce benchmark ainsi que les rapports détaillés sont bien sûr disponibles sur Github.

Écrire un protocole personnalisé et modifier l'authentification pour améliorer les performances

Dans l’équipe, même si nous sommes plutôt fiers de ces résultats, nous ne pouvons pas nous empêcher de nous demander comment faire encore mieux.

 

Comme nous connaissons très bien notre produit, nous avons d’ores et déjà pensé à certaines parties de notre infrastructure qui pourraient être améliorées en vu de l’obtention de performances encore meilleures.

 

Tout d’abord l’authentification effectuée sur chaque requête est inutile une fois que la connexion websocket a été authentifiée une première fois. Attendez-vous à voir cette amélioration dans une de nos prochaines versions ;)

 

Le plus gros goulot d’étranglement de performances de ce test est l’utilisation du protocole Websocket.

Dans Kuzzle, ce protocole est utilisé en mode texte. Le texte prend bien sûr plus de place que des données binaires mais en plus, la sérialisation du JSON est une opération coûteuse.

 

L’utilisation d’un protocole binaire directement au dessus de TCP voir d’UDP tel que ProtoBuf ou CoAP permettrait d’atteindre des performances radicalement meilleures.

 

La création et l’utilisation d’un tel protocole est possible grâce à la gestion du multi-protocole proposée dans Kuzzle.

 


 

J’espère que cet article vous a plu et que les performances atteintes par Kuzzle vous ont autant impressionné que nous !

 

N’oubliez pas que nous restons disponibles pour toutes questions sur le chat de notre site ainsi que par email ;-)

 

 

Adrien Maret

Postes associés