[ Blog · Architecture ]

Gérer l'avalanche réseau pour maintenir votre backend mobile debout sous charge

Vous espérez encaisser dix mille utilisateurs simultanés sur votre nouvelle application. Votre serveur crash. C'est classique. La gestion de la concurrence réseau ne s'improvise pas avec un simple framework par défaut. Oubliez les tutoriels basiques. Regardons ce qui se casse vraiment sous le capot quand le trafic s'emballe.

Photo of Yanis
Yanis
Ingénieur / Développeur
·5 min read
Gérer l'avalanche réseau pour maintenir votre backend mobile debout sous charge

L'enfer silencieux des descripteurs de fichiers

Vous lancez votre application mobile. Le trafic monte en flèche. Le serveur tombe. Vous regardez les logs d'erreur. Rien d'évident. C'est le comportement habituel d'un système mal configuré. Vous avez oublié les limites imposées par le système d'exploitation. Linux traite chaque connexion réseau entrante comme un fichier. Un socket TCP ouvert correspond à un descripteur de fichier spécifique. Par défaut, cette limite est souvent fixée à une valeur dérisoire de 1024. C'est ridicule. Dix mille utilisateurs se connectent en même temps. Le noyau refuse les nouvelles requêtes instantanément. Le fameux problème C10k n'a pas disparu par magie avec l'arrivée du cloud.

Vous devez impérativement modifier les limites du kernel via la commande ulimit. Modifiez la variable fs.file-max dans le fichier sysctl.conf. C'est la base de l'ingénierie système. Une fois la limite de sockets est dépassé, le système rejette tout le reste de manière impitoyable.

Les réseaux mobiles sont notoirement instables. Les utilisateurs passent de la couverture 4G au réseau Wi-Fi d'un café. Leur adresse IP publique change. La connexion TCP d'origine est rompue unilatéralement. Le client mobile tente de se reconnecter en urgence. Votre serveur, lui, garde l'ancienne connexion ouverte dans l'état TIME_WAIT. Ce statut fantôme consomme de la mémoire RAM inutilement. Des milliers de sockets inactifs s'accumulent. La table de routage interne sature complètement.

Peut-être que vous pensez que votre framework web de haut niveau gère cela pour vous. Faux. Le framework vit dans l'espace utilisateur. Le blocage critique se produit bien plus bas, directement dans l'espace noyau. Vous perdez des paquets réseau. Les temps de réponse de l'API explosent. L'expérience utilisateur est détruite. Vous cherchez des solutions d'architecture complexes. Le problème est purement mathématique. Un descripteur ouvert consomme de la mémoire. Multipliez cette empreinte par dix mille. Calculez votre marge de manœuvre réelle.

Le piège de la couche applicative lors du routage

Le trafic arrive massivement. Vous le passez obligatoirement dans un répartiteur de charge frontal. NGINX ou HAProxy font souvent l'affaire pour ce rôle. La plupart des ingénieurs configurent par habitude un équilibrage de niveau 7. Le proxy lit les en-têtes HTTP de chaque requête. Il déchiffre l'intégralité du trafic TLS entrant. Le handshake TLS asymétrique consomme énormément de cycles CPU. Vous saturez vos processeurs simplement pour établir des connexions sécurisées.

Passez au niveau 4. Le proxy agit alors comme un simple routeur de paquets TCP. Il ne lit pas le contenu du trafic. Il transfère les octets bruts. C'est infiniment plus rapide. Vous soulagez instantanément l'infrastructure de périphérie.

Voici les deux seules choses qui comptent vraiment à ce stade critique :

  • Le déchiffrement TLS asymétrique.
  • La répartition round-robin bas niveau.

Vous pouvez explorer notre approche technique détaillée sur notre site. L'architecture réseau nécessite des choix stricts. L'équilibrage de niveau 4 demande de déporter la terminaison TLS sur les instances applicatives finales. C'est un compromis technique assumé.

Euh, disons que c'est surtout une question de transfert de ressources. Vous déplacez délibérément le goulot d'étranglement vers une zone plus facilement scalable. Il faut mesurer l'impact de ce choix. Ce type de configurations exigent une surveillance constante des métriques CPU sur les instances applicatives.

Gestion de la mémoire, concurrence système et choix du runtime applicatif pour encaisser la charge

Votre code s'exécute enfin. Le choix du langage dicte directement votre capacité à encaisser la charge réseau. Node.js utilise une boucle d'événements unique tournant sur le moteur V8. C'est purement asynchrone. L'I/O non bloquant repose sur les mécanismes epoll sous Linux. Node.js est idéal pour gérer beaucoup de connexions simultanées. Enfin, je veux dire, c'est ce qu'on lit partout sur les forums. Sauf que le garbage collector fige parfois le thread principal sous une charge massive d'objets JSON. Donc ce n'est pas si idéal au final. Le processus unique limite drastiquement l'utilisation des processeurs multicœurs.

À moins que le garbage collector décide soudainement de...

Passez à Go. Les goroutines changent totalement la donne. Le multiplexage M:N associe des milliers de goroutines légères à seulement quelques threads du système d'exploitation. Une goroutine coûte environ deux kilo-octets de RAM au démarrage. Vous lancez cent mille goroutines sans transpirer. Le scheduler interne du runtime Go gère la concurrence avec une efficacité chirurgicale. Les changements de contexte sont extrêmement rapides.

Regardez l'architecture de WhatsApp. L'application gère des millions de connexions actives par nœud serveur. Ils utilisent Erlang. La machine virtuelle BEAM implémente nativement le modèle d'acteur. Chaque connexion utilisateur est un processus léger totalement isolé en mémoire. Un processus crashe suite à une erreur. Les autres continuent de fonctionner sans aucune interruption. Le code Erlang est conçu pour les télécoms. La résilience est codée dans l'ADN du langage. C'est une véritable leçon d'architecture distribuée.

La phase initiale de dévelopement doit intégrer ces contraintes dès le premier jour. Vous ne changez pas de runtime en plein milieu du cycle de vie du produit. C'est une erreur suicidaire.

L'état asynchrone

Les applications mobiles modernes exigent du temps réel. Les notifications push traditionnelles ne suffisent plus. Vous ouvrez des WebSockets. La connexion TCP reste ouverte indéfiniment entre le client et le serveur. L'architecture devient soudainement stateful. Le client mobile est intimement lié à un serveur spécifique du cluster.

Si ce serveur tombe en panne, des milliers de clients tentent de se reconnecter simultanément. C'est le redoutable problème de la tempête d'orages. Le nouveau serveur désigné reçoit un pic de trafic massif d'un seul coup. Il s'effondre à son tour sous le poids des handshakes.

Je me demande souvent si on ne force pas l'utilisation du WebSocket partout par simple mimétisme technologique. Le Server-Sent Events (SSE) est parfois beaucoup plus adapté pour du flux de données unidirectionnel. Le protocole HTTP/2 multiplexe très bien les requêtes sans maintenir une machine à états complexe.

Définissez des règles strictes pour survivre. Vous devez surveiller méticuleusement :

  • L'empreinte RAM exacte par connexion active.
  • Le délai du ping-pong de keep-alive.
  • La stratégie de reconnexion exponentielle côté client.
  • L'éviction des sessions zombies dans le cache.
  • Le format de sérialisation binaire ou texte.
  • L'affinité de session sur le répartiteur de charge.

L'état global des connexions doit impérativement être partagé entre les nœuds. Vous utilisez Redis pour cela. Redis stocke l'emplacement réseau de chaque utilisateur connecté. Un nouveau message arrive. L'API interroge Redis pour savoir précisément quel nœud détient le socket ouvert du destinataire. Le routage interne fait le reste du travail. Consultez notre méthodologie pour voir comment structurer ces flux de données persistants de bout en bout.

La base de données en suffocation totale

Votre couche API encaisse le choc. Le réseau tient la charge. La base de données explose en vol. PostgreSQL crée un nouveau processus système lourd pour chaque connexion entrante. Dix mille connexions directes mettent le serveur en croix instantanément. La RAM est entièrement saturée. Le système d'exploitation invoque le tueur OOM en dernier recours. Le processus PostgreSQL est assassiné sans sommation. Fin de partie.

Vous devez utiliser un pooler de connexions externe. PgBouncer est l'outil standard de l'industrie. Il maintient un très petit nombre de connexions réelles avec la base de données. Il multiplexe ensuite les milliers de requêtes entrantes sur ce pool restreint.

Les requêtes attendent leur tour patiemment. C'est inévitable. Vous optimisez les index pour réduire le temps d'exécution. Vous évitez les jointures complexes sur les tables chaudes. Les verrous de ligne bloquent les écritures concurrentes. Un mauvais lock peut paralyser l'ensemble du serveur ,ce qui provoque une réaction en chaîne catastrophique.

Pensez aux bases de données NoSQL pour les accès à haute fréquence. L'équipe d'ingénierie de Discord a publiquement documenté sa migration épique. Ils stockaient initialement les milliards de messages dans MongoDB. Les limites de concurrence en écriture ont rapidement forcé un passage vers Cassandra. Les requêtes simultanées massives exigeaient une architecture sans maître. Les écritures sont distribuées uniformément sur plusieurs nœuds du cluster. Les goulots d'étranglement matériels disparaissent. Retrouvez des cas d'usage similaires documentés dans nos références.

Redis est un composant absolument indispensable pour soulager la base principale de ce fardeau. Vous cachez les lectures fréquentes. Vous mettez en mémoire tampon les écritures non critiques. Redis fonctionne sur un seul thread d'exécution. Il traite les commandes séquentiellement. Paradoxalement, cela évite les conditions de course sur les données:vous contournez les problèmes de verrous distribués.

Persistance asynchrone via les courtiers de messages distribués

Écrire directement dans la base de données de manière synchrone pour chaque action utilisateur est une erreur d'architecture fondamentale. Le client mobile attend la réponse. Le socket réseau reste occupé. Le thread applicatif est bloqué inutilement.

Découplez les processus vitaux. Utilisez un courtier de messages robuste. Kafka excelle particulièrement dans ce domaine précis. Il ingère des millions d'événements par seconde sans broncher. Kafka est fondamentalement un journal d'ajout immuable. Les écritures sur les disques physiques sont toujours séquentielles. Les performances d'I/O du système.C'est optimisé au maximum des capacités matérielles.

L'API de bordure reçoit la requête du client mobile. Elle publie immédiatement l'événement métier dans un topic Kafka. L'API retourne instantanément un code HTTP 202 au client. Le socket est libéré sur le champ. Le client mobile affiche une interface parfaitement réactive sans latence perceptible.

En arrière-plan, des groupes de workers consomment les messages de la file d'attente. Ils traitent la logique métier complexe. Ils insèrent ensuite les données formatées dans PostgreSQL par lots de plusieurs centaines de lignes. Le rythme d'écriture global est lissé mathématiquement. La base de données n'est jamais submergée par des pics imprévisibles. Elle ingère les données à son propre rythme optimal.

RabbitMQ offre une alternative très pertinente pour le routage de messages complexe. Les échanges AMQP dirigent intelligemment les messages vers différentes files de traitement selon des clés de routage dynamiques. Kafka privilégie le débit brut massif. RabbitMQ privilégie la flexibilité des règles de routage.

Le choix final dépend intrinsèquement de la nature de l'application. Une application de messagerie instantanée nécessite un débit d'ingestion massif. Une application e-commerce nécessite des transactions absolument garanties. Le design backend dicte la survie matérielle du produit face aux pics d'utilisation réels.

Fin de l'exercice. Vous avez maintenant les vraies métriques à surveiller. Les sockets, la mémoire, les pools de connexions. Arrêtez de surdimensionner vos instances à l'aveugle. L'ingénierie réseau exige de la précision. Appliquez ces concepts. Si votre architecture s'effondre encore sous la charge, c'est que votre design initial est à jeter.

[ Team ]

Entrust your project
to our app experts.

Our experts in web, mobile and AI applications build your project, delivering superior technical and functional quality within shorter timeframes.

Kosmos team — portrait 1
Kosmos team — portrait 2
Kosmos team — portrait 3
Kosmos team — portrait 4
Kosmos team — portrait 5
Kosmos team — portrait 7
Kosmos team — portrait 6
15
Experts
100+
Projects delivered
78%
Loyal clients
4.9/5
Average rating
[ Press ]

They talk about us.

Explore the mentions and analyses that spotlight our work and our innovations across the business and tech press.

Free quote · no commitment

Let's discuss your project.

Describe your project. Our team replies within 24 hours with free technical scoping, along with a clear estimate of costs and timelines. No commitment.

  • Reply within 24 hours from a project manager
    or engineer.
  • Technical scoping and quote, with no fees.
  • No commitment, your data stays
    confidential.
Quick estimate

Free scoping & estimate in less than 24h

Describe your project and we'll get back to you with a costed estimate and a roadmap.

Call us
01 76 50 66 44
Monday to Saturday, 9 AM to 6:30 PM