Construire un pipeline d'analyse de fraude en temps réel
Visite guidée de l'architecture : ingérer 50K événements/seconde, enrichir avec les smart signals et scorer le risque en moins de 10ms grâce à notre moteur de streaming.
Traiter 50 000 événements d'empreinte par seconde, enrichir chacun avec les smart signals et renvoyer un score de risque en moins de 10 millisecondes exige une architecture de streaming soigneusement conçue. Cet article parcourt notre pipeline, de l'ingestion à la décision.
Couche d'ingestion
Les événements arrivent sous forme de requêtes HTTPS POST depuis notre agent JavaScript qui s'exécute dans les navigateurs des visiteurs. Chaque événement contient la charge utile de signaux chiffrée — typiquement 8-12KB de données compressées couvrant 130+ signaux de navigateur. Nos serveurs edge terminent le TLS, valident la signature de la requête et transmettent la charge utile au pipeline de traitement.
Nous utilisons un déploiement multi-régions où les serveurs edge sont colocalisés avec les nœuds CDN de nos clients. Cela maintient l'aller-retour réseau sous 20ms pour 95% des requêtes dans le monde. Les serveurs edge sont des services Go sans état s'exécutant derrière un équilibreur de charge, à mise à l'échelle horizontale selon le volume de requêtes.
Extraction des signaux
La première étape de traitement déchiffre et analyse la charge utile de signaux. Chaque signal est extrait, validé et typé. Les hachages canvas sont vérifiés par rapport à des valeurs impossibles connues (qui indiquent un blocage ou une usurpation du canvas). Les paramètres WebGL sont recoupés pour vérifier leur cohérence. Les propriétés du navigateur sont contrôlées par rapport à des combinaisons valides connues.
Cette étape effectue aussi la normalisation des signaux. Les chaînes de user agent sont analysées en composants structurés (navigateur, version, OS, appareil). Les dimensions d'écran sont normalisées pour tenir compte de la mise à l'échelle DPI. Les décalages de fuseau horaire sont validés par rapport aux données de géolocalisation IP.
Enrichissement Smart Signals
Les signaux extraits sont ensuite enrichis par l'analyse Smart Signals — notre couche d'intelligence côté serveur. Cela inclut la détection d'incognito (comparaison des schémas de signaux à des signatures connues de navigation privée), la détection de VPN (recoupement des données IP avec les signaux de fuseau horaire et de locale), la détection d'altération du navigateur (identification d'incohérences qui trahissent une usurpation de signaux) et la détection de machine virtuelle (reconnaissance des profils matériels associés à VMware, VirtualBox et aux VM cloud).
Chaque smart signal est calculé indépendamment et produit à la fois un résultat booléen et un score de confiance. L'étape d'enrichissement ajoute 24 signaux supplémentaires à chaque événement, fournissant une évaluation complète des menaces qui va au-delà de ce que la collecte côté client seule peut atteindre.
Moteur de scoring de risque
L'événement enrichi est transmis à notre moteur de scoring de risque — un modèle d'arbre de décision à gradient boosté entraîné sur des millions d'événements étiquetés. Le modèle prend en compte l'ensemble des 130+ signaux bruts, les 24 smart signals et plusieurs caractéristiques dérivées : métriques de vélocité (combien d'événements de cet appareil au cours des 5 dernières minutes, de la dernière heure et des dernières 24 heures), schémas de comportement historiques et scores de réputation réseau.
Le modèle produit un score de risque entre 0 et 100, accompagné des principaux facteurs contributifs. Un score de 85, par exemple, pourrait être accompagné de facteurs comme « VPN détecté », « mode incognito » et « vélocité élevée — 47 événements en 5 minutes ». Cette explicabilité est essentielle pour les analystes fraude qui doivent comprendre pourquoi un événement donné a été signalé.
Couche de stockage et de requête
Tous les événements sont persistés dans ClickHouse — une base de données en colonnes optimisée pour les requêtes analytiques sur de grands jeux de données. ClickHouse gère notre volume d'écriture (50K événements/seconde) sans effort, et son stockage en colonnes permet des requêtes analytiques en moins d'une seconde sur des milliards de lignes.
Nous utilisons une stratégie de rétention multi-niveaux. Les données chaudes (7 derniers jours) sont stockées sur des SSD NVMe pour une réponse aux requêtes en moins de 100ms. Les données tièdes (7-90 jours) sont sur des SSD standard. Les données froides (90+ jours) sont compressées et déplacées vers du stockage objet, interrogeables mais avec une latence plus élevée.
Kafka comme colonne vertébrale
Apache Kafka relie le pipeline. Chaque étape lit et écrit dans des topics Kafka. La couche d'ingestion écrit les événements bruts. L'étape d'extraction des signaux lit les événements bruts et écrit les événements extraits. L'étape d'enrichissement Smart Signals lit les événements extraits et écrit les événements enrichis. Le moteur de scoring de risque lit les événements enrichis et écrit les événements scorés.
Cette architecture offre plusieurs avantages : les étapes peuvent être mises à l'échelle indépendamment, les défaillances d'une étape n'affectent pas les autres, et nous pouvons rejouer les événements à travers n'importe quelle étape à des fins de débogage ou de retraitement. Les groupes de consommateurs de Kafka permettent le traitement parallèle au sein de chaque étape, et sa sémantique exactly-once garantit qu'aucun événement n'est traité deux fois ni perdu.
Budget de latence
Notre cible de latence de bout en bout est de 10ms, du moment où la charge utile de signaux enrichie arrive au pipeline de traitement au moment où le score de risque est renvoyé. Voici comment le budget se décompose : l'extraction des signaux prend 1-2ms, l'enrichissement Smart Signals prend 3-4ms, le scoring de risque prend 2-3ms, et la sérialisation et la réponse prennent 1-2ms. Le saut Kafka entre les étapes ajoute moins de 1ms dans notre déploiement colocalisé.
Respecter ce budget de façon constante à 50K événements/seconde exige une optimisation soigneuse à chaque étape. Nous utilisons des pools de mémoire préalloués, une sérialisation zero-copy et des écritures ClickHouse par lots. Le modèle de scoring de risque est compilé en code natif à l'aide d'ONNX Runtime, éliminant la surcharge de l'interpréteur Python.
Mark a passé deux semaines à profiler le pipeline avant de trouver le goulot d'étranglement dans notre couche de recherche distribuée — un unique mutex sérialisait les recherches à travers toutes les goroutines. Après le passage à une conception à verrou partitionné, le p99 est tombé de 48ms à 9ms. Parfois, la correction est d'une simplicité embarrassante une fois qu'on l'a trouvée.