Module 7 — Points de terminaison, trafic partagé et mise à l'échelle
Le registre du module 6 contient deux versions du modèle fraude : v1 en production depuis août, v2 fraîchement entraînée. Comment mettre v2 devant le vrai trafic sans exposer le service à un modèle qui n'a jamais vu de production ? Vertex répond par le point de terminaison avec trafic partagé : deux versions cohabitent, on choisit la répartition, et l'on bascule progressivement selon les résultats.
Anatomie d'un point de terminaison
Un Endpoint Vertex est une adresse HTTPS qui accepte des requêtes de prédiction. Derrière cette adresse, il peut y avoir de 1 à 10 versions déployées, chacune avec sa part du trafic (les pourcentages doivent sommer à 100). Chaque version a ses propres réplicas et sa propre configuration machine, ce qui permet des expérimentations fines : v1 sur n1-standard-4, v2 sur n1-standard-8 si elle est plus coûteuse à évaluer.
Notre plateforme utilise un point de terminaison par cas d'usage, jamais par version. Le service front appelle toujours fraude-endpoint-eu. Ce qui change en interne — versions, pourcentages, réplicas — ne le concerne pas.
Créer et déployer
from google.cloud import aiplatform
endpoint = aiplatform.Endpoint.create(
display_name="fraude-endpoint-eu",
location="europe-west1",
labels={"equipe": "fraude", "env": "prod"},
)
# v1, deja en production, 100 % du trafic
modele_v1 = aiplatform.Model("projects/paiement-fraude-prod/locations/europe-west1/models/1234567890@1")
deploiement_v1 = endpoint.deploy(
model=modele_v1,
deployed_model_display_name="fraude-xgb-v1",
machine_type="n1-standard-4",
min_replica_count=2,
max_replica_count=8,
traffic_percentage=100,
service_account="vertex-fraude-runner@paiement-fraude-prod.iam.gserviceaccount.com",
)
Le déploiement prend cinq à dix minutes : Vertex provisionne les machines, tire l'image de service, charge le modèle en mémoire, teste la route /health. Une fois deployed_model_id renvoyé, l'endpoint accepte du trafic.
Ajouter la version challenger
Le vrai geste du module. On déploie v2 sur le même point de terminaison, avec 10 % du trafic — les 90 % restants restent sur v1 :
modele_v2 = aiplatform.Model("projects/paiement-fraude-prod/locations/europe-west1/models/1234567890@2")
endpoint.deploy(
model=modele_v2,
deployed_model_display_name="fraude-xgb-v2-challenger",
machine_type="n1-standard-4",
min_replica_count=1,
max_replica_count=4,
traffic_split={
deploiement_v1.id: 90,
"0": 10, # 0 est un placeholder pour la version qu'on vient de deployer
},
)
Vertex accepte l'ancienne convention où l'on passe la répartition à deploy(), mais un appel séparé à endpoint.update_traffic_split(...) reste plus lisible pour les revues d'exécution ultérieures. Après quelques minutes, la moitié des transactions du trafic entrant passera par v2, mais surtout 90 % sur v1 — le rapport 90/10 protège l'entreprise si v2 se révèle catastrophique.
Requête et forme des données
Le service appelle l'endpoint en JSON :
reponse = endpoint.predict(
instances=[{
"montant": 189.50,
"pays_carte": "FR",
"pays_marchand": "US",
"canal": "e-commerce",
"age_compte_jours": 42,
"nb_transactions_24h": 3,
# ... 36 autres variables
}]
)
print(reponse.predictions[0])
La forme du dictionnaire dépend du modèle. Pour un sklearn inscrit sans schéma, Vertex passe les valeurs dans l'ordre : c'est fragile. La bonne pratique est d'inscrire un predict_schemata à l'upload du modèle, ou de faire précéder le modèle d'un petit conteneur de prétraitement qui accepte un dictionnaire nommé et le convertit en vecteur ordonné.
Réplicas minimum et maximum
min_replica_count est le nombre minimal de machines toujours allumées. À 0, Vertex démarre à la première requête — mais cela signifie 30 à 60 secondes de latence pour cette première requête (cold start), rédhibitoire pour un service en ligne. Pour la production, jamais moins de 2 : cela garantit la tolérance à une panne d'instance et évite la latence de démarrage. En développement, min=0 économise sur les nuits.
max_replica_count est le plafond de l'autoscaler. Vertex ajoute des réplicas quand l'utilisation CPU d'un réplica dépasse 60 %, et en enlève quand elle descend. Le plafond protège la facture face à un pic anormal — et permet à l'équipe SRE de dormir.
Le rapport à choisir : pour un trafic aux variations naturelles, max = 4 × min couvre les heures de pointe. Pour un trafic qui triple en une seconde (soldes, promotions), il faut anticiper — l'autoscaler ne réagit pas assez vite pour un pic aussi brutal, et pré-scaler à min=8 la veille est plus sûr.
Mesurer la latence
La console affiche pour chaque déploiement les percentiles de latence (p50, p95, p99) sur les dernières 24 h. Trois seuils à surveiller :
| Percentile | Notre cible fraude | Sens |
|---|---|---|
| p50 | < 30 ms | Ressenti moyen d'une transaction |
| p95 | < 80 ms | Ce que voit une transaction sur vingt |
| p99 | < 200 ms | Le pire acceptable, une sur cent |
Le p99 est celui qui casse la promesse : à 3 000 transactions par seconde, une sur cent lente représente 30 par seconde qui excèdent 200 ms — visible dans les traces distribuées, à l'origine de tickets clients.
Journalisation des requêtes
Par défaut, Vertex ne journalise ni les requêtes ni les prédictions. Activation à la déploiement :
endpoint.deploy(
model=modele_v2,
enable_container_logging=True,
enable_access_logging=True,
# journalisation echantillonnee des requetes et predictions
explanation_metadata=None,
request_response_logging_config={
"enabled": True,
"sampling_rate": 0.01, # 1 % des requetes
"bigquery_destination": {
"output_uri": "bq://paiement-fraude-prod.vertex_logs.predictions_fraude",
},
},
)
Un pour cent des requêtes est écrit dans BigQuery, avec l'entrée, la sortie, la version déployée, l'horodatage. C'est la matière première de la surveillance de dérive (cours 20) et de la comparaison quantitative entre v1 et v2 : au bout de deux semaines, on compare les scores et les taux d'alerte de chaque version sur des transactions comparables. Sans ce log, l'expérimentation 90/10 ne prouve rien.
Basculer le trafic
Après validation, on inverse :
endpoint.update_traffic_split({
deploiement_v1.id: 0,
deploiement_v2.id: 100,
})
On garde v1 déployée quelques jours à 0 % : la remise à 100 % sur v1 en cas d'incident sur v2 prend alors une seconde, sans réprovisionner de machines. Retour arrière trivial — c'est là que la promesse du registre du module 6 se concrétise.
La répartition 90/10 partage les requêtes, pas les utilisateurs. Un client peut voir sa première transaction évaluée par v1 et la suivante par v2, cinq secondes plus tard. Pour un vrai test A/B (métrique par cohorte), il faut acheminer soi-même selon un hash de l'identifiant client, en amont de Vertex. Vertex fournit une exposition contrôlée du modèle, pas un moteur d'expérimentation.
En résumé
- Un
Endpointest une adresse HTTPS derrière laquelle vivent jusqu'à 10 versions, avec des pourcentages de trafic sommant à 100. min_replica_count ≥ 2en production : évite lecold startet tolère la panne d'un réplica.max_replica_countprotège la facture ; pour un pic soudain, pré-scaler la veille.- Le trafic partagé 90/10 expose
challengersans risquer la production, avec retour arrière à la seconde. request_response_logging_configest indispensable pour comparerv1etv2sur du trafic réel.
Module suivant : nous traitons les transactions non temps réel — celles qui n'ont pas besoin d'une réponse en 30 ms — avec la prédiction par lots.