Les notifications push sont partout – qu’il s’agisse d’une alerte de réduction des nouvelles, d’une mise à jour météorologique ou d’un message “Votre commande a été expédiée”, ils stimulent l’engagement et fournissent une valeur en temps réel aux utilisateurs. Mais la conception d’un système de notification push qui peut gérer des milliards de messages sur les plates-formes, tout en restant performant et fiable, n’est pas une promenade dans le parc.
Les applications modernes doivent souvent pousser des informations sensibles au temps aux utilisateurs sur les appareils mobiles (iOS / Android), les ordinateurs de bureau (macOS / Windows) et les navigateurs (Chrome, Firefox, Safari). Chacune de ces plates-formes est livrée avec son propre protocole, ses contraintes de livraison et ses limites de taux. Maintenant, la couche dans les règles métier comme les préférences des utilisateurs, la segmentation, la limitation, les tentatives et la localisation – vous regardez soudainement un système distribué non trivial.
Une implémentation de base peut fonctionner à faible échelle ou dans une preuve de concept. Mais que se passe-t-il lorsque vous avez 50 millions d’utilisateurs, chacun avec plusieurs appareils, et que le marketing veut exécuter des campagnes à 10% de votre public toutes les quelques minutes? C’est là que les choses commencent à se désagréger si votre architecture n’a pas été construite pour elle à partir de zéro.
Ce guide traverse le plan architectural de la construction d’un système de notification poussée évolutif, tolérant aux pannes et extensible. Il se concentrera sur la livraison multiplateforme (APNS, FCM, WebPush), les préoccupations au niveau du système comme la file d’attente et les tentatives, ainsi que sur la façon de régler les performances sous une charge élevée.
L’objectif est de vous doter du modèle mental et des modèles de conception nécessaires pour construire un système qui ne boucle pas sous pression et peut évoluer avec les besoins de votre produit.
Exigences du système
Exigences fonctionnelles
À la base, le système de notification push doit transmettre des messages aux appareils utilisateurs finaux. Mais la “livraison” ne suffit pas. Voici ce que le système devrait réellement faire:
- Livraison multiplateforme: Prise en charge du service Apple Push Notification (APNS), Messagerie cloud Firebase (FCM) et Protocole Web Push(WPP).
- Enregistrement et gestion de l’appareil: Stockez les jetons d’appareil mappés aux utilisateurs, plates-formes et applications.
- Capacités de ciblage: Envoyez des messages à des utilisateurs spécifiques, des groupes d’appareils, des segments d’utilisateurs ou tous les utilisateurs (diffusion).
- Planification: Autoriser l’envoi des messages immédiatement ou à une heure prévue.
- Limitation du taux: Messages de gaz basés sur les contraintes de plate-forme ou les règles commerciales internes.
- Réessayez la logique: Réessayez automatiquement les livraisons échouées avec des politiques de revers exponentielles ou de réessayer personnalisées.
- Préférences des utilisateurs: Respectez l’état opt-in / opt-out, les heures de calme ou les types de canaux spécifiques (par exemple, promotionnel vs transactionnel).
- Audit et analyse: Suivre le succès / échec de la livraison, ouvre (si possible) et les métadonnées diagnostiques pour le dépannage.
Exigences non fonctionnelles
Ce sont les préoccupations de la colonne vertébrale – les supprimer, et votre plate-forme s’effondrera sous une utilisation réelle.
- Évolutivité: Le système doit gérer des pics de millions de messages par minute.
- Disponibilité: Cibler de 99,99% de disponibilité, en particulier pour les chemins critiques comme l’enregistrement des périphériques et les pipelines de livraison.
- Latence: Traitement de sous-seconde pour transactionnel (par exemple, OTP, alertes de sécurité); retard tolérable (5-15) pour les messages marketing par lots.
- Durabilité: Les messages ne doivent pas être perdus en cas de défaillance de nœud ou de service.
- Sécurité: Protection de bout en bout des données utilisateur, authentification vers les services de 3e partie, chiffrement des charges utiles en transit et au repos.
- Multi-location: Capacité à prendre en charge plusieurs applications / clients avec des données isolées et des pipelines de livraison.
Contraintes et hypothèses
La définition des limites est essentielle pour réduire l’ambiguïté architecturale.
- Supposons que les fournisseurs de push de plate-forme (APNS, FCM, WebPush) sont externes et agissent comme des boîtes noires avec des SLA publiés.
- Les charges utiles du message sont petites (2KB – 4KB), la plupart des logiques gérés du côté client.
- Il existe une plate-forme d’identité utilisateur existante qui expose les mappages et les préférences de l’utilisateur de l’appareil / utilisateur.
- Le système ne garantira pas la livraison – une fois qu’il transfère APNS / FCM, la responsabilité est la leur.
- Le système s’exécutera dans un environnement de cloud-natif (Kubernetes ou conteneurs gérés, automatiquement, etc.).
Cas d’utilisation de base et paysage de livraison
Avant de plonger dans l’architecture, il est important de clarifier ce que ce système résout – car les «notifications push» signifient différentes choses dans différents contextes commerciaux. Cette section explore le paysage opérationnel du monde réel, qui utilise le système et comment l’échelle a un impact sur les choix de conception.
Cas d’utilisation de l’entreprise principale
Définissons un cas d’utilisation typique et à fort impact: une plate-forme de commerce électronique B2C à grande échelle souhaite envoyer des notifications push en temps réel sur le mobile et le Web pour stimuler l’engagement des utilisateurs, alerter les utilisateurs de mises à jour de l’état de commande ou déclencher des rappels basés sur le comportement (par exemple, des nuances de panier abandonnées). Il existe également des cas d’utilisation internes: les alertes OPS, les systèmes de fraude et les intégrations des partenaires. Mais le pilote de base est une messagerie à haut débit et centrée sur l’utilisateur avec des niveaux de criticité différents.
Utilisateurs et canaux de notification
Les utilisateurs finaux du système ne sont pas seulement les clients qui reçoivent les messages push. Il y a plusieurs acteurs:
- Spécialistes du marketing: Exécutez de grandes campagnes, calendrier et segmenter les cohortes des utilisateurs.
- Équipes de produits: Déclencher des notifications contextuelles à partir du comportement de l’application (jalons dans l’application, boucles de gamification).
- Systèmes backend: Déclencher automatiquement des messages transactionnels comme OTPS, des confirmations de paiement ou des alertes de livraison.
À la réception, chaque utilisateur peut avoir plusieurs types de périphériques:
- Applications mobiles: IOS via APNS et Android via FCM.
- Browsers Web: Via le protocole Web Push (basé sur VAPID), généralement pour les utilisateurs de bureau / ordinateur portable.
- Services tiers: Dans certains cas, des intégrations avec des canaux de livraison tiers comme WhatsApp ou des superpositions de messagerie dans l’application sont impliquées, mais hors de portée pour ce système.
Considérations de volume et d’échelle
Voici ce que le système devrait gérer à l’échelle du monde réel:
- 100m + dispositifs enregistrés sur toutes les plateformes, avec 5 à 10% actifs quotidiennement.
- Événements transactionnels: Messages 3 à 5M / jour, avec des SLA de latence dure (par exemple, OTP dans les 3 secondes).
- Campagnes: Burst envoie 10 à 20 millions d’utilisateurs en moins de 5 minutes, souvent déclenchés par le tableau de bord ou les files d’attente d’emplois.
- Pic de concurrence: 200K + messages / minute lors des événements de type Black Friday ou pendant les pointes virales.
Il ne s’agit pas d’envoyer un message à un utilisateur – il s’agit d’envoyer des millions de messages sur mesure sur des milliers de nœuds, avec la fiabilité, les tentatives et le retard minimal. La conception doit s’adapter à ce type de charge de travail dynamique, ce qui signifie les services de noyau sans état, les files d’attente distribuées et l’évolutivité horizontale à chaque niveau.
Architecture du système de haut niveau
L’architecture d’un système de notification push évolutive tourne autour de trois principes: découplage, parallélisme, et Livraison spécifique à la plate-forme. À grande échelle, les conceptions monolithiques s’effondrent – donc cette architecture adopte une approche basée sur les microservices et axée sur des événements qui peut s’écarter, accélérer, réessayer et auditer des milliards de messages avec des goulots d’étranglement minimaux.
Voyons les sous-systèmes de base, le flux de données et les abstractions spécifiques à la plate-forme qui font que tout fonctionne.
Présentation des composants
L’architecture est divisée en composantes logiques suivantes:
- API d’ingestion: Reçoit des demandes de message – repliant ou transactionnelles – évalue l’entrée, interroge les messages dans le pipeline.
- Moteur de routage: Fonds les appareils, divise les messages par paire de plate-forme de périphérique, les enile dans des files d’attente respectives.
- Livraison de plate-forme: Microservices dédiés pour APNS, FCM et WebPush. Ceux-ci gèrent la gestion des connexions, les tentatives, les lots et la limitation des taux.
- File d’attente de messages (couche de courtier): Courtier à haut débit (par exemple, Kafka, Rabbitmq ou Google Pub / Sub) pour les producteurs de découplage de la logique de livraison.
- Service de registre des périphériques: Stocke les métadonnées des périphériques, les mappages d’utilisateurs, la validité des jetons, le type de plate-forme et l’état d’opt-in.
- Moteur de préférence et de règles: Évalue les paramètres de notification utilisateur, les règles de suppression (heures de calcul, les plafonds de fréquence) ou les remplacements spécifiques aux canaux.
- Planificateur: Pour la livraison de messages retardée ou basée sur le temps.
- Boucle de surveillance et de rétroaction: Capture les reçus de livraison au niveau de la plate-forme, les erreurs et les analyses; gère la rétroaction APNS, la désinstallation du FCM, etc.
Diagramme d’architecture de haut niveau
+------------------+ | Ingestion API | +--------+---------+ | v +---------------------+ | Routing Engine | +--------+------------+ | v +---------------------+ | Message Broker | | (Kafka / RabbitMQ) | +--------+------------+ | +--------------------------+--------------------------+ | | | v v v +-------------+ +--------------+ +----------------+ | APNs Worker | | FCM Worker | | WebPush Worker | +------+------+ +------+-------+ +--------+-------+ | | | v v v +------------------+ +---------------------+ +------------------------+ | Apple Push Notif | | Firebase Cloud Msg | | Web Push Service (VAPID)| | Service (APNs) | | (FCM) | | | +------------------+ +---------------------+ +------------------------+ +------------------------+ +--------------------------+ | Device Registry Svc | <------> | User Preferences Engine | +------------------------+ +--------------------------+ +---------------------------+ | Scheduler / Campaign Svc | +---------------------------+ +---------------------------+ | Monitoring / Analytics | | (Logs, Receipts, Metrics) | +---------------------------+
Modèles architecturaux clés
- Architecture axée sur l’événement: Le flux de messages est entièrement asynchrone. Les producteurs (API, systèmes internes) sont découplés à partir de la livraison à l’aide de files d’attente de pub / sous ou de messagerie.
- Abstraction spécifique à la plate-forme: Les travailleurs sont personnalisés par plateforme. Chacun gère ses propres limites de débit, formats de charge utile, nouvelles tentatives et authentification API.
- Support de contre-pression: Les courtiers de messages doivent gérer les pics de trafic sans perte de données. La mise en mémoire tampon, les files d’attente de lettres mortes et la mise à l’échelle automatique des consommateurs sont intégrées.
- Idempotence et déduplication: Les messages doivent transporter des identifiants uniques pour éviter les problèmes à double sens, en particulier sur les tentatives.
- Isolement des pannes: Une panne de plate-forme (par exemple, APNS) ne devrait pas en cascade et en décrocher des messages pour FCM / WebPush. Chaque piscine de travailleur est isolé et tolérante aux pannes.
Cette architecture peut faire évoluer horizontalement chaque composant indépendamment – plus de travailleurs pour les APN pendant les éclats de campagne iOS, ou plus de nœuds de routage pendant les pics d’ingestion. Chaque niveau peut être surveillé, étranglé ou redémarré sans impact sur le système complet.
Besoin d’aide d’architecture poussoir à grande échelle?
Vous prévoyez de déployer des notifications push auprès des millions d’utilisateurs, mais vous ne savez pas comment mettre à l’échelle la livraison ou gérer les bizarreries multiplateformes?
Nous pouvons vous aider à concevoir un système de poussée éprouvé au combat adapté aux besoins de croissance et de performance de votre produit.
Conception de la base de données et gestion des jetons
Les systèmes de notification push vivent ou meurent par leur capacité à gérer des millions de jetons d’appareil, les préférences des utilisateurs et les états de message efficacement. Cette section décompose comment concevoir un schéma de base de données qui évolue horizontalement, maintient la cohérence de la livraison et prend en charge le ciblage et le filtrage en temps réel.
Entités de données de base
Au minimum, les entités suivantes sont nécessaires:
- Utilisateurs: Identité utilisateur logique (UID), liée à un ou plusieurs appareils.
- Appareils: Enregistrements d’appareils spécifiques à la plate-forme avec jetons, version de l’application, dernière vue, etc.
- Préférences: Indicateurs opt-in / opt-out spécifiques à l’utilisateur, paramètres de canal, heures de calme, etc.
- Messages: Historique des notifications envoyées, leur statut de livraison et les métadonnées pour le dépannage / l’audit.
Modèle de relation d’entité (ERD)
Voici comment les entités se rapportent à un niveau élevé:
+--------+ 1 +---------+ M +-----------+ | Users |---------------<| Devices |--------------->| Preferences| +--------+ +---------+ +-----------+ | | | | 1 | | | M | v v +-------------+ +--------------+ | Notifications| | Delivery Logs| +-------------+ +--------------+
Schémas de table (simplifiés)
users ( id UUID PRIMARY KEY, email TEXT UNIQUE NOT NULL, created_at TIMESTAMP DEFAULT NOW() ) -- Index: unique email lookup -- CREATE UNIQUE INDEX idx_users_email ON users(email); devices ( id UUID PRIMARY KEY, user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, platform ENUM('ios', 'android', 'web') NOT NULL, token TEXT UNIQUE NOT NULL, app_version TEXT, last_active TIMESTAMP, is_active BOOLEAN DEFAULT true, created_at TIMESTAMP DEFAULT NOW() ) -- Indexes: -- CREATE INDEX idx_devices_user_platform ON devices(user_id, platform); -- CREATE UNIQUE INDEX idx_devices_token ON devices(token); preferences ( id UUID PRIMARY KEY, user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, channel ENUM('transactional', 'marketing') NOT NULL, enabled BOOLEAN DEFAULT true, quiet_hours JSONB, updated_at TIMESTAMP DEFAULT NOW() ) -- Index: preference lookup -- CREATE UNIQUE INDEX idx_prefs_user_channel ON preferences(user_id, channel); notifications ( id UUID PRIMARY KEY, title TEXT, body TEXT, payload JSONB, scheduled_at TIMESTAMP, priority ENUM('high', 'normal', 'low') DEFAULT 'normal', created_by TEXT, created_at TIMESTAMP DEFAULT NOW() ) delivery_logs ( id UUID PRIMARY KEY, notification_id UUID NOT NULL REFERENCES notifications(id) ON DELETE CASCADE, device_id UUID NOT NULL REFERENCES devices(id) ON DELETE CASCADE, status ENUM('pending', 'delivered', 'failed', 'dropped') DEFAULT 'pending', attempt_count INT DEFAULT 0, response_code TEXT, error_message TEXT, delivered_at TIMESTAMP ) -- Indexes: -- CREATE INDEX idx_logs_device_status ON delivery_logs(device_id, status); -- CREATE INDEX idx_logs_notif_status ON delivery_logs(notification_id, status);
Exemples de lignes (illustrative uniquement)
users -------------------------------------------------------------- id | email --------------------------------------+------------------------- 5b6e...d1 | user@example.com devices -------------------------------------------------------------- id | user_id | platform | token | is_active ----------+----------+----------+---------------+------------ f7a9...91 | 5b6e...d1| ios | abc123token...| true preferences -------------------------------------------------------------- id | user_id | channel | enabled | quiet_hours ----------+----------+----------------+---------+------------- c1f3...72 | 5b6e...d1| marketing | false | {"start":"22:00","end":"07:00"} notifications -------------------------------------------------------------- id | title | priority | scheduled_at ----------+----------------+----------+-------------- e93f...55 | Order Shipped! | high | 2025-04-22 13:00:00 delivery_logs -------------------------------------------------------------- id | notification_id | device_id | status | attempt_count ----------+-----------------+-----------+------------+--------------- d95b...11 | e93f...55 | f7a9...91 | delivered | 1
Meilleures pratiques de gestion des jetons
- Jetons de dédouage: Plusieurs appareils peuvent envoyer le même jeton (en particulier sur Android); Deduplicate sur l’inscription.
- Manipulation de l’expiration des jetons: Valider périodiquement les jetons via des services de rétroaction (par exemple, la rétroaction APNS, les erreurs non enregistrées FCM) et marquent inactif.
- Supprimations douces: Utilisez des drapeaux `IS_ACCY` plutôt que des suppressions dures pour éviter les journaux de livraison orphelins.
- Index judicieusement: Les appareils doivent être indexés sur `(user_id, plate-forme)` et `(token)» pour les recherches rapides et la déduction.
- Évitez les joints des utilisateurs au moment de l’exécution: Gardez toutes les données de ciblage (jetons, opt-ins) dans des magasins à accès rapide comme Redis ou des vues pré-jointes pour les courses de livraison à grande vitesse.
Stratégies multi-tenue et d’isolement
Si vous prendz en charge plusieurs applications ou clients:
- Stratégie de colonne des locataires: Ajoutez une colonne `Tenant_id` à chaque table et appliquez l’isolement au niveau des lignes.
- Isolement db logique: Utilisez des schémas ou des bases de données séparés par locataire si le SLA et la sensibilité aux données l’exigent.
- Séparation des chemins d’écriture: Isoler les messages transactionnels de haute priorité des files d’attente en vrac / marketing sur la couche DB pour éviter les problèmes de voisin bruyant.
Partitionnement et échelle
À l’échelle, certaines tables (comme livraison_logs
) se développera rapidement. Considérer:
- Partitionnement basé sur le temps: Shard s’enregistre mensuellement ou hebdomadaire pour éviter les index gonflés.
- Politique d’archives: Déplacez les journaux plus anciens vers le stockage à froid (par exemple, S3 + Athena) pour l’accès à l’audit sans avoir un impact sur les performances en direct.
- Cache de jeton: Synchronisation des jetons de périphérique actif dans Redis ou DynamoDB pour les boucles de répartition à haut débit.
Schéma de cache de jeton redis
Redis est utilisé comme couche de recherche de jetons en mémoire optimisée et optimisée. Il évite de frapper la base de données primaire lors de la répartition des messages et prend en charge les recherches à temps constant sur des ensembles utilisateur / périphériques massifs.
Cas d’utilisation principaux:
- Éventail rapide des jetons d’appareil par utilisateur
- Recherche par segments d’utilisateurs (par exemple, appareils iOS actifs)
- Déplication de jetons et contrôle d’expiration
- TTL Enforcement pour les jetons inactifs ou tournés
Structure de clé recommandée
Key: push:user::tokens Type: Redis Set Value: token:: TTL: Optional (based on last_active)
Exemple:
Key: push:user:5b6ed...d1:tokens Value: { "token:ios:abc123token...", "token:web:def456token...", "token:android:xyz789token..." }
Clé alternative pour la recherche de jetons directs
Key: push:token:: Type: Hash Fields: { user_id: , app_version: , last_seen: , is_active: true/false } TTL: 30 days from last_seen
Exemple:
Key: push:token:ios:abc123token... Value: { user_id: "5b6ed...d1", app_version: "6.4.1", last_seen: "2025-04-21T18:11:45Z", is_active: true }
Meilleures pratiques
- Charge en vrac de DB: Les travaux d’échauffement de cache doivent synchroniser les jetons actifs de la base de données relationnelle au démarrage ou via CDC (modifier la capture des données).
- Invalider sur les non-inscriptions: Lorsqu’un appareil n’est pas enregistré ou que le jeton est marqué invalide par APNS / FCM, supprimez l’entrée Redis.
- Gardez TTL Lean: Les jetons non utilisés en 30 à 60 jours devraient expirer pour empêcher le gonflement du cache.
- Fanout au niveau des régions: Utilisez des ensembles Redis pour obtenir tous les jetons par utilisateur et effectuez efficacement le fan de messages dans les processus de travail.
- Support multi-locataire: Préfixe toutes les clés avec ID du locataire si vous opérez dans un environnement multi-locataire.
Ce cache complète la couche de DB persistante en servant de niveau de recherche à faible latence pendant la boucle d’envoi critique. Il aide également à segmenter les flux de livraison (par exemple, envoyer uniquement aux utilisateurs avec des jetons iOS actifs) sans jointures relationnelles coûteuses ni analyses complètes.
Besoin d’aide pour structurer les données des périphériques pour l’échelle?
Vous avez du mal à gérer des millions de jetons d’appareil, des journaux de livraison et des préférences d’optoir sur le mobile et le Web?
Nous pouvons vous aider à concevoir une couche de données robuste – SQL et Redis incluses – qui maintient votre système de poussée rapide, cohérent et toujours prêt à livrer.
Conception détaillée des composants
Chaque partie du système a sa propre responsabilité, mais la façon dont elle travaille ensemble définit si votre architecture push peut évoluer ou s’effondrer. Dans cette section, nous décomposerons les composants de base Couche par couche: Manipulation des données, logique de service, travailleurs de livraison et crochets d’interface utilisateur en option.
1. Couche de données (stockage, accès et mise en cache)
- DB relationnel: Store entités principales (utilisateurs, appareils, préférences, notifications, journaux de livraison).
- Redis: Sert de couche de recherche à grande vitesse pour les jetons actifs, les livraisons récentes et les règles de suppression en temps réel.
- ORM ou couche d’accès aux données: Utilisez une abstraction propre pour appliquer la validation, les paramètres de champ et les contraintes de schéma. Évitez d’écrire SQL brut dans les boucles de livraison.
- Lire l’utilisation des répliques: Achetez des requêtes de lecture à volume élevé (par exemple, des recherches de fan-out) aux répliques pour empêcher l’écriture.
2. Couche d’application (routage, filtrage, segmentation)
La couche d’application est le cerveau du système. Il sait quoi envoyer, à qui, quand et dans quelles conditions. C’est là que la logique commerciale vit.
- API d’ingestion: Gère les demandes entrantes des services internes (OTP, outils marketing, déclencheurs transactionnels).
- Service de routage des messages: Décide quels utilisateurs / appareils doivent obtenir quel message. Rejoint les métadonnées du message avec des ensembles de jetons redis.
- Moteur de préférence et de règles: Applique l’opt-in / out, les limites de canal (par exemple, les pings marketing max 2 par jour) et les fenêtres temporelles (par exemple, pas de messages à 2 heures du matin).
- Contrôleur de taux: Exécution des messages par locataire, par plate-forme, par région. S’intègre aux compteurs redis ou aux algorithmes de fenêtre coulissants.
3. Couche d’intégration (services de livraison et travailleurs)
Chaque plate-forme (APNS, FCM, WebPush) a ses bizarreries – donc ne les résume pas derrière une interface générique. Au lieu de cela, traitez-les comme des citoyens de première classe avec des services de livraison dédiés.
- APNS Worker: Utilise l’authentification basée sur les jetons via JWT. Les poignées poussent sur HTTP / 2. Gère le pool de connexions TCP et les limites de taux d’Apple.
- Travailleur du FCM: Auth via des comptes de service. Messages par lots par sujet ou groupe d’utilisateurs. Trace les erreurs par périphérique (par exemple, non enregistrées, le quota dépassé).
- WEBPUSH WORKING: Implémente Vapid, chiffre les charges utiles à l’aide de la cryptographie de la courbe elliptique et envoie directement aux URI de terminaison.
- Réessayer la file d’attente: Toute livraison échouée est récompensée par un revers exponentiel. Les DLQ (files d’attente de lettres d’adaptation) capturent des échecs persistants pour l’inspection.
4. Couche d’interface utilisateur (facultatif, orienté administrateur)
Tous les systèmes n’ont pas besoin de cela, mais pour les opérations de marketing internes ou les équipes de produits, un tableau de bord léger peut être utile.
- Compositeur de campagne: Créer et planifier la notification explose vers les segments d’utilisateurs avec des outils WYSIWYG.
- Aperçu et ciblage: Test en direct sur les appareils de test ou les seaux A / B avant un déploiement complet.
- Audit d’activité: Tableau de bord en temps réel montrant ce qu’il y a dans la file d’attente, ce qui est livré et ce qui a échoué (avec des codes de raison).
Conseils de conception
- Divisez chaque travailleur en microservices apatrides qui peuvent évoluer horizontalement.
- Ne réutilisez pas le même service pour la livraison et les commentaires (par exemple, les reçus APNS). Isoler ces flux pour la résilience.
- Ajouter les ID de journalisation et de corrélation structurés à chaque couche pour la traçabilité.
Considérations d’évolutivité
Les systèmes de notification push n’ont pas seulement besoin de travailler – ils ont besoin de travailler * rapidement * et * à grande échelle *, sous des surtensions de trafic imprévisibles. Cette section décrit les modèles, les stratégies d’infrastructure et les garanties nécessaires pour maintenir le débit élevé et les latences faibles, même lorsque vous envoyez des millions de messages par minute.
Échelle horizontale entre les niveaux
Chaque composant du système – API INGESTtion, routeur, travailleurs, files d’attente – devrait être évolutif horizontalement. Cela permet un réglage indépendant des goulots d’étranglement sans trop proposer l’ensemble du pipeline.
- Passerelles API / entrée: Les API avant doivent être à l’échelle automatique en fonction de CPU / RPS. Utiliser la limitation des services en aval.
- Travailleurs apatrides: Les livreurs et les routeurs doivent être apatrides et conteneurisés. Utilisez Kubernetes HPA (Horizontal POD Autoscaler) ou les règles d’autoscalités de Fargate basées sur la profondeur de file d’attente, le processeur ou la latence.
- Échelle basée sur la profondeur de file d’attente: Suivez la taille du backlog et engendrer plus de travailleurs lorsque la profondeur franchit le seuil (par exemple, leg kafka ou la longueur de file d’attente de lapin).
Sharding et partitionnement
- Shard par user_id: La livraison de partition charges de travail par ID utilisateur hachée pour préserver la localité et empêcher les affirmations dans la base de données ou le cache de jeton.
- Partionnement de Kafka: Utilisez des clés de message en fonction de l’ID utilisateur ou du locataire pour acheminer les notifications vers le bon fragment de groupe de consommateurs.
- Partionnement de la base de données: Pour de grandes tables comme
livraison_logs
, Utilisez le partitionnement basé sur le temps (par exemple, mensuel) pour maintenir la vitesse de requête.
Optimisations de performances de fan-out
Le vrai goulot d’étranglement dans les systèmes à grande échelle est un fan-out: mappage d’un message logique à des milliers ou des millions de jetons d’appareil.
- Union redis set: Utilisez Redis pour obtenir tous les jetons pour un utilisateur ou une cohorte instantanément à l’aide des opérations de set.
- Appels API par lots: Messages de groupe par plate-forme et endormi (par exemple, FCM prend en charge jusqu’à 500 jetons par demande par lots).
- Déduplication de jeton: Assurez-vous qu’aucun jeton en double entre dans les files d’attente de livraison. Maintenir l’unicité via Redis ou le prétraitement.
Stratégie de mise en cache
- Jetons: Mis en cache par ID utilisateur. TTL actualisé lors de la livraison ou de la connexion.
- Préférences: Règles de suppression du cache (par exemple, heures silencieuses, capuchons de fréquence) dans Redis ou Memory-local Store.
- Étranglement: Les compteurs redis (incry + TTL) ou les seaux de jeton pour les CAP au niveau des locataires et mondiaux.
Modèles de résilience
- Isolement de la cloison: Piscines de travailleurs séparés par plate-forme. Un ralentissement du FCM ne devrait pas bloquer les APNS envoyés.
- Files d’attente de lettres de mort: Les messages défaillants persistants (par exemple, les jetons non valides) sont déchargés et enregistrés pour l’inspection sans calculer les flux de livraison.
- Circuits Breakers: Arrête temporairement les réchauffages aux fournisseurs en aval montrant des taux de défaillance élevés (par exemple, APNS 503S).
- Stratégies de revers: Utilisez un backoff exponentiel avec une gigue pour des files d’attente de réessayer. Évitez les tampons pendant la limitation du fournisseur.
Benchmarks de débit (cibles de base)
- Ingestion de l’API: 2 000 à 10 000 RP par nœud en fonction de la taille de la charge utile.
- Routage et fan-out: 5 000 à 20 000 recherches d’appareil / sec avec le partitionnement Redis +.
- Débit des travailleurs de la livraison:
- APNS: ~ 5 000–10 000 pousses / min par connexion (HTTP / 2 multiplexé)
- FCM: ~ 12 000 / min avec des demandes de lots
- Webpush: ~ 2 000 / min (le point de terminaison unique envoie)
Besoin d’aide pour faire de votre pipeline Push Pipeline à l’épreuve?
Le bâtiment pour l’échelle est plus que des gousses de mise à l’échelle automatique. Du réglage de Kafka à l’optimisation des fan-out et aux disjoncteurs, nous pouvons vous aider à concevoir une infrastructure push qui ne clignote pas, même le jour de lancement.
Architecture de sécurité
Les systèmes de notification push interfacent avec les données utilisateur sensibles, les plates-formes de messagerie cloud et les services internes. Si la sécurité n’est pas cuite dans chaque couche – du stockage de jetons aux interactions API – vous vous préparez pour des fuites de confidentialité, des vecteurs d’abus et des échecs de conformité. Cette section couvre les principes et pratiques de conception de sécurité essentiels pour durcir votre système de bout en bout.
1. Authentification et autorisation
- Contrôle d’accès interne: Toutes les API internes (ingestion, planification, routage) doivent être protégées avec des JWT de courte durée ou des TL mutuels, en particulier s’ils sont accessibles entre les services ou les environnements.
- Politiques de la passerelle API: Utilisez IAM ou RBAC au niveau de la passerelle pour restreindre les services ou les utilisateurs peuvent soumettre différents types de notifications (par exemple, transactionnels vs marketing).
- Séparation des locataires: Si vous soutenez les systèmes multi-locataires, appliquez une isolation stricte basée sur les locataires dans chaque requête, itinéraire et flux de répartition des messages.
2. Gestion des informations d’identification de la plate-forme
Les intégrations tierces avec APNS et FCM nécessitent des secrets qui doivent être gérés avec soin.
- Stockez les clés dans un gestionnaire secret: Utilisez des outils comme AWS Secrets Manager, Hashicorp Vault ou GCP Secret Manager pour stocker les touches APNS et les informations d’identification FCM.
- Tourner périodiquement les références: Créez l’automatisation pour faire tourner les informations d’identification de service au moins trimestriellement.
- Limiter les portées clés: Utilisez des comptes de service avec les moins de privilèges requis, non plus, pas moins.
3. Sécurité en charge utile
- N’incluez pas PII dans les charges utiles Push: Les charges utiles sont souvent visibles au niveau du système d’exploitation (en particulier Android). N’incluez jamais les noms, les adresses e-mail ou les jetons sensibles.
- Crypter au repos et en transit: Toutes les données de la base de données et Redis doivent être cryptées à l’aide du chiffrement AES-256 ou de la plate-forme.
- Encryption de charge utile sur le Web: La poussée Web basée sur le vaporisateur nécessite un chiffrement de la courbe elliptique (NIST P-256); Cela doit être géré correctement pour éviter les défaillances de livraison silencieuses.
4. Protection des abus et limitation des taux
Laissée sans contrôle, un système de poussée peut être armé, soit aux utilisateurs de spam, soit pour surcharger l’infrastructure de livraison.
- Limites de taux par service: Utilisez des compteurs Redis ou des algorithmes de boucket qui fuisent pour appliquer les plafonds de taux par API et par location.
- Exécution du quota: Les limites de messages quotidiennes par utilisateur ou segment (en particulier pour le marketing) doivent être appliquées à la couche de routage.
- Trails d’audit de niveau Auth: Toutes les demandes d’envoi de messages doivent être vérifiables avec le nom du service, l’identité de l’utilisateur, l’IP et les métadonnées des messages.
5. Secrets et Hygiène des diplômes
- Utilisez l’isolement au niveau de l’environnement: Ne partagez jamais Dev, Staging et ProdalSelals pour les services push.
- Désactiver les journaux en texte en clair: Évitez les jetons de journalisation, les informations d’identification ou poussent des charges utiles avec des métadonnées sensibles dans les journaux. Masquez tout ce qui n’est pas nécessaire pour le débogage.
- Surveillance de l’utilisation abusive: Alerte si l’utilisation augmente en dehors des modèles attendus – en particulier les envoies à volume élevé à partir de comptes non comptables ou d’erreurs de FCM soudaines.
6. Protections côté client (minimal mais mérite d’être mentionné)
- Rotation des jetons au niveau de l’application: Assurez-vous que votre SDK mobile rafraîchit périodiquement les jetons et les désinscrivez-les lors de la déconnexion ou de la désinstallation.
- Pinage SSL (facultatif): Si l’application se connecte directement à votre backend pour vous inscrire à Push, envisagez d’épingler pour empêcher les attaques MITM.
Extensibilité et maintenabilité
Un système push évolutif n’est pas une version unique – elle doit évoluer avec les besoins de l’entreprise changeants, les mises à jour de la plate-forme et les modèles d’utilisation. L’architecture doit être modulaire, facile à étendre et en sécurité à entretenir sans introduire de régressions. Cette section décrit comment structurer votre infrastructure push pour l’évolution à long terme et la santé mentale des développeurs.
1. Architecture adaptée aux plugins
Une séparation propre entre la logique centrale et la logique spécifique à la livraison permet une itération plus rapide sans déstabiliser les flux de production.
- Livraison comme plugins: Encapsulez les APN, FCM et la logique WebPush dans des modules autonomes avec une interface de livraison partagée (par exemple, `Send (jeton, charge utile, config)`).
- Transformers de message: Implémentez les crochets de transformation par plate-forme (par exemple, les APN utilisent «alert», FCM utilise «Notification» + «Data»).
- Crochets pour la logique personnalisée: Autorisez les crochets préend et post-Send dans la couche de routage pour les remplacements spécifiques aux locataires, par exemple, la limitation personnalisée ou la logique A / B.
2. Pratiques de code propre
Les bases de code push ont tendance à devenir des terrains de vidage des hacks spécifiques à la plate-forme à moins d’être maintenus rigoureusement.
- Contrats d’interface stricts: Utilisez des interfaces claires pour les modules de livraison et les définitions de messages (par exemple, `MessagePayload ‘,` LivrotContext`).
- Gestion de la configuration centrale: Toutes les limites de taux, les politiques de réessayer et les informations d’identification de la plate-forme doivent être définies en externe dans les fichiers de configuration ou les gestionnaires de secrets.
- Limites de service: Évitez de coupler la logique de routage avec la logique de livraison. Traitez chacun comme un microservice déployable indépendamment.
3. Fonctionnalités des drapeaux et du versioning
Prise en charge le développement des fonctionnalités itératives et la compatibilité en arrière grâce à des versioning stricts.
- Formats de messages versés: Définissez les schémas de message avec le versioning («V1», «V2», etc.) et soutenez les mises à niveau en parallèle sans casser des formats plus anciens.
- Fonctionnalités pour les nouveaux flux: Découvrez la nouvelle logique de livraison derrière les drapeaux par locataire ou environnement pour minimiser le rayon de souffle.
- Modèle de dépréciation douce: Marquez les API héritées et les structures de messages pour le retrait planifié; Ajouter la journalisation lorsqu’elle est utilisée.
4. Couches de test et de validation
Une charge utile cassée peut se casser en échecs de livraison. Protéger chaque nouvelle version avec une forte validation.
- Validation du schéma: Utilisez le schéma JSON ou la validation Protobuf avant d’obtenir des messages pour expédier.
- Test de contrat: Définissez les attentes des modules de plate-forme à l’aide de PACT ou d’outils similaires pour empêcher la dérive d’intégration.
- Mode bac à sable: Fournissez un mode de test à sec ou de test pour les services internes pour simuler la poussée sans frapper les points de terminaison en direct.
5. Maintenabilité des anti-motifs pour éviter
- Comportement spécifique à la plate-forme de codage en dur: Toujours abstrait la logique de plate-forme en modules ou plugins.
- Mélanger la logique des locataires avec la logique globale: Utilisez des services dans les plans ou des conditions au niveau de l’itinéraire – ne vous incorporez pas de remplacements de locataires.
- Manque d’observabilité dans les nouveaux flux: Les nouveaux itinéraires ou modules doivent inclure des journaux structurés, des métriques et une gestion des erreurs dès le premier jour.
Optimisation des performances
Pousser des millions de notifications ne concerne pas seulement la conception du système – il s’agit également de l’efficacité de chaque composant sous pression. Le réglage des performances peut réduire la latence, améliorer le débit et empêcher les échecs en aval. Cette section se concentre sur la façon d’optimiser votre pipeline push aux couches de données, de traitement et de livraison.
1. Tunage de la requête de la base de données
- Index ciblés: Assurez-vous des index sur «Token», «user_id» et «notification_id» dans leurs tables respectives. Les index composites aident aux lectures de fan-out (par exemple, `device_id, statut`).
- Requête par ID de segment, pas les filtres utilisateur bruts: Évitez les requêtes de jointure complexes pendant les heures d’envoi. Précompute segments et cache ID utilisateur ou jetons dans Redis.
- Gestion du pool de connexion: Utilisez le regroupement de connexion (par exemple, PGBouncer) pour éviter les goulots d’étranglement de demande épineux pendant les courses à volume élevé.
2. Efficacité de fan-out de jeton
- Le lot se lit de redis: Lors de la récupération de jetons par utilisateur ou par segment, utilisez toujours «Smembers» + «Mget» dans des lots pipelinés.
- Boucles de livraison en vrac: Processus en lots (par exemple, 500 à 1 000 jetons par itération) pour éviter les frais généraux du réseau par périphérique.
- Modèle de charge utile Cache: Cache a rendu des charges utiles (titre / corps / métadonnées) lors de la diffusion de groupes d’appareils similaires.
3. Traitement asynchrone et réglage des travailleurs
- Préfet de message: Utilisez des dénombrements de préfet de message (par exemple, kafka `fetch.min.bytes`, Rabbitmq` prefetch_count`) pour réduire le temps inactif dans les travailleurs de la livraison.
- Livraison par lots: FCM et WebPush permettent un certain degré de lots – utilisez-le lors de l’envoi de campagnes non personnalisées.
- Convêtement de travailleur par région: Exécutez des pools de travailleurs isolés (ou des gousses) par région géographique pour minimiser la latence croisée et réduire le coût de sortie des nuages.
4. Limitation du taux et contrôle du débit
- Compteurs de fenêtres coulissantes: Utilisez des scripts Redis LUA pour implémenter les plafonds de taux au niveau de la plate-forme (par exemple, max 100k / sec par plate-forme ou locataire).
- Exécution de file d’attente: Ralentissez dynamiquement les taux de lecture du message du courtier lorsque les taux d’erreur augmentent (par exemple, les erreurs d’APNS 429 ou FCM).
- Contrôle de backoff: Sur les tentatives, utilisez des backoff exponentiels gênés pour empêcher les troupeaux de tonnerre de livraisons ratées.
5. Performances de rendu frontal (web push uniquement)
- Minimisation de la charge utile: Les messages WebPush doivent être compacts – dépuiser les métadonnées supplémentaires, garder ~ 2 Ko ou moins pour un rendu le plus rapide.
- Route en clic: Utilisez des paramètres de requête ou des liens profonds dans webpush `click_action` pour générer des expériences plus rapides dans l’application ou le navigateur.
- Enrichissement de rendu paresseux: Dans la mesure du possible, affichez un contenu de notification minimal et chargez tous les détails après le clic de l’utilisateur.
6. Surveillance et optimisation de la boucle de rétroaction
- Suivre les percentiles de latence: Ne surveillez pas seulement le délai de livraison moyen. Piste P90, P99 pour assister à la lenteur de livraison à longue queue.
- Filtrage de rétroaction: Ingérer uniquement la rétroaction de livraison critique (expiré du jeton, un appareil inaccessible) au lieu de tout, pour réduire la charge d’analyse.
- AGLÉGATION DE MÉTRIQUES: Utilisez des outils comme Prometheus avec des étiquettes conscientes de la cardinalité pour éviter l’explosion métrique en volume élevé.
Stratégie de test
Un système qui pousse à des millions de dispositifs ne peut pas s’appuyer sur une QA manuelle ou des tests isolés. La livraison est asynchrone, dépendante de tiers et en temps réel – ce qui signifie que les tests doivent être en couches, automatisés et résilients à la défaillance. Cette section couvre comment aborder les tests à toutes les phases: le développement local, les pipelines CI et le durcissement de la production.
1. Test unitaire
Les tests unitaires garantissent correctement la logique interne à travers le routage, la résolution de jetons et la génération de charge utile.
- Logique de routage de test: Valider les filtres de ciblage des utilisateurs, l’application des préférences et le fractionnement de la plate-forme.
- Ensembles de jetons simulés: Simulez les réponses Redis / DB avec de faux mappages de jetons pour tester la logique de fan-out.
- Validation du schéma: Assurez-vous que les charges utiles sont conformes aux schémas de plate-forme – structure d’alerte / message, champs spécifiques à la plate-forme, etc.
2. Test d’intégration
- Files d’attente de messages en mémoire: Exécutez Kafka / RabbitMQ localement (ou utilisez des conteneurs de test) pour simuler le flux complet du producteur à consommation.
- Faux adaptateurs de livraison: Mock APNS, FCM et WebPush avec des critères de terminaison locaux qui simulent les cas de réussite / défaillance, y compris les dispositifs étrangères ou non enregistrés.
- Flux de livraison de bout en bout: Affirmer qu’un message soumis à l’API d’ingestion atteint avec succès l’adaptateur de livraison moqué via la file d’attente, le moteur de règles et les services de travailleurs.
3. Test de contrat
Les tests contractuels valident que les modules de livraison de plate-forme ne se cassent pas en raison des modifications externes d’API ou de format de message.
- Utilisez des pactes ou des outils similaires: Définissez les attentes contractuelles pour chaque module de livraison (APNS, FCM, WebPush).
- Schémas versés: Gardez les formats de messages versés et vérifiez la compatibilité arrière sur les modifications.
4. Test de chargement et de stress
Les systèmes de poussée doivent tenir sous des volumes réels. Les tests de charge aident à valider les performances de la file d’attente, les coups de redis et les affirmations de base de données.
- Simuler les campagnes: Injectez 10m + simulation de messages dans la file d’attente pour observer la mise à l’échelle des travailleurs, les taux d’erreur et la latence des messages.
- Tests de pointe et de trempage: Valider comment le système gère les rafales courtes (100k / min) vs volume stable à long terme (10k / sec pendant des heures).
- Isoler les services lents: Surveillez les composants (par exemple, le routage, DB écrit, le cache de jeton) ralentit sous volume.
5. Couverture du pipeline CI
- Testez chaque chemin de poussée: Inclure la logique de livraison, les tentatives de secours et la gestion des défaillances dans le cadre des exécutions automatisées CI.
- Utilisez des jetons synthétiques: Générez des jetons factices APNS / FCM pour les charges utiles de test (n’utilisez jamais de vraies dans CI).
- Schémas de peluches: Valider automatiquement toutes les charges utiles par rapport aux spécifications de la plate-forme avant de fusionner en utilisant le schéma JSON ou les chèques Protobuf.
6. Chaos et injection de défauts (avancé)
Pour les équipes opérant à grande échelle, introduisez un chaos contrôlé pour attraper les cas de bord avant les utilisateurs.
- Remerciements de livraison de dépression: Simuler les retards ou les pertes de réseau entre le travailleur et le pushpurder.
- Injecter de mauvaises charges utiles: Champs corrompus ou violent les contrats de schéma pour confirmer les captures du système et isoler le problème.
- Ingestion de rétroaction de l’accélérateur: Retarder les reçus de livraison pour s’assurer que le système ne bloque pas ou ne s’écrase pas en raison des mises à jour d’état manquantes.
DevOps et CI/CD
Les systèmes de notification push couvrent plusieurs services, files d’attente, bases de données et intégrations tierces. Cette complexité exige un pipeline DevOps fiable automatisé qui peut construire, tester, déployer et revenir en toute confiance. Cette section couvre l’outillage et les pratiques nécessaires pour garder votre pipeline de livraison rapide, sûr et observable.
1. Conception du pipeline CI / CD
- CI stages: Lint → Tests unitaires → Tests contractuels → Tests d’intégration → Validation du schéma → Build Docker
- Étapes du CD: Déploiement canari → Contrôles de santé → Gate de métriques → Déployage complet
- Schéma pré-déploiement Diff: Les migrations de base de données de vérification automatique pour la compatibilité et les problèmes de temps d’arrêt potentiels (par exemple, l’ajout de colonnes non nulles sans défaut).
2. Stratégies de déploiement
- Déploiement bleu-vert: Pour des services avec état comme les planificateurs ou les API d’ingestion, utilisez le bleu-vert pour changer de trafic sans temps d’arrêt.
- Déploiement canari: Pour les livreurs et les routeurs, déployez dans un petit sous-ensemble de pod (par exemple, 5%) et observez pour les défaillances de livraison ou les erreurs d’API de plate-forme.
- Déploiements progressifs: Déplacer les fonctionnalités à l’aide des drapeaux de configuration (pas de branches de code) afin que les modifications puissent être basculées au moment de l’exécution.
3. Infrastructure comme code (IAC)
- Utilisez Terraform ou Pulumi: Gérez l’infra à travers AWS / GCP pour les files d’attente, DBS, Redis Clusters et VPCS.
- Environnements dynamiques: Tournez les environnements de test isolés sur les branches des fonctionnalités pour tester les flux de poussée de bout en bout sans une stadification polluante.
- Secrets Automation: Stocker les informations d’identification de service dans les gestionnaires secrètes et injecter dans des pods via des secrets scellés ou des siders.
4. Gitops et gestion de la configuration
- Configuration versée: Gardez les limites de taux, les politiques de réessayer et les remplacements des locataires en GIT – non codés en dur en services.
- Comportement de configmap: Injectez des paramètres spécifiques à la plate-forme dans les travailleurs (par exemple, la taille du pool APNS, WebPush TTL) via Kubernetes Configmaps.
- Rollback via Git Revert: Si une configuration ou un drapeau rompt la production, Gitops permet un retour en arrière rapide avec une auditabilité.
5. Validation de libération et chèques post-déploie
- Crochets post-déploie: Déclenchez automatiquement les contrôles de santé ou les tests de fumée après le déploiement.
- Regarder les mesures de livraison: Surveillez les taux de livraison, les codes d’erreur et la taille de la file d’attente dans les 15 à 30 minutes après le déploiement avant de mettre à l’échelle complètement.
- Comportement à défaut: Si les erreurs de livraison augmentent (par exemple, les jetons non valides, 403 à partir de FCM), le déploiement de halte automatique et les avis sur l’appel.
Besoin d’aide pour expédier des notifications push en toute confiance?
Construire un système de poussée robuste est une chose – l’opérer en production sans crainte est une autre. Si vous avez besoin d’aide pour configurer un pipeline CI / CD, des déploiements sécurisés et des versions en sécurité pour votre pile, nous l’avons déjà fait.
Surveillance et observabilité
Les systèmes de notification push sont asynchrones, distribués et s’appuient sur des services tiers à boîte noire comme les APN et le FCM. Sans observabilité appropriée, les défaillances passent inaperçues, des baisses de livraison silencieuses se produisent et le débogage devient une conjecture. Cette section décrit ce qu’il faut surveiller, comment tracer le flux de messages et comment construire des alertes significatives.
1. Journaux
- Journalisation structurée: Utilisez des journaux JSON avec des champs comme `Message_id`,` Device_id`, `plate-forme`,` statut` et `error_code` pour chaque étape de la livraison.
- ID de corrélation: Journaux de balises de l’ingestion → Routing → Livraison des travailleurs avec un ID de demande partagé pour la traçabilité de bout en bout.
- Champs sensibles à la réduction: Les jetons de masque, les ID utilisateur ou le contenu de charge utile dans les journaux, en particulier sur les plates-formes partagées ou tierces.
2. Métriques
Les mesures vous indiquent ce qui se passe à un niveau macro. Les regrouper entre les services pour détecter les problèmes à l’échelle de la plate-forme tôt.
- Débit de livraison: Messages envoyés par plate-forme, par minute. Décomposer par «locataire», «priorité» et «message_type» (transactionnel / marketing).
- Succès de livraison / taux d’erreur: Suivi “ Livré ”, «Dropped», «échoué» et «Rerying» Bucket – avec des balises pour la cause profonde («non enregistrée», «rate_limited», `invalid_token»).
- Latence de file d’attente: Il est temps de l’equare à la ramassage des travailleurs et du travailleur en passant par la reconnaissance de la plate-forme.
3. Trace
Les traces sont essentielles lorsque les messages disparaissent silencieusement ou sont retardés. Intégrez le traçage distribué dans chaque service interne.
- Trace des portées: Ingestion → Recherche Redis / Token → Vérification des préférences → ENQUEUe de file d’attente → DÉPASSION DES TRAVAILLANTS → LA PLATEFORME.
- Lien des journaux aux traces: Incluez les ID de trace dans les journaux et les liens de tableau de bord (par exemple, de Kibana à Jaeger / Tempo).
- Contrôle du taux d’échantillonnage: Tracez toujours les OTP et les messages échoués; Utilisez un échantillonnage probabiliste pour les campagnes pour réduire les frais généraux.
4. Tableaux de bord
Les tableaux de bord en temps réel aident les opérateurs et les ingénieurs sur appel à comprendre la santé du système en un coup d’œil.
- État de livraison de la plate-forme: Les dénombrements en temps réel de messages envoyés, échoués, repris par plate-forme (APNS / FCM / WebPush).
- Profondeur de file d’attente: La visibilité en direct dans les files d’attente de routage et de livraison – la profondeur de la file d’attente croissante indique la saturation ou le ralentissement en aval.
- Analyse du signal de rétroaction: Visualisez les invalidations de jetons, les limites de taux atteint et les reçus de rétroaction des plates-formes push.
5. Alerte
- Échec des alertes de pointe: Si les messages échoués dépassent un seuil (comptage absolu ou taux d’erreur%) dans une fenêtre coulissante.
- Alertes de latence de livraison: Si la latence P95 dépasse le SLA (par exemple, OTP> 3S, campagne> 30s).
- Croissance de la file d’attente de la lettre d’impasse: Alerte si les DLQ commencent à accumuler des messages – signale un chemin de défaillance persistant.
6. Surveillance de la boucle de rétroaction
Des plates-formes comme APNS et FCM envoient des commentaires de manière asynchrone. Ces reçus ont besoin de leur propre pipeline.
- Rétroaction des travailleurs de l’ingestion: Consommer et stocker des événements de jetons non enregistrés, des erreurs de livraison et des avis de limite de taux.
- Extraction de mesures: Les signaux de rétroaction agrégés dans les tableaux de bord et les distributions de classe d’erreur.
- Automatisation du nettoyage des jetons: Déclencher des travaux d’arrière-plan pour désactiver ou supprimer les jetons périmés en fonction des commentaires de la plate-forme.
Compromis et décisions de conception
Chaque choix architectural est livré avec des compromis. La conception d’un système de notification push évolutif signifie constamment équilibrer la latence par rapport au débit, la simplicité par rapport à la flexibilité et la fiabilité par rapport au coût. Cette section décrit certaines des décisions clés prises dans tout le système et les alternatives considérées.
1. Travailleurs spécifiques à la plate-forme vs interface de livraison unifiée
- Décision: Séparez les APN, FCM et WebPush en services de livraison isolés.
- Compromis: Plus de complexité de code et de déploiement, mais une bien meilleure isolement de défaillance, un réglage d’évolutivité et une débogabilité par plate-forme.
- Alternative: Une interface unifiée générique pourrait réduire la duplication du code mais nécessiterait une logique conditionnelle étendue et réduire l’observabilité.
2. Cache de jeton Redis vs livraison DB uniquement
- Décision: Utilisez Redis pour la recherche de jetons active et le fan-out pendant le routage des messages.
- Compromis: Nécessite des synchronisation d’arrière-plan et une logique d’invalidation, mais améliore considérablement le débit de livraison et réduit la charge de DB.
- Alternative: Les lectures DB directes pendant le fan-out simplifieraient l’architecture mais ne se feraient pas évoluer dans les volumes au niveau de la campagne.
3. Kafka pour la file d’attente de messages par rapport aux files d’attente plus simples
- Décision: Utilisez Kafka ou le journal distribué équivalent pour les files d’attente de routage et de livraison.
- Compromis: La courbe d’apprentissage plus abrupte et le fardeau de gestion infra, mais permet une durabilité, des tentatives et une évolutivité des consommateurs élevées.
- Alternative: Le lapin / sqs est plus facile à utiliser mais offrent moins de flexibilité pour les garanties de ventilateur ou de livraison à grande échelle.
4. Files d’attente de lettres mortes par rapport aux boucles de réessayer en ligne
- Décision: Utilisez des DLQ dédiés pour les défaillances permanentes et limitez les tentatives en place à 2 à 3 tentatives.
- Compromis: Surcharge opérationnelle légèrement plus élevée mais empêche le blocage des files d’attente et permet le traitement de la récupération asynchrone.
- Alternative: En ligne, réessayer avec Backoff est plus facile à mettre en œuvre, mais risque de surcharger les systèmes en aval ou de retarder les messages.
5. Partionnement de base de données temporelle par rapport à la croissance de la table plate
- Décision: Journaux de livraison de partition par mois pour contrôler la taille de l’indice et les politiques de rétention.
- Compromis: Route de requête plus compliquée et fragmentation potentielle d’accès aux données.
- Alternative: Une table monolithique serait plus facile à gérer initialement, mais dégraderait les performances et compliquerait le nettoyage de rétention.
6. compromis dans la vitesse des caractéristiques vs garanties de livraison
- Décision: Transactionnel séparé des flux de marketing à chaque couche – ingestion, files d’attente, services de livraison.
- Compromis: Plus de complexité de routage et d’infrastructure supplémentaire, mais empêche le trafic non critique de dégrader les chemins critiques (par exemple, OTPS).
- Alternative: Un flux unifié simplifie le routage mais risque l’impact des clients lors de lourdes charges de campagne ou de la plate-forme.
7. Zones de dette technique connues
- Nettoyage de jeton périmé: Besoin d’optimisation ou d’automatisation via l’ingestion de boucle de rétroaction.
- Pré-matière du segment: Exécute actuellement juste dans le temps pendant la campagne Send; devrait être déplacé vers des travaux de fond.
- Échelle du limiteur de taux: Les instances de redis partagées pour le contrôle des taux pourraient devenir un goulot d’étranglement dans le cadre des campagnes à l’échelle mondiale.
Ce que cette architecture va bien
La conception d’un système de notification push évolutif ne consiste pas seulement à envoyer des messages – il s’agit de livrer les bons messages, aux bons appareils, de manière fiable et à grande échelle. Cette architecture est spécialement conçue pour relever ce défi de front, équilibrer le débit, le contrôle et la maintenabilité dans un système hautement distribué.
Principaux à retenir
- Architecture découplée: L’ingestion, le routage et la livraison sont séparés proprement pour la résilience et l’évolutivité.
- Isolement de la plate-forme: Chaque service push (APNS, FCM, WebPush) est géré par un travailleur dédié réglé sur ses bizarreries.
- Cache de jeton et fan-out: Redis alimente la résolution de jetons rapides, permettant la livraison de messages à haut débit sans marteler votre base de données principale.
- Durabilité des données: Les files d’attente de messages garantissent une livraison fiable même lorsque les API de plate-forme échouent, les DLQ capturant les cas Edge pour une inspection ultérieure.
- Observabilité partout: Le traçage, les mesures et les journaux structurés rendent les pipelines de livraison de débogage et les flux de niveau utilisateur à grande échelle.
- Extensibilité de la fonction: Les composants modulaires, la logique basée sur le crochet et les versioning de schéma permettent au système d’évoluer sans casser les chemins hérités.
Opportunités d’amélioration future
- Escoupe à grains fins: Les plafonds par utilisation ou par périphérique pourraient réduire davantage la sur-notification et améliorer l’UX.
- Pipeline de matérialisation du segment: La segmentation de déchargement vers des travaux d’arrière-plan pré-programmées rendrait les lancements de campagne encore plus rapidement.
- Optimisation régionale de la livraison: Les livreurs géo-locaux pourraient réduire le coût de la latence et de la sortie du cloud en gardant les appels de plate-forme plus proches de l’origine de l’utilisateur.
Ce système ne fonctionnera pas seulement – il tiendra sous pression, évoluera avec la croissance et restera maintenable à mesure que les cas d’utilisation évoluent. C’est ce qui sépare les scripts de notification jetable d’une plate-forme de livraison de qualité de production en temps réel.
Besoin d’aide pour amener votre système de notification push à ce niveau?
La conception et la mise à l’échelle d’une architecture de notification push multiplateforme n’est pas un projet de week-end. Si vous cherchez à créer quelque chose de fiable depuis le premier jour ou à réparer ce qui montre déjà des fissures, nous pouvons aider à ingérer le système que vos utilisateurs attendent.
Testimonials: Hear It Straight From Our Customers
Our development processes delivers dynamic solutions to tackle business challenges, optimize costs, and drive digital transformation. Expert-backed solutions enhance client retention and online presence, with proven success stories highlighting real-world problem-solving through innovative applications. Our esteemed clients just experienced it.