Bonjour, je suis Stanislav Yablonskiy, développeur de serveur principal chez Pixonic (MY.GAMES). Les microservices sont une approche du développement logiciel (principalement le développement de backend) où la fonctionnalité est décomposée en les plus petits composants possibles, dont chacun fonctionne indépendamment.Chacun de ces composants a sa propre API.Il peut avoir sa propre base de données et peut être écrit dans son propre langage de programmation. Les microservices sont très populaires de nos jours, mais leur utilisation introduit une surcharge importante en termes de réseau, de mémoire et de CPU. Chaque appel se transforme en une nécessité de sérialisation, d’envoi et de réception de données sur le réseau.En outre, il n’est plus possible d’utiliser des transactions de base de données classiques, ce qui entraîne soit des transactions distribuées, soit une cohérence éventuelle. Les transactions distribuées sont lentes et coûteuses, tandis que la cohérence éventuelle signifie que les résultats des opérations peuvent ne pas apparaître immédiatement et que les données peuvent être temporairement incohérentes. L'utilisation de microservices oblige les développeurs à écrire plus de code dans chaque service individuel en raison des difficultés d'accès à la logique déjà écrite d'autres services. Parfois, il est difficile de réutiliser le code existant, ou vous ne pouvez même pas savoir qu'il existe - car d'autres personnes peuvent travailler sur un projet différent. Les « microservices » Débutant Overhead Le débogage devient beaucoup plus difficile avec les microservices. Un débogage régulier est presque inutile dans de telles conditions puisque vous ne pouvez pas déboguer tous les services à la fois. Sans un système de journalisation, de suivi et de mesures correctement mis en place, le débogage est presque impossible jusqu'à ce que le problème soit localisé. Cela signifie que vous avez besoin d’un environnement spécial dans lequel fonctionne non seulement le service en débogage, mais aussi toutes ses dépendances (autres services, bases de données, files d’attente, etc.). HTTP en haut de gamme Le protocole HTTP a beaucoup de fonctionnalités intégrées.Il prend en charge divers itinéraires, méthodes de passage de paramètres, codes de réponse et est pris en charge par de nombreux services prêts à l'emploi (y compris les proxies).Mais il n'est pas léger - il oblige chaque service à mettre en œuvre beaucoup de code pas aussi efficace pour analyser et générer des chemins, des en-têtes, etc. Protobuf au dessus La sérialisation pour la communication réseau et la désérialisation lors de la réception des messages sont nécessaires. Lorsque vous utilisez protobuf pour l'échange de messages, vous devez: Créer des objets, et les transformer en arènes, Les jeter immédiatement après utilisation. Cela crée beaucoup de travail supplémentaire pour le collecteur de déchets ou le gestionnaire de mémoire dynamique. Réseau Overhead La transmission de données sur le réseau augmente le temps de réponse du service.Cela augmente la consommation de mémoire et de CPU, même si les microservices s'exécutent sur le même hôte. Mémoire Overhead L'envoi et la réception de messages nécessitent le maintien de structures de données supplémentaires, en utilisant des fils séparés et en les synchronisant.Chaque processus séparé, en particulier celui qui fonctionne dans un conteneur, consomme une quantité significative de mémoire simplement en existant. CPU en tête Naturellement, toute cette communication entre les processus et entre les conteneurs nécessite des ressources informatiques. Base de données Overhead Les transactions normales sont impossibles lorsque les opérations couvrent plusieurs microservices. Les transactions distribuées sont beaucoup plus lentes et nécessitent une coordination complexe, souvent manuelle. Réseau Disc Overhead Les conteneurs de microservices sont souvent exécutés sur des disques montés sur le réseau, ce qui augmente la latence, réduit les performances (IOPS) et le rend imprévisible. Le projet Border Overhead La conception et le développement de microservices entraîne des difficultés à évoluer et à refactoriser un projet. Il n’est pas facile de changer la zone de responsabilité d’un service. Vous ne pouvez pas simplement déplacer le code d'un service à un autre. Cela nécessite généralement : beaucoup de temps et d’efforts, Plusieurs versions d’API, et des migrations complexes avant que la fonctionnalité ne puisse être redistribuée entre les services. De plus, si vous souhaitez mettre à jour ou remplacer une bibliothèque, vous devrez le faire sur tous les projets, pas seulement un. Les infrastructures au dessus Vous ne pouvez pas simplement « faire des microservices ». vous aurez besoin d’infrastructure – non, INFRASTRUCTURE : conteneurs (chaque contenant des copies de bibliothèques partagées), Les couvertures, les services cloud, Les chevaux (RabbitMQ, Kafka) outils de synchronisation de configuration (Zookeeper, Etcd, Consul), et ainsi de suite. Tout cela nécessite des ressources massives à la fois de la part des machines et des personnes. Déploiement indépendant Overhead Soutenir les déploiements indépendants signifie : Chaque service doit être déployable séparément, Chacun doit avoir son propre pipeline CI/CD, et la partie la plus difficile - API versioning. Chaque service devra prendre en charge plusieurs versions de l'API simultanément et les appelants devront suivre ces versions et mettre à jour leurs appels à temps. Ballon de boue distribué Au lieu de microservices propres, vous finirez par avoir une boule de boue distribuée – où la fonctionnalité est mal distribuée, les appels externes déclenchent des chaînes entières d’appels de service internes, et le tout est terriblement lent. Le Monolith est-il vraiment si effrayant ? Monolithes modulaires Les monolithes modulaires vous permettent d'éviter la plupart des dépassements de microservices - tout en fournissant une séparation qui peut être utilisée plus tard si nécessaire. Cette approche implique l’écriture de l’application (principalement le backend) en tant que service unique divisé en modules individuels avec : des limites clairement définies, et des interdépendances minimales. Cela permet de les diviser en services si l’échelle l’exige réellement. Attendez, vous pouvez le faire ? De nombreux avantages attribués à l'architecture de microservices peuvent être obtenus dans un monolith : La modularité peut être mise en œuvre avec des caractéristiques linguistiques : classes, espaces de noms, projets et assemblages. Plusieurs bases de données – possible, si vraiment nécessaire; Plusieurs langages – également possible, par exemple, de combiner C/C++/C#/Java avec des langages de script comme JavaScript, Python ou Erlang pour le développement de niveau supérieur; Interop – de nombreuses plates-formes prennent en charge l’appel de C/C++ à partir de Java, C#, Python, JavaScript ou Erlang; Les files d’attente des messages – il suffit d’utiliser la structure de données appropriée. Et quand vous voulez débrouiller — un clavier, et l'application entière est à portée de main. Acteurs Frameworks Les frameworks Actor vous permettent de construire des microservices – sans les microservices. Toute logique est divisée en classes (acteurs) qui ne communiquent que via un bus de message (chaises). Ces acteurs peuvent : existent dans un seul processus, ou Il est distribué sur plusieurs processus. De cette façon, vous obtenez le modèle de programmation de microservices, mais la plupart de l'infrastructure est gérée par le cadre lui-même. Conclusion Conclusion L’architecture doit être choisie en fonction de : les exigences du projet, les ressources disponibles, et l’expertise d’équipe. Les microservices ne sont pas une balle d’argent. Ils sont utiles pour de grands projets et des équipes – mais le monolith n’est pas obsolète et n’est pas une dette technique par défaut. Ce qui compte le plus, c’est l’équilibre entre flexibilité et complexité, évolutivité et maintenance – pour que le système que vous construisez soit efficace et durable.