Serveur, serverless et conteneur — la couche serveur d'application

Cet article fait partie du cours Les bases de l'informatique, qui construit depuis zéro les connaissances informatiques pratiques indispensables pour programmer et faire du vibe coding.
La différence, c'est la durée pendant laquelle le programme de traitement tourne. Des schémas te font distinguer la forme qui reste démarrée et attend, celle qui ne tourne qu'à la requête, et le conteneur, qui tourne avec son propre environnement d'exécution sur un seul OS.

Cet article porte sur les trois formes qui font tourner la couche serveur d'application.

Le mode toujours actif, qui laisse une machine démarrée ; le serverless, qui ne tourne qu'à l'arrivée d'une requête ; et le conteneur.

La différence, c'est la durée pendant laquelle le programme de traitement tourne.

Comme cette durée diffère, la façon d'ajouter de la capacité quand les requêtes augmentent et ce que tu dois préparer toi-même changent aussi.

Trois façons de faire tourner le traitement, distinguées par la durée d'exécution
Faire tourner lacouche applicativeTourner même sansrequêteTourner seulementsur requêteServeur toujoursactif, conteneurServerless
À partir du nœud de gauche, la séparation se fait selon qu'il doit tourner ou non quand il n'y a aucune requête. Le haut reste démarré ; le bas ne tourne que lorsqu'il est appelé.

Le serveur toujours actif reste démarré et attend les requêtes

Tu ne sais jamais quand une requête va arriver : tu lances donc server.js d'abord et tu le laisses attendre sous forme de processus (process ; un programme lancé et en cours d'exécution).

Laisser ce processus en place au lieu de le terminer, c'est le mode toujours actif (always-on ; garder le programme démarré pour pouvoir accepter une requête à tout moment).

Server listening on port 3000
Press Ctrl+C to stop

La première ligne montre qu'il écoute les requêtes sur le port choisi.

Comme l'indique la deuxième ligne, le processus ne se termine pas tant que tu ne l'arrêtes pas.

Ce qui est arrivé à cette heureLe processus server.jsCe qui repart vers la couche serveur Web
9:00 le lancementDémarre et se met en écouteRien ne repart encore
9:05 une requête /reservationsLa reçoit telle quelle et consulte les réservations3 réservations
9:06 rien n'arriveContinue d'attendre au lieu de se terminerRien ne repart
Ce qu'il y a dans un serveur qui reste démarré
Machine gardée en marche
Le processus node (lancé par node server.js)
  • Écoute les requêtes sur le port 3000
  • Ne se termine pas tant que tu ne l'arrêtes pas
server.js — le fichier du traitement de l'app de réservation
  • Contient le traitement des requêtes arrivant sur /reservations
  • Interroge la couche base de données sur le nombre de réservations
L'OS, et le node que tu as installé toi-même
  • Tu installes node depuis le site officiel
  • Tu appliques aussi les mises à jour de l'OS
Le cadre extérieur est l'ordinateur que tu gardes en marche. À l'intérieur, le processus node écoute, et à l'intérieur de celui-ci, le server.js que tu as écrit est chargé.

Le server.js le plus intérieur n'est pas la seule chose que tu prépares toi-même.

Tu prépares aussi la machine que tu gardes en marche, l'OS qui tourne dessus et node.

C'est là la grande différence avec le serverless, vu juste après.

À l'intérieur du cadre se trouve la machine unique que tu prépares et gardes en marche.

Le processus ne se termine pas même quand aucune requête n'arrive : il attend, le port ouvert.

Le mode toujours actif reste en marche jusqu'à ce que tu l'arrêtes

Un serveur toujours actif, c'est un serveur que tu lances à l'avance et que tu laisses attendre les requêtes.

C'est node server.js qui le démarre, le processus ne se termine pas tant que tu ne l'arrêtes pas, et c'est toi qui prépares la machine gardée en marche, l'OS et node.

Le serverless ne fait tourner le traitement qu'à l'arrivée d'une requête

Avec le serverless (serverless ; forme dans laquelle le programme de traitement ne tourne qu'à l'arrivée d'une requête et s'arrête une fois le traitement terminé), tu ne fais pas tourner toi-même de processus en écoute.

Ce que tu enregistres est un seul fichier, comme handler.js, et l'unité d'enregistrement s'appelle une « fonction ».

Avec le serverless, ce que prépare le fournisseur et ce que tu y déposes
Le système du fournisseur cloud
La partie qui reçoit la requête et appelle la fonction
  • Reçoit les requêtes qui arrivent
  • Décide combien tournent en même temps
Environnement préparé à chaque requête
  • Le fournisseur prépare l'OS et node
  • S'arrête une fois le traitement terminé
handler.js — le fichier du traitement de l'app de réservation
  • Ne traite que la requête arrivée sur /reservations
  • Sa durée d'exécution est plafonnée
Le cadre extérieur est le système du fournisseur cloud. Le cadre du haut est la partie qui reçoit les requêtes, et elle tourne en permanence. Le cadre du bas est l'environnement d'exécution préparé à chaque requête, et ton handler.js se trouve à l'intérieur.

La seule chose que tu touches est le handler.js le plus intérieur.

Les cadres extérieurs sont préparés par le fournisseur, qui applique aussi les mises à jour de l'OS et de node.

La question de savoir qui prépare quoi est traitée dans l'article sur le sur site, l'hébergement mutualisé et le cloud.

Tant qu'aucune requête n'est arrivée, handler.js ne tourne pas.

Un environnement d'exécution est préparé à chaque requête et s'arrête une fois la réponse renvoyée.

C'est là la différence avec le mode toujours actif, qui reste en marche jusqu'à ce que tu l'arrêtes.

Le serverless ne tourne que lorsqu'il est appelé

Le serverless, c'est la forme qui lance le traitement après l'arrivée d'une requête et l'arrête une fois la réponse renvoyée.

La seule chose que tu déposes est handler.js, et le fournisseur prépare à chaque requête l'environnement d'exécution qui le fait tourner.

La façon d'ajouter de la capacité change quand les requêtes simultanées augmentent

Le nombre de requêtes qui arrivent en même temps varie selon le moment de la journée.

S'y ajuster, c'est la mise à l'échelle (scaling ; augmenter ou diminuer le nombre d'éléments qui traitent, en fonction du volume de requêtes).

Commence par le cas où trois requêtes arrivent en même temps sur du serverless.

Quand trois arrivent en même temps, trois environnements démarrent aussi
Requête de A vers/reservationsRequête de B vers/reservationsRequête de C vers/reservationsPartie réceptricedu fournisseurEnvironnement 1handler.js tourneEnvironnement 2handler.js tourneEnvironnement 3handler.js tourne
Les trois de gauche sont toutes des requêtes vers le même /reservations. Après leur réception au centre, un environnement d'exécution est préparé par requête.

Jusqu'au nombre d'exécutions simultanées fixé par le fournisseur, aucune requête n'attend.

Tu ne fais rien non plus pour augmenter la capacité.

Un serveur toujours actif a besoin des mêmes rôles, mais ce ne sont pas les mêmes acteurs qui les tiennent.

Ce qui tient le même rôle dans le mode toujours actif et dans le serverless
===Se mettre enécouteLe processus nodeécoute sur 3000Partie réceptricedu fournisseurExécuter le codeserver.js dans lemême processusUn environnementpour handler.jsAjouter des unitésAjout manuel deprocessus/machinesLe fournisseur enajoute aussitôt
La colonne de gauche est le rôle, celle du milieu le serveur toujours actif, celle de droite le serverless. Les deux reliés par un double trait font la même chose ; seul l'acteur change.

Ce qui change, c'est de décider toi-même d'ajouter de la capacité ou d'en laisser le soin au système du fournisseur.

Une fois le nombre augmenté, les requêtes d'une même personne n'atteignent pas toujours le même élément : il faut donc que le traitement soit sans état (stateless ; un traitement ne conserve aucune valeur mémorisée par le traitement précédent).

Que la deuxième requête puisse lire une valeur mémorisée par la première dépend de l'endroit où tu as mis cette valeur.

Une valeur que tu utilises aussi à la requête suivante s'enregistre dans la couche base de données et se relit de là.

C'est pareil sur un serveur toujours actif : dès que tu ajoutes des processus, la valeur ne subsiste pas dans les autres.

Comment la capacité s'ajoute, et où les valeurs se conservent

Quand les requêtes simultanées augmentent, en mode toujours actif tu ajoutes la capacité toi-même, et en serverless c'est le système du fournisseur qui le fait.

Une fois le nombre augmenté, ce n'est pas toujours le même élément qui répond aux deux requêtes d'une même personne : une valeur que tu veux réutiliser va donc dans la couche base de données, et non en mémoire locale.

Le conteneur tourne sur un seul OS, et tu choisis parmi les trois selon ton besoin de toujours actif

La troisième forme, le conteneur (container ; format qui regroupe l'app, son environnement d'exécution et les fichiers nécessaires en un seul ensemble, pour le faire tourner sur un autre ordinateur avec la même configuration), tourne aussi longtemps qu'un serveur toujours actif.

Ce qui diffère, c'est que l'environnement d'exécution n'est pas installé sur l'ordinateur, mais empaqueté avec l'app.

Les mêmes trois apps sur trois machines, et dans des conteneurs sur une seule machine
Une machine préparée par app
Ce que tu prépares
  • Trois ordinateurs
  • Trois OS
  • Node.js 18 / Python 3.11 / Node.js 20 sur des machines distinctes
Une machine partagée par des conteneurs
Un ordinateur, un OS — trois conteneurs dessus
Conteneur 1
  • Un processus
  • Node.js 18
  • server.js
Conteneur 2
  • Un processus
  • Python 3.11
  • batch.py
Conteneur 3
  • Un processus
  • Node.js 20
  • admin.js
En haut, une machine est préparée par app : il faut donc trois machines et trois OS. En bas, trois conteneurs tournent, chacun comme un processus, sur un seul OS : une machine et un OS suffisent.

Il y a un seul OS, et chaque conteneur y tourne comme un unique processus.

Les environnements d'exécution sont séparés à l'intérieur des conteneurs : ce qu'utilise le voisin n'a donc aucun effet.

La part de matériel utilisée pour faire tourner quelque chose, comme le CPU et la mémoire, est une ressource (resource).

Le haut fait tourner trois OS, alors que le bas partage un seul OS : le même matériel peut donc porter plus d'apps.

Tu fais tourner plus de choses sur le même nombre de machines, et le coût pour les garder en marche est plus faible.

Aucun nouvel OS n'est démarré : le temps avant la mise en route est donc plus court aussi.

Faire tourner deux apps sur la même machine : l'emplacement de l'environnement change le résultat
Sur une machine,Node 18 et Node 20en même tempsEnvironnementinstallé dans l'OSUn seul node parmachineIl faut choisirl'un des deuxEnvironnementdans le conteneurChaque conteneur ason propre nodeLes deux tournentcôte à côte
À gauche, ce que tu veux faire tourner. Le chemin du haut installe l'environnement d'exécution sur l'ordinateur ; celui du bas le regroupe dans un conteneur. Sur la même machine, l'endroit où tu le places change le résultat.

Un seul OS ne peut contenir qu'un seul node, mais avec des conteneurs tu peux les faire tourner côte à côte avec des node distincts.

L'environnement d'exécution est séparé pour chaque app : monter la version de l'une laisse donc l'autre en marche.

L'ensemble de fichiers regroupé est une image de conteneur (container image ; l'app, l'environnement d'exécution et les fichiers nécessaires regroupés en un seul ensemble), et Docker est le logiciel le plus connu pour en fabriquer et en faire tourner.

Celui qui la fait tourner n'a qu'à recevoir cette image et la démarrer.

La même image unique donne la même configuration où que tu la fasses tourner
App, environnementet fichiers requisImage de conteneurregroupant le toutTon ordinateurServeur publicPC du collègue
L'image de conteneur, ce sont les trois éléments de gauche regroupés en un seul. Les trois endroits de droite démarrent cette image telle quelle : tu n'as donc pas à réinstaller l'environnement d'exécution.

Même quand le lieu d'exécution change, ce qui démarre est la même image unique.

Tu n'as pas à réinstaller l'environnement d'exécution sur le serveur public : tu peux donc publier la configuration exacte qui tournait chez toi.

Ce qui départage, au moment de choisir, c'est de savoir s'il doit tourner quand il n'y a aucune requête.

L'autre critère est la quantité que tu peux placer sur une seule machine.

Le besoin de toujours actif sépare les trois façons de faire tourner
Code à exécuterDoit tourner mêmesans requêteEnvironnement surla machineServeurtoujours actifTout regroupé avecl'environnementConteneurRépondre auxrequêtes suffitTourner seulementsi appeléServerless
À partir du nœud de gauche, la séparation se fait selon qu'il doit tourner ou non quand il n'y a aucune requête. Les deux lignes du haut restent en marche une fois démarrées, celle du bas se met en marche après l'arrivée d'une requête.

Sur les deux lignes du haut, le processus reste en marche même quand il n'y a aucune requête.

Ces deux-là se séparent selon que l'environnement d'exécution est installé sur l'ordinateur ou regroupé avec l'app.

Les deux formes toujours actives tournent aussi pendant le temps où aucune requête n'arrive.

En serverless, ce qui est compté n'est que le temps d'exécution et le nombre d'appels.

Tant que les requêtes sont clairsemées, cette différence se traduit directement par un écart de coût.

Choisir selon la durée d'exécution

La première séparation est de savoir s'il doit tourner quand il n'y a aucune requête.

Si ce n'est pas nécessaire, le serverless ; si ça l'est, un serveur toujours actif ou un conteneur.

Les conteneurs partagent un seul OS entre les apps : tu peux donc en placer beaucoup sur le même matériel et contenir le coût de leur maintien en marche.

Tu choisis aussi le conteneur quand tu veux que la configuration soit identique chez toi et sur le serveur public.

QUIZ

Vérification des connaissances

Répondez à chaque question une par une.

Question 1Entre un serveur toujours actif et le serverless, en quoi la durée d'exécution du programme de traitement diffère-t-elle ?

Question 2Dans quel cas utilises-tu un conteneur ?

Question 3Que fais-tu quand tu veux réutiliser à la requête suivante une valeur mise en mémoire au cours du traitement ?