Systèmes distribués. Modèles de conception. Critique de livre

Bonjour chers collègues. Aujourd'hui, nous publions une traduction de la prochaine critique du site de Ben Neidel - ce site vous intéressera certainement dans l'original. Cette fois, nous parlerons du livre " Distributed Systems. Design Patterns ", qui complète le livre " Master Kubernetes " qui a été publié au début de cette année et, en substance, est un analogue du GoF pour la conception de systèmes distribués.



Bonne lecture.

Au cours du week-end, j'ai lu le livre Distributed Systems. Design Patterns, par Brendan Burns . J'ai vraiment aimé le livre, même si, je dois l'avouer, je m'attendais à y trouver un peu de matière différente. Ainsi, dans la description du livre, les conteneurs ne sont mentionnés qu'en passant. Dans le même temps, bien que les modèles décrits dans le livre s'appliquent non seulement à la conteneurisation, presque tous les modèles décrits ici sont donnés dans le contexte du conteneur, puis ils sont pris en compte dans le pipeline de déploiement de Kubernetes. Cela s'est avéré d'ailleurs. Je commence tout juste à me familiariser avec le développement et le déploiement orientés conteneurs, et discuter des modèles architecturaux d'un tel point de vue «conteneur» a été une révélation pour moi. Cette approche m'a aidé à bien comprendre comment dans le paysage des microservices les petits services sont correctement différenciés, chacun ayant une opportunité spécifique.

L'auteur du livre, Brendan Burns, est le co-fondateur du projet open source Kubernetes. Par conséquent, il n'est pas surprenant que tous ses exemples d'application soient construits autour du déploiement de conteneurs basés sur des fichiers de configuration de Kubernetes. Au moment de lire le livre, j'étais un peu versé dans Docker et je ne savais rien de Kubernetes. Ainsi, j'ai essayé de comprendre le «but» des fichiers de configuration de Kubernetes en les lisant simplement. Cependant, je pense que le livre sera plus utile si le lecteur a au moins une certaine expérience avec Kubernetes.

En lisant le livre, je n'ai pas pu me débarrasser des associations avec le travail « Modèles d'intégration pour les applications d'entreprise » de Gregor Hope et Bobby Wolf. Beaucoup de modèles discutés par Burns sont très similaires aux modèles de file d'attente de messages discutés par Hope et Wolfe. En fait, je dois dire que de nombreux modèles sont même mentionnés dans les deux livres de la même manière (par exemple, Scatter / Gather). C'est logique, car le thème des deux livres est la partition de systèmes monolithiques complexes en un ensemble de petits services réutilisables étroitement adaptés. Je pense que l'on peut même affirmer que Burns décrit des approches spécifiques qui seront utiles dans la mise en œuvre des services de producteur et des services de consommation impliqués dans le fonctionnement des workflows basés sur les messages, les mêmes que ceux décrits dans le livre «Enterprise Application Integration Templates».

Encore une fois, je crois que les parallèles tracés entre ces deux livres témoignent de la puissance des modèles de conception. À la fois dans la façon dont ils nous conduisent à des solutions éprouvées et dans le fait que les modèles de conception facilitent la communication technique, car ils nous permettent de raisonner dans un langage commun.

Dans le même temps, l'une des approches que j'ai le plus appréciée est décrite dans le livre «Distributed Systems. Design Patterns »est précisément lié à la consommation de la file d'attente de messages. Burns conseille de ne pas forcer le conteneur de travail à extraire les messages directement du système (similaire à la façon dont cela se fait dans le système Simple Queue Service (SQS) d'Amazon), mais de créer un «ambassadeur» (modèle Ambassador). Un tel conteneur «ambassadeur» sera déployé avec le conteneur de travail et fournira une API généralisée pour manipuler les files d'attente. Le conteneur Ambassador vous permet d'abstraire les détails d'implémentation liés au stockage permanent des éléments dans la file d'attente de messages, afin que le conteneur de travail soit complètement indépendant de toute solution technologique spécifique.

«L'ambassadeur du conteneur-source de la file d'attente de travail» n'est qu'un exemple d'un sujet transversal qui traverse le livre comme un fil rouge: utilisez des collections de petits conteneurs pour que chaque conteneur individuel puisse se concentrer sur une tâche spécifique et être aussi réutilisable que possible. Burns explore ce concept au niveau du conteneur individuel, en parlant de paramétrage des conteneurs à l'aide d'arguments de ligne de commande et de variables d'environnement. Puis il monte d'un niveau, parle des modèles de side-car multi-conteneurs et d'ambassadeur dans un contexte à nœud unique. Enfin, il montre comment créer une puissante architecture de microservices à l'aide de modèles multi-conteneurs.

Je pense que Burns a parfaitement articulé le "rêve" de l'ensemble du paysage des microservices:

L'approche microservice présente de nombreux avantages, dont beaucoup sont liés à la fiabilité et à la flexibilité. Les microservices divisent l'application en petites parties, chacune étant responsable de la fourniture d'un service spécifique. En réduisant la portée des services, chaque service est en mesure de développer et de maintenir une équipe qui peut être alimentée avec deux pizzas.

La réduction de la taille de l'équipe réduit également le coût de maintien de ses activités.

De plus, l'émergence d'une interface formelle entre les microservices affaiblit l'interdépendance des équipes et établit un contrat fiable entre les services. Un tel contrat officiel réduit le besoin d'une synchronisation étroite de l'équipe, car l'équipe qui fournit l'API comprend dans quelle mesure il est nécessaire d'assurer la compatibilité, et l'équipe qui utilise l'API peut compter sur un service stable sans se soucier des détails de la mise en œuvre du service consommé. Une telle décomposition permet aux équipes de contrôler indépendamment le rythme de développement et le calendrier de sortie des nouvelles versions, ce qui leur donne la possibilité d'itérer, améliorant ainsi le code de service.

Enfin, la division en microservices augmente l'évolutivité. Étant donné que chaque composant est alloué à un service distinct, il peut être mis à l'échelle indépendamment des autres

(p. 79-80 en traduction russe)

Je parle du "rêve" car, comme le reconnaît Burns lui-même, il est difficile de concevoir un système de microservices et de concevoir son architecture. Et la surveillance et le débogage d'un tel système est beaucoup plus compliqué que la surveillance et le débogage d'un analogue monolithique. Juste avec cela, je peux facilement être d'accord. Selon ma propre expérience limitée de travail avec les microservices, je confirme que les services partagés deviennent rapidement hautement connectés et que les «contrats fiables» entre les services deviennent rapidement une cible mouvante, subissant de plus en plus de nouveaux changements.

En conclusion, je voudrais aborder le concept FaaS - «fonctionne comme des services». Des systèmes comme Lambda Service d'Amazon me font me sentir mélangé. Dans un sens extrêmement abstrait, j'aime de tels systèmes, mais je ne sais pas comment ils se manifestent dans une application particulière. Burns aborde FaaS dans la partie II sur les «Modèles de conception des systèmes de service», mais malheureusement cela ne clarifie pas complètement le problème de Faas pour moi.

J'ai vraiment aimé que Burns recommande d'utiliser FaaS pour résoudre uniquement un sous-ensemble des problèmes connus:

Comme pour les autres outils de développement de systèmes distribués, vous souhaiterez peut-être utiliser une solution particulière (par exemple, le traitement orienté événement) comme outil universel. La vérité est qu'une solution particulière résout généralement des problèmes particuliers. Dans un certain contexte, il s'avérera être un outil puissant, mais le tirer par les oreilles pour résoudre des problèmes communs crée des architectures complexes et fragiles.

(p. 135 en traduction russe)

De plus, merci beaucoup à lui d'avoir mentionné les difficultés qui se posent lors de l'utilisation de FaaS:

Comme mentionné dans la section précédente, le développement de systèmes utilisant l'approche FaaS vous oblige à faire des composants système faiblement couplés. Chaque fonction est indépendante par définition. Toutes les interactions sont effectuées sur le réseau. Les instances de fonction n'ont pas leur propre mémoire; par conséquent, elles nécessitent un stockage partagé pour stocker l'état. L'affaiblissement forcé de la connectivité des éléments du système peut augmenter la flexibilité et la vitesse de développement des services, mais en même temps peut compliquer considérablement son support.
En particulier, il est assez difficile de voir la structure globale du service, de déterminer comment les fonctions sont intégrées les unes aux autres, de comprendre quoi et pourquoi s'est mal passé en cas de défaillance. De plus, la nature orientée requêtes et sans serveur des fonctions signifie que certains problèmes seront difficiles à détecter.

(p. 136-137 en traduction russe)

Encore une fois, j'ai été surpris par le fait que la plupart des systèmes FaaS ne sont pas trop bons pour résoudre des tâches qui nécessitent un traitement actif:

... en outre, en raison de l'implémentation de services sans serveur, le temps d'exécution d'une instance de fonction est généralement limité. Cela signifie que l'approche FaaS n'est généralement pas adaptée aux applications qui nécessitent un long traitement de données en arrière-plan. (P. 138 en traduction russe)
Enfin, j'ai été satisfait de la remarque selon laquelle les FaaS deviennent économiquement inefficaces s'il est impossible d'assurer un fonctionnement long et ininterrompu du processeur:
Mais si vous avez tellement de demandes que la fonction est constamment active, vous risquez de surpayer le nombre de demandes traitées.

... à mesure que le service se développe, le nombre de demandes traitées augmente à un niveau tel que le processeur est constamment occupé à les traiter. À ce stade, les frais pour le nombre de demandes commencent à devenir non rentables. Le coût par unité de temps CPU des machines virtuelles cloud diminue à mesure que des cœurs sont ajoutés, ainsi qu'en réservant des ressources et des remises pour une utilisation à long terme. Le coût du paiement du nombre de demandes augmente généralement avec le nombre de demandes.

(p. 139-140 en traduction russe)

En conséquence, je ne comprenais toujours pas: quand est-il préférable d'utiliser des «fonctions comme services»? Je note que Burns décrit brièvement le travail avec des tâches à court terme orientées événements qui ne chargent pas beaucoup le processeur, comme l'authentification à deux facteurs (2FA). Cependant, étant donné que nous parlons de petites tâches à court terme à faible coût, la question se pose: pourquoi devraient-elles être mises à l'échelle indépendamment? Pourquoi ne pas simplement inclure ces fonctionnalités dans un autre service de conteneur étroitement lié au premier?

J'espère mieux gérer ces problèmes lorsque j'utiliserai les technologies FaaS dans la pratique.

Mis à part une certaine confusion avec FaaS, j'ai vraiment aimé le livre. Il est lu rapidement, facilement perçu. Cela nous rappelle une fois de plus l'énorme potentiel d'affaiblissement de la connexion entre les composants à tous les niveaux de développement d'applications. Enfin, il sera désormais beaucoup plus facile pour moi de maintenir une conversation avec mes collègues sur des sujets tels que les «conteneurs Sidecar».

Source: https://habr.com/ru/post/fr442514/


All Articles