Dans l’article précédent, nous avons discuté de deux modèles de processus pour le Serverless : run-to-completion et les processus de longue durée. La différence clé entre ces modèles réside dans le fait que l’instance de fonction se termine immédiatement après l’exécution. De plus, nous avons exploré deux scénarios : l’orchestration des données et l’orchestration des services.
Vous vous demandez peut-être si ces scénarios peuvent être implémentés en utilisant des processus de longue durée. La réponse est oui, mais il est important de noter que run-to-completion est la forme la plus pure du Serverless. Alors, quelle est la logique sous-jacente ?
Pour bien comprendre cela, nous devons introduire un concept crucial dans l’évolution de l’architecture des applications internet complexes : la mise à l’échelle, qui est le sujet de cet article.
Imaginez 200 utilisateurs accédant simultanément à la page d’accueil index.html de votre application web développée localement. Que se passe-t-il pour votre instance de serveur web local ?
Décrivons l’état de votre PC. Tout d’abord, 200 connexions TCP/IP sont établies entre les clients et votre PC, ce qu’il peut à peine gérer. Ensuite, les 200 clients initient simultanément des requêtes HTTP « GET/ ». Le processus principal de votre serveur web crée « nombre de cœurs CPU -1 » processus fils simultanément pour traiter ces requêtes. Notez que nous soustrayons un du nombre de cœurs CPU pour en réserver un pour le processus principal.
Par exemple, un CPU à 4 cœurs crée trois processus fils pour traiter trois requêtes client simultanément, tandis que les requêtes restantes sont mises en file d’attente. Les processus fils commencent à traiter les requêtes « GET/ », correspondent aux règles de routage, entrent dans la fonction de contrôle correspondante et renvoient index.html aux clients. Une fois qu’un processus fils a envoyé le fichier index.html, le processus principal le recycle et en crée un nouveau pour traiter la requête suivante jusqu’à ce que toutes les requêtes soient traitées.
En comprenant cela, la question suivante devient simple. Comment améliorer la vitesse de traitement de notre file d’attente client ?
Mise à l’échelle verticale vs. Mise à l’échelle horizontale
Une solution évidente est d’augmenter le nombre de cœurs CPU. Nous pouvons y parvenir en améliorant la configuration d’une seule machine, par exemple de 4 cœurs à 8 cœurs, ce qui donne 7 processus fils simultanés.
En plus d’augmenter directement les cœurs CPU, nous pouvons ajouter plus de machines (chacune avec 4 cœurs). En distribuant 500 clients à chacune des deux machines, nous pouvons également augmenter le nombre de processus fils simultanés à 6.
Augmenter ou diminuer les performances d’une seule machine est une mise à l’échelle verticale, qui s’accompagne souvent d’une courbe de coûts abrupte à mesure que les performances augmentent. Par conséquent, une réflexion approfondie est nécessaire lors de l’adoption de cette approche. D’autre part, augmenter ou diminuer le nombre de machines est une mise à l’échelle horizontale, une approche plus rentable et notre méthode de mise à l’échelle par défaut.
Maintenant, ajoutons un peu de complexité. Alors que index.html est un seul fichier, qu’en est-il des données ? Que ce soit une mise à l’échelle verticale ou horizontale, nous devons redémarrer les machines. Dans notre exemple de liste de tâches, les données sont stockées en mémoire et se réinitialisent à chaque redémarrage. Alors, comment préserver nos données pendant la mise à l’échelle ?
Stateful vs. Stateless
Les nœuds d’une topologie réseau peuvent être classés comme stateful ou stateless selon qu’ils stockent un état. Les nœuds stateful conservent l’état, ce qui signifie qu’ils stockent des données. Par conséquent, ils nécessitent une attention supplémentaire, exigeant stabilité et résistance aux changements fréquents. Par exemple, les bases de données utilisent généralement une structure maître-esclave, permettant de basculer immédiatement vers un nœud esclave si le nœud maître rencontre des problèmes, assurant ainsi une disponibilité continue du service.
Les nœuds stateless, en revanche, ne stockent aucun état ou ne conservent que temporairement des données non fiables. En raison de leur absence d’état, les nœuds stateless peuvent être mis à l’échelle horizontalement pour gérer une forte concurrence et réduits à zéro lorsqu’il n’y a pas de trafic (cela vous semble familier ?). Les nœuds stateful, cependant, ne peuvent pas faire cela. Dans les scénarios avec des fluctuations de trafic importantes entre les heures de pointe et creuses, nous devons concevoir des nœuds stateful pour gérer le trafic de pointe tout en maintenant les coûts opérationnels même pendant les périodes de faible trafic.
Une base de données est un nœud stateful typique car elle stocke de manière persistante les tâches des utilisateurs. De même, un équilibreur de charge est également stateful, un peu comme le processus principal qui maintient la file d’attente des clients dans notre expérience de pensée. Il doit stocker les connexions clients pour renvoyer aux clients les résultats traités par notre application web.
Pour revenir à nos modèles de processus, run-to-completion est intrinsèquement stateless car il se termine après l’exécution, ce qui rend impossible de l’utiliser seul pour un stockage persistant de données. Les processus de longue durée, en revanche, sont naturellement stateful car leur processus principal ne se termine pas, ce qui lui permet de stocker certaines valeurs.
Cependant, dans le Serverless, même si nous stockons des valeurs dans le processus principal d’un processus de longue durée, le fournisseur de cloud peut toujours le récupérer. Même avec des instances réservées, les données dans la mémoire des nœuds mis à l’échelle restent isolées.
Par conséquent, pour rendre les processus de longue durée stateless, nous devons éviter de stocker des valeurs dans le processus principal ou ne stocker que des variables temporaires. Les données persistantes doivent être déplacées vers des nœuds stateful dédiés comme les bases de données.
En séparant le stockage des données du nœud du processus principal et en veillant à ce que le processus principal ne conserve pas de données, notre application devient stateless. Nous stockons les données dans un nœud de base de données stateful séparé. Cet exemple se transforme en le scénario Serverless de longue durée discuté dans l’article précédent, où nous nous connectons à la base de données lors du démarrage du processus principal et accédons aux données via les processus fils. Cependant, cette approche présente un inconvénient majeur : elle augmente directement le temps de démarrage à froid. Existe-t-il une meilleure solution ?
Envisageons une approche alternative pour la persistance des données. Pourquoi devons-nous nous connecter nous-mêmes à la base de données ? Nos opérations CRUD (create, read, update, delete) sur les données impliquent essentiellement que les processus fils réutilisent la connexion TCP établie par le processus principal, envoient des instructions à la base de données et récupèrent les données. Imaginez si nous pouvions envoyer des instructions à la base de données en utilisant des requêtes HTTP comme POST, DELETE, PUT et GET. Cela ne nous permettrait-il pas de tirer parti des concepts d’orchestration des données et des services de la leçon précédente ?
Qu’est-ce que le BaaS
En effet, tout ce travail de base nous amène au protagoniste d’aujourd’hui : la BaaSification. Les opérations d’interface de données POST, DELETE, PUT et GET correspondent aux méthodes HTTP sémantiques des API RESTful. Prenons MySQL comme exemple : POST correspond à la commande CREATE, DELETE à DELETE, PUT à UPDATE, et GET à SELECT. Cette correspondance sémantique un-à-un nous permet de traduire naturellement les opérations MySQL en opérations d’API RESTful.
Les approches traditionnelles des bases de données, en raison de la réutilisation des connexions TCP et d’un faible surcoût de communication, sont plus rapides pour les mêmes opérations par rapport à HTTP. Bien que le Serverless puisse se connecter directement aux bases de données, se connecter aux bases de données traditionnelles en utilisant des adresses IP s’avère souvent difficile dans les environnements cloud avec segmentation VPC. Par conséquent, pour les connexions de bases de données Serverless, nous comptons généralement sur les services BaaS fournis par les fournisseurs de cloud, bien que de nombreux services BaaS ne soient pas encore matures.
Allant plus loin, si le Serverless n’est pas adapté aux nœuds stateful, pourquoi ne pas externaliser toutes les opérations stateful en tant qu’interfaces de données ? Cela permet à nos fonctions Serverless d’utiliser l’approche d’orchestration des données discutée dans la leçon précédente et d’obtenir une mise à l’échelle libre.
Résumé
La raison pour laquelle le modèle run-to-completion est considéré comme plus pur que le modèle de processus de longue durée est que ce dernier peut être trompeur, nous incitant à le traiter comme du PaaS et à l’utiliser comme un nœud stateful pour le stockage permanent de données. Cependant, dans le Serverless, même avec des processus de longue durée, les fournisseurs de cloud peuvent toujours récupérer nos instances de fonction.
Tout comme dans notre exemple où le stockage des données en mémoire entraînait des réinitialisations à chaque redémarrage, en adoptant un état d’esprit d’orchestration des données et en transformant les opérations de base de données backend en interfaces de données, nous pouvons décharger le stockage des données dans Serverless vers des applications backend et interagir avec elles en utilisant l’orchestration des données comme expliqué dans la leçon précédente. Cependant, nous devons aller au-delà de la simple création d’interfaces de données pour les applications backend. Nous devons adopter la BaaSification, libérant les ingénieurs backend des préoccupations opérationnelles côté serveur pendant le développement.
Pour la mise à l’échelle, nous pouvons choisir entre la mise à l’échelle verticale et horizontale. La mise à l’échelle verticale se concentre sur l’amélioration des performances d’une seule machine mais s’accompagne souvent d’une augmentation des coûts abrupte, ce qui en fait un choix prudent. La mise à l’échelle horizontale implique d’augmenter le nombre de machines, offrant une courbe de coûts plus douce et servant de méthode de mise à l’échelle par défaut.
Les nœuds stateful stockent des données, tandis que les nœuds stateless traitent les données sans les conserver. Seuls les nœuds stateless peuvent être mis à l’échelle librement. Les nœuds stateful, responsables du stockage de données critiques, exigent une manipulation minutieuse. Si nous voulons que les nœuds de notre topologie réseau puissent être mis à l’échelle librement, nous devons externaliser leurs opérations de données vers des nœuds stateful dédiés.
Lorsque nos fonctions Serverless accèdent à des nœuds stateful, il est préférable que ces nœuds fournissent des interfaces de données plutôt que de se fier uniquement aux commandes de base de données, car les connexions de base de données introduisent une surcharge supplémentaire pour les fonctions Serverless. De plus, pour simplifier le développement pour les ingénieurs backend, nous devons viser la BaaSification des nœuds stateful. Nous approfondirons la BaaSification dans des articles ultérieurs.
Novita AI est la plateforme cloud tout-en-un qui donne vie à vos ambitions en IA. API intégrées, serverless, instances GPU — les outils rentables dont vous avez besoin. Éliminez l’infrastructure, commencez gratuitement et réalisez votre vision de l’IA.
Lectures recommandées
Dévoiler la révolution : Explorer le monde du Serverless Computing
