Je comprends qu'un service dans une architecture de microservices doit avoir sa propre base de données. Cependant, en ayant sa propre base de données, cela signifie-t-il simplement avoir une autre base de données dans la même instance de base de données ou littéralement avoir une autre instance de base de données?
Par cela, je ne veux pas dire le partage de bases de données, qui est un non-non, mais plutôt l'instance de base de données.
Par exemple, si j'utilisais AWS et que j'ai 3 services, dois-je créer 3 bases de données pour chaque service sur une seule instance RDS ou créer 3 instances RDS contenant chacune une base de données utilisée indépendamment par chacun des 3 services?
Si l'utilisation de plusieurs bases de données sur une seule instance RDS est une meilleure idée, cela va-t-il à l'encontre de l'objectif d'avoir des services indépendants, car pour:
La ressource de l'instance RDS sera partagée entre les services. Le service A qui peut avoir une utilisation intensive de la base de données à un moment donné aura-t-il un impact sur le service B qui utilise une base de données différente mais sur la même instance RDS?
Tous les services dépendent de la version de la base de données de cette instance RDS.
Cela dépend vraiment de vos besoins d'évolutivité et de la manière dont vos instances de microservices doivent coopérer pour fournir un résultat unique. Il est utile de savoir quels sont les compromis:
Tout garder dans une seule base de données
Garder les bases de données séparées
Quel est le problème que vous résolvez?
Dans certains cas, vous ne vous inquiétez que des données éphémères. Si la base de données tombe en panne, ce n'est pas un gros problème. Dans ces cas, il se peut que vous n'ayez même pas besoin d'une base de données pour commencer. Gardez tout cela en mémoire et rendez les choses incroyablement rapides. Il s'agit de la solution la plus simple à utiliser.
Dans d'autres cas, vous avez besoin de l'intégrité des données, mais votre base de données est capable d'étendre sa capacité en fonction du nombre de nœuds qu'elle possède. Dans ce cas, une seule base de données est probablement plus que suffisante, et la gestion indépendante de sa réactivité est la bonne réponse.
Il y a plusieurs cas entre les deux. Par exemple, vous pouvez avoir des bases de données qui sont spécifiques à la région, donc pour chaque instance de votre service dans une région différente, vous avez une base de données distincte. Généralement, le partage de bases de données ne fonctionne pas bien entre les régions, c'est donc un moyen de localiser un peu les données et de contrôler vous-même la coordination.
Doctrine et réalité
J'ai lu un certain nombre d'articles sur les microservices et leur modularité. Les recommandations vont de la conservation du niveau frontal, du microservice et des données dans son ensemble au partage de la base de données et/ou du code frontal pour toutes les instances. Habituellement, une plus grande isolation offre la plus grande évolutivité, mais cela se fait au prix d'une complexité accrue.
Si votre microservice est lourd à calculer, il est logique d'autoriser le nombre de ces microservices à l'échelle selon les besoins - le partage de la base de données ou même du code frontal ne nuit ni n'entrave cette approche.
La réalité est que les besoins spécifiques de votre projet nécessiteront un ensemble différent de compromis pour effectuer le travail en temps opportun et gérer la charge du système que vous mesurez (plus un peu plus). Considérez le trio frontal, de microservices et de niveau de données entièrement isolé comme l'objectif suprême. Plus votre système sera sollicité, plus vous devrez probablement vous rapprocher de cet objectif. Nous ne sommes pas tous [insert name of highly successful web entity here]
, et ils n'ont pas commencé où ils sont maintenant. Parfois, il suffit de commencer avec une situation loin d'être parfaite et d'en être satisfait.
Supposons que vous ayez certains services qui peuvent utiliser le même type de système et de version de base de données, si vous utilisez des bases de données ou des instances de base de données différentes, vous ne devriez pas avoir à prendre de décision au moment de la conception. Au lieu de cela, vous devriez pouvoir prendre la décision au moment du déploiement, quelque chose que vous pouvez simplement configurer. Concevez vos services de manière à ce qu'ils soient indépendants de l'endroit où les bases de données d'autres services sont hébergées.
Pendant le fonctionnement, vous pouvez commencer avec une seule instance, et si le système fonctionne correctement, laissez-le de cette façon. Cependant, si vous remarquez que cela ne s'adapte pas bien à votre système, car différentes bases de données sur une instance partagent trop de ressources, vous avez toujours la possibilité d'utiliser différentes instances, si cela vous aide.
Un service ne viole donc pas l'architecture de microservice simplement parce que vous en laissez deux partager une ressource - il la viole lorsque le partage de la ressource devient obligatoire.
Ça n'a pas d'importance.
Le seul scénario où cela pourrait théoriquement avoir une importance est de savoir si un service doit migrer vers des versions différentes de la base de données. Mais même dans ce cas, il n'y a pas de réelle différence entre avoir des instances distinctes dès le départ et migrer ce service d'une instance partagée vers une instance distincte. Je dirais en fait qu'avoir des instances séparées uniquement à cause de ce scénario est un exemple de YAGNI.
Une instance RDS est une seule boîte. Si vous avez plusieurs bases de données sur une seule instance, elles partagent le CPU/la mémoire, etc.
Si les performances de votre microservice sont liées à ses performances de base de données: puis déployez plusieurs copies du microservice, chacune utilisant une base de données différente, mais avec chaque base de données sur la même instance RDS. Est inutile * (sauf pour le basculement). Votre cluster de microservices fonctionnera à la même vitesse qu'un seul microservice
Cependant, je dirais qu'un microservice lié aux performances de la base de données est inhabituel.
Habituellement, votre microservice récupère les données d'une base de données, exécute une logique et réécrit des informations dans la base de données. Le goulot d'étranglement des performances est la logique , pas la sélection et/ou l'insertion.
Dans ce cas, vous pouvez simplement partager la même base de données entre toutes vos instances de microservice
Le but de garder une base de données privée à un service est l'encapsulation. Votre microservice est une boîte noire que d'autres services du système utiliseront via une interface publique.
Il existe deux plans sur lesquels cette encapsulation opère:
Le premier est logique, au niveau de l'application. Votre service possède certains objets métier dans votre système et il doit conserver l'état de ces objets. Le fait que certaines bases de données en particulier soutiennent ces objets métier n'est qu'un détail d'implémentation. En conservant une base de données distincte, vous empêchez d'autres services d'avoir un accès par porte dérobée à votre implémentation, les forçant à utiliser votre interface publique à la place. Le but ici est une architecture propre et une programmation disciplinée. L'endroit exact où réside la base de données n'a pas d'importance à ce niveau, tant que votre service dispose des bons détails de connexion pour qu'il puisse les trouver.
Le deuxième niveau est opérationnel. Même si votre conception est une boîte noire parfaite, comme vous le faites remarquer, différents travaux colocalisés sur une seule machine peuvent se disputer des ressources. C'est une bonne raison de placer des bases de données logiques distinctes sur des machines distinctes. Comme d'autres réponses l'ont noté, si vos besoins ne sont pas très exigeants et que votre budget est serré, c'est un argument pragmatique pour la colocation sur une seule machine. Cependant, comme toujours, les compromis: cette configuration peut nécessiter plus de baby-sitting à mesure que votre système se développe. Si le budget le permet, je préfère presque toujours deux petites machines distinctes pour exécuter deux tâches plutôt que de partager une machine plus grande.
Je pense que cela pourrait aider à être un peu plus théorique ici. L'une des idées motivantes derrière les microservices est le partage de rien, les processus de transmission de messages. Un microservice est comme un acteur dans le modèle Acteur. Cela signifie que chaque processus conserve son propre état local et la seule façon pour un processus d'accéder à l'état d'un autre est d'envoyer des messages (et même alors, l'autre processus peut répondre comme il le souhaite à ces messages). Ce que l'on entend par "chaque microservice a sa propre base de données", c'est vraiment que l'état d'un processus (c'est-à-dire le microservice) est local et private. Dans une large mesure, cela suggère que la "base de données" devrait être colocalisée avec le microservice, c'est-à-dire que la "base de données" devrait être stockée et exécutée sur le même nœud logique que le microservice. Différentes "instances" du microservice sont des processus distincts et doivent donc chacune avoir sa propre "base de données".
Une base de données globale ou une base de données partagée entre des microservices ou même des instances d'un microservice constituerait, de ce point de vue, un état partagé. La manière "appropriée" de gérer cela du point de vue des microservices consiste à faire en sorte que la base de données partagée soit médiée par un microservice "base de données". D'autres microservices qui voulaient connaître le contenu de la base de données enverraient des messages à ce "microservice de base de données". Cela n'élimine généralement pas la nécessité d'un état local (c'est-à-dire par instance de microservice "bases de données") pour les microservices d'origine! Ce qui change, c'est ce que cet État local représente. Au lieu de stocker "User Sally est un administrateur", il stockerait "Le microservice de la base de données a dit" User Sally est un administrateur "il y a cinq minutes". En d'autres termes, au-delà de tout état qu'il contrôle complètement, il stockerait ses croyances sur l'état des autres microservices.
L'avantage de cela est que chaque microservice est autonome. Cela fait d'un microservice une unité atomique de défaillance. Vous (surtout) n'avez pas à vous soucier d'un microservice dans un état partiellement fonctionnel. Bien sûr, le problème a été déplacé vers le réseau de microservices. Un microservice peut ne pas être en mesure d'exécuter la fonction souhaitée en raison de l'impossibilité de contacter d'autres microservices. L'avantage, cependant, est que le microservice sera dans un état bien défini et pourrait bien être en mesure d'offrir un service dégradé ou limité, par exemple en travaillant sur des croyances dépassées. L'inconvénient est qu'il est très difficile d'obtenir un instantané cohérent du système dans son ensemble, et il peut y avoir beaucoup de redondance et de duplication (indésirables).
Bien sûr, la suggestion n'est pas de coller une instance d'Oracle dans chaque conteneur Docker. Premièrement, tous les microservices n'ont pas besoin d'une "base de données". Certains processus ne nécessitent aucun état persistant pour fonctionner correctement. Par exemple, un microservice qui se traduit entre deux protocoles n'a pas nécessairement besoin d'un état persistant. Car lorsqu'un état persistant est nécessaire, le mot "base de données" n'est qu'un mot pour "état persistant". Il peut s'agir d'un fichier contenant JSON ou d'une base de données Sqlite ou d'une copie locale d'Oracle si vous le souhaitez ou de tout autre moyen de localement stocker de manière persistante des données. Si la "base de données" n'est pas locale, du point de vue des microservices purs, elle doit être traitée comme un (micro) service distinct. À cette fin, il n'est jamais logique qu'une instance RDS soit la "base de données" d'un microservice. Encore une fois, la perspective n'est pas "un tas de microservices avec leurs propres bases de données RDS" mais "un tas de microservices qui communiquent avec les bases de données RDS". À ce stade, peu importe que les données soient stockées dans la même instance de base de données ou non.
De façon pragmatique, une architecture de microservices ajoute une énorme quantité de complexité. Cette complexité n'est que le prix à payer pour traiter sérieusement une défaillance partielle. Pour beaucoup, c'est la surpuissance qui ne vaut probablement pas les avantages. Vous devriez vous sentir libre d’architecturer votre système de la manière qui vous semble la plus avantageuse. Il y a de fortes chances que les préoccupations de simplicité et d'efficacité puissent conduire à des écarts par rapport à une architecture de microservices pure. Le coût sera un couplage supplémentaire qui introduit ses propres complexités telles que les interactions invisibles entre les services et les restrictions sur votre liberté de déploiement et d'évolution à votre guise.