Calcul de tarif de taxi en temps réel
Plateforme de streaming qui calcule le tarif d'une course à la volée : un processeur NiFi développé en Java applique la formule de haversine à chaque événement Kafka, ElasticSearch et Kibana supervisent le flux, et 10 000 courses consolidées en Parquet alimentent une segmentation K-Means du chiffre d'affaires par zone et par niveau de confort dans BigQuery.
Le sujet
Dans une application de type VTC, le tarif s’affiche avant que le client valide sa course. Le calcul ne peut donc pas attendre un traitement par lots : il se fait dans le flux, événement par événement, entre la demande et la réponse à l’écran. Le projet reconstruit cette chaîne de bout en bout, du producteur d’événements jusqu’à l’analyse du chiffre d’affaires par zone géographique.
Le flux est simulé : un producteur Python émet 10 000 demandes de course réparties sur huit paires client / chauffeur de quatre continents, avec trois niveaux de confort facturés 0,5, 0,3 et 0,2 par kilomètre. Les positions sont tirées aléatoirement, ce qui rend les distances volontairement irréalistes mais donne un volume et une variété de messages suffisants pour valider l’architecture.
L’architecture
Quatre étages, un seul chemin pour la donnée : Kafka transporte les événements, NiFi les orchestre et calcule le tarif, ElasticSearch les rend observables en continu, BigQuery les analyse une fois consolidés.
Le calcul du tarif dans le flux
Le cœur du projet est un processeur NiFi développé en Java et packagé en NAR. TravelProcessor étend AbstractProcessor, reçoit chaque FlowFile issu du topic Kafka, calcule la distance orthodromique entre le chauffeur et le client par la formule de haversine (rayon terrestre 6 371 km), la multiplie par le prix au kilomètre du niveau de confort demandé, puis réécrit le JSON enrichi de la distance et du tarif.
Trois décisions structurent ce composant :
- Calculer dans le flux plutôt qu’à côté. Un service externe appelé depuis NiFi aurait ajouté un aller-retour réseau et un point de panne hors du pipeline. Un processeur natif hérite du contrôle de flux, de la traçabilité (data provenance) et du routage d’erreur du framework.
- Isoler l’échec au lieu de le subir. Deux relations, SUCCESS et FAILURE : un JSON malformé part sur la branche d’erreur avec sa trace dans le log du composant, le reste du flux continue. Pas de message perdu, pas de pipeline bloqué.
- Compter l’argent en décimal. Distance et tarif transitent par des
BigDecimalarrondis en HALF_UP, à trois décimales pour les kilomètres et deux pour le montant. La virgule flottante n’a pas sa place dans un calcul de facturation.
Le processeur est couvert par un test unitaire qui rejoue un message complet et vérifie la sortie, ce qui permet de faire évoluer la règle tarifaire sans redéployer le flux à l’aveugle. En aval, un JoltTransformJSON aplatit la structure imbriquée en un enregistrement de dix colonnes et y ajoute un horodatage de passage dans le flux.
L’indexation et la supervision
Les enregistrements sont indexés dans ElasticSearch avec un mapping déclaré explicitement plutôt que déduit automatiquement : type géographique pour les positions, date pour l’horodatage, keyword pour les identifiants. C’est ce qui rend les agrégations fiables et la carte exploitable, là où un mapping dynamique aurait typé les coordonnées en texte.
Kibana sert de poste de pilotage : débit du flux, distribution des courses par niveau de confort, carte des trajets et inspection message par message quand une valeur sort de l’ordinaire.
L’entrepôt et l’analyse
- Consolidation : un
MergeRecordregroupe les événements par lots de 10 000 et les écrit en Parquet compressé, environ 24 ko pour 10 000 lignes et 10 colonnes, un fichier horodaté par lot déposé sur Cloud Storage. - Entrepôt : BigQuery lit le bucket via une table externe déclarée sur
gs://.../*.parquet. Pas de chargement ni de duplication, le schéma est lu à la volée et chaque nouveau lot devient interrogeable dès son dépôt. - Modèle : un K-Means entraîné directement en SQL avec BigQuery ML (8 clusters, variables standardisées) segmente les courses sur les coordonnées, extraites du champ de localisation par expression régulière.
- Restitution :
ML.PREDICTcroise le cluster et le niveau de confort pour agréger le chiffre d’affaires, restitué dans un tableau de bord Looker Studio.
Le modèle retrouve les huit zones du générateur, ce qui vaut ici comme contrôle de cohérence de bout en bout plutôt que comme découverte. L’analyse fait en revanche ressortir un déséquilibre net : le niveau de confort le plus élevé pèse 60 % du chiffre d’affaires alors qu’il ne représente qu’un tiers des courses. Sur un flux réel, c’est exactement le type de signal qui oriente une grille tarifaire ou l’allocation d’une flotte.
Ce que le projet démontre
Une chaîne événementielle tenue de bout en bout : ingestion, calcul métier dans le flux, indexation, supervision, entrepôt et modèle analytique. Le framework d’ingestion est étendu par un composant JVM assumé et testé, pas contourné par un script en marge du flux, et l’entrepôt évite les copies inutiles (table externe, schéma en lecture, modèle entraîné en SQL). C’est le même socle événementiel qui porte aujourd’hui les pipelines de features et la télémétrie des systèmes d’IA en production.