Microservices en phase avancée
J'ai lu sur les efforts de l'équipe Amazon Prime Video pour évoluer et réduire les coûts de 90 % en combinant leurs microservices en un monolithe. Bien que je sois sûr qu'il y a plus à l'histoire ici, il y a des histoires similaires publiées sur Internet ; une sorte de réfutation de l'engouement pour les microservices de la dernière décennie.
Cela m'a rappelé les dernières années que j'ai passées sur Twitter, où le nombre de microservices (par milliers) a culminé puis a commencé à baisser, alors même que le trafic augmentait. Toutes sortes de logiques d'application ont été absorbées dans des plates-formes gérées monolithiques d'un type ou d'un autre. Le principe de création de microservices dédiés n'est pas intrinsèquement bon et, passé un certain point, ne semblait pas non plus être un retour sur investissement positif pour beaucoup de nos équipes.
Une architecture de microservice peut être coûteuse. Il y a eu un récit au cours de la dernière décennie selon lequel il s'agit d'une politique naturelle pour les grandes organisations d'ingénierie, car :
- Les équipes peuvent itérer sur leurs services en toute autonomie par rapport à l'organisation au sens large et à son code
- Les petits composants de l'architecture de service peuvent être modifiés sans perturber le système plus vaste
- L'architecture permet de définir des domaines d'application et de défaillance clairs et gérables via des services indépendants
- L'architecture permet des charges de travail réglables ou évolutives indépendamment
Il faut tenir compte de la complexité du travail qui est confié à de petites équipes propriétaires de services et à l'écosystème plus large qui en résulte, contrairement à un singulier ou à un petit nombre de monolithes. Le travail déchargé dépend de la maturité de la pile technologique de l'organisation ; mais cela peut inclure :
Répartition des responsabilités opérationnelles et des frais généraux entre toutes les équipes propriétaires de services
- La compréhension et la configuration des composants de l'infrastructure de service à partir des outils de planification et de déploiement des tâches, de la découverte de services, des cadres RPC, des machines virtuelles et du réglage associé, de la surveillance des services et de la journalisation
- Définitions et processus de développement distribués pour les SLO et les SLI, la gestion des défaillances et des pannes de service, la gestion de la contre-pression et la signalisation des erreurs
- Planification des capacités distribuée et souvent non coordonnée, tests de charge, mise en œuvre des tests d'intégration et responsabilités
- La logique d'application qui interagit avec de nombreux services backend navigue souvent dans une série de définitions d'API de service sur mesure, de sémantique, de modèles de données, de systèmes de gestion des versions et parfois même de protocoles différents
- Les ingénieurs doivent comprendre et raisonner sur l'architecture globale des services et les modèles de trafic afin de créer des éléments fonctionnels
- Solutions de contournement organiques pour les chemins de service sous-optimaux ou goulots d'étranglement, la réplication et la consommation de données distribuées , les dépendances de requêtes circulaires
- Approches localisées des problèmes d'inférence et de classement, de traitement d'événements, de traduction d'API de protocole HTTP/interne et de mappage de modèles de données
- Fragmentation générale et difficulté à maintenir les normes sur l'ensemble de la pile
Le problème est que le processus de création, de construction et d'opérationnalisation d'un nouveau service coûte cher . L'intégration de ce service dans l'architecture de service de production est difficile. L'attention requise pour régler un autre service pour un fonctionnement efficace ; pour configurer les comptes de service correspondants, les profils d'observabilité et de journalisation, les tests d'intégration, la rotation sur appel et tout le reste ne fait qu'ajouter à la maintenance et aux frais généraux opérationnels de l'équipe. La plupart des organisations manquent d'automatisation et d'échafaudages de bout en bout pour ce type de travail passe-partout complexe.
Cette surcharge est une dissuasion majeure pour les équipes de s'en tenir au principe architectural de microservice inspiré d'UNIX de « bien faire une chose ». Il est simplement plus facile de créer de nouveaux cas d'utilisation dans des services existants. À l'extrémité la plus éloignée du spectre, les équipes exploitent des services « macro » qui commencent à encapsuler tout ce dont ils sont responsables en tant qu'équipe, ce qui peut inclure une variété de produits ou de capacités. La qualité de propriété diminue avec le temps, car les réorganisations sont relativement fréquentes. Vous travaillez avec une boule de boue.
Les pannes de macro-services ne se limitent pas à un ensemble de fonctionnalités spécifiques, mais plutôt à une partie imprévisible ou sans principes du système, qui peut ressembler à des organigrammes historiques. Le site peut tolérer ou non l'indisponibilité de ces services. Il est plus difficile d'optimiser les services pour des charges de travail hétérogènes ; les chemins d'appel ne peuvent pas être démêlés. Un ancien collègue l'a inventé "le microlithe".
Les microservices encodent et encouragent l'optimisation locale dans l'architecture de service. Il est difficile de tenir les équipes responsables d'une conception raisonnée pour servir l'architecture lorsque l'objectif est la fédération du développement de services. De même, il est difficile de résoudre des problèmes d'optimisation à l'échelle du backend lorsque les propriétés des services dépendants sont sur mesure. Sans une architecture de service soigneusement conçue et des plates-formes de services de support, l'effet de levier est difficile à trouver - le code de plate-forme de produit réutilisable est dispersé dans une série de services volumineux ou de bibliothèques partagées ; les services frontaux sont généralement sur mesure.
L'effet de levier des microservices a été trouvé au niveau de la couche de calcul (tout ce qui orchestre et exécute des tâches de service ou des conteneurs), la découverte de services, la machine virtuelle (applicable dans certains contextes), le cadre de service (comme gRPC , Finagle ou Rest.Li ) et les outils de développement centralisés . Bien sûr, les maillages de services résument bien certaines de ces préoccupations.
Une autre façon d'aborder ces problèmes consiste à réduire les frais généraux fonctionnels. Ainsi, plutôt que d'essayer de réduire les frais d'infrastructure répétés liés à l'exécution du service , vous pouvez réduire les coûts des équipes qui réimplémentent des classes de travail communes . C'est pourquoi les plates-formes gérées connaissent un tel succès - même si la création ou l'exploitation d'un service coûte cher, si nous pouvons alléger sa logique applicative en l'externalisant vers une plate-forme gérée publique ou privée, cela devient moins un fardeau pour son équipe propriétaire.
Il est important que les organisations évaluent soigneusement les compromis architecturaux en fonction de leurs besoins spécifiques, de leurs objectifs et de la maturité de la pile technologique. Les microservices offrent certains avantages. Ils introduisent également des complexités et des frais généraux opérationnels qui semblent gérables au début, mais qui s'aggravent avec le temps. Le fait de ne pas résoudre ces problèmes rend le processus de développement de bout en bout un peu plus facile que de travailler dans un monolithe.
Quelques points à garder à l'esprit, surtout si vous travaillez avec un ancien microlithe :
- Les « gros services » ou les monolithes ne sont pas nécessairement mauvais ; ils nécessitent un type d'outillage, un support d'infrastructure et un ensemble de principes différents de ceux des microservices, mais ils doivent être conçus pour capturer des éléments communs bien définis de l'architecture de service
- Défendre le principe « une tâche, un service » a tendance à être beaucoup moins pratique que de tracer des limites intuitives autour des domaines de collaboration étroite, des problèmes de performance et des domaines de défaillance distincts - et de pousser les équipes à s'en tenir au plan
- Vous pouvez atténuer les complexités et les frais généraux de "trop de services" en réduisant la profondeur verticale de la pile dont les propriétaires de services sont responsables (cadres de services, maillage de services, calcul), ainsi que l'étendue de l'espace d'application via des services gérés ou plates-formes pour les flux de travail courants