Situation actuelle
Nous mettons en œuvre (et maintenons maintenant) une application Web d'achat en ligne dans une architecture de microservices.
L'une des exigences est que l'entreprise doit être en mesure d'appliquer des règles sur ce que nos clients ajoutent à leur panier, afin de personnaliser leur expérience et la commande éventuelle. De toute évidence, un moteur de règles métier devait être mis en place, et nous avons implémenté un "microservice" spécifique pour cela (si nous pouvions encore l'appeler ainsi).
Au cours d'une année, ce moteur de règles est devenu de plus en plus complexe, nécessitant de plus en plus de données (par exemple le contenu du panier mais aussi des informations utilisateur, son rôle, ses services existants, certaines informations de facturation, etc.) pour pouvoir calculer ces règles.
Pour le moment, notre shopping-cart
microservice recueille toutes ces données à partir d'autres microservices. Même si une partie de ces données est utilisée par shopping-cart
, la plupart du temps, elle est principalement utilisée pour alimenter le moteur de règles.
De nouvelles exigences
Arrive maintenant le besoin d'autres applications / microservices pour réutiliser le moteur de règles pour des exigences similaires. Dans la situation actuelle, ils devraient donc transmettre le même type de données, appeler les mêmes microservices et constituer (presque) les mêmes ressources pour pouvoir appeler le moteur de règles.
En continuant ainsi, nous serons confrontés à plusieurs problèmes:
- tout le monde (appelant le moteur de règles) doit réimplémenter la récupération des données, même s'il n'en a pas besoin pour lui-même;
- les demandes adressées au moteur de règles sont complexes;
- en poursuivant dans cette direction, nous devrons transporter ces données tout autour du réseau pour de nombreuses demandes (pensez à μs A appelant μs B appelant le moteur de règles, mais A possède déjà certaines des données dont le moteur de règles a besoin);
shopping-cart
est devenu énorme en raison de toutes les données extraites;- J'en oublie probablement beaucoup…
Que pouvons-nous faire pour éviter ces problèmes?
Idéalement, nous éviterions d'ajouter plus de complexité au moteur de règles. Nous devons également nous assurer que cela ne devienne pas un goulot d'étranglement - par exemple, certaines données sont assez lentes à récupérer (10 s ou même plus), nous avons donc implémenté la prélecture de shopping-cart
telle sorte que les données soient plus susceptibles d'être présentes avant d'appeler les règles. moteur, et garder une expérience utilisateur acceptable.
Quelques idées
- Laissez le moteur de règles récupérer les données dont il a besoin. Cela y ajouterait encore plus de complexité, violant le principe de la responsabilité unique ( encore plus… );
- Implémentez un proxy μs avant le moteur de règles pour récupérer les données;
- Implémentez un «récupérateur de données» μs que le moteur de règles appelle pour récupérer toutes les données dont il a besoin en même temps (interrogation composite).
shopping-cart
, mais nous pourrions l'adapter assez facilement aux besoins des autres microservices (ils sont toujours liés aux utilisateurs, aux produits et aux commandes). Comme nous le voyons, ils auront besoin des mêmes données d'entrée, d'autant plus que l'entreprise est en mesure de choisir les prédicats à appliquer. Toutes les données sont fournies par d'autres microservices à l'exception du contenu du panier lui-même. La récupération des données n'est pas complexe en soi, mais elle devient complexe lorsque vous devez appeler ~ 10 autres microservices et maintenir la structure attendue par le moteur de règles.Réponses:
Faisons un pas en arrière pendant une seconde et évaluons notre point de départ avant d'écrire cette réponse de longueur susceptible d'être nouvelle. Tu as:
Ok, ce n'est pas terrible pour les microservices. Un problème immédiatement flagrant est que vous semblez mal comprendre ce que sont les microservices.
Vous devez définir une sorte d'API ou de méthode de communication que vos microservices utilisent et la rendre courante. Il peut s'agir d'une bibliothèque que tous peuvent importer. Il pourrait s'agir de définir un protocole de message. Il peut utiliser un outil existant ( recherchez des bus de messages de microservice comme bon point de départ).
La question de la communication interservices n'est pas un problème "résolu" en soi, mais ce n'est pas non plus un problème "roll your own" à ce stade. De nombreux outils et stratégies existants peuvent vous faciliter la vie.
Peu importe ce que vous faites, choisissez un seul système et essayez d'adapter vos API de communication pour l'utiliser. Sans une certaine manière définie pour vos services d'interagir, vous allez avoir tous les inconvénients des microservices et des services monolithiques et aucun des avantages des deux.
La plupart de vos problèmes en découlent.
Rendez-les moins complexes.
Trouvez des moyens de les rendre moins complexes. Sérieusement. Modèles de données courants, divisez votre moteur de règles unique en plus petits, ou quelque chose du genre. Améliorez le fonctionnement de votre moteur de règles. Ne prenez pas l'approche «tout coincer dans la requête et continuez à les compliquer» - regardez sérieusement ce que vous faites et pourquoi.
Définissez une sorte de protocole pour vos données. Je suppose que vous n'avez pas de plan d'API défini (comme ci-dessus) et que vous avez commencé à écrire des appels REST ad hoc chaque fois que nécessaire. Cela devient de plus en plus complexe car vous devez maintenant maintenir chaque microservice chaque fois que quelque chose est mis à jour.
Mieux encore, vous n'êtes pas exactement la première entreprise à mettre en œuvre un outil d'achat en ligne. Allez rechercher d'autres entreprises.
Maintenant quoi...
Après cela, vous avez au moins trié certains des plus gros problèmes.
Le problème suivant est cette question de votre moteur de règles. J'espère que cela est raisonnablement apatride, de sorte que vous pouvez le mettre à l'échelle. Si tel est le cas, bien que sous-optimal, vous n'allez pas au moins mourir dans un éclat de gloire ou construire des solutions de contournement folles.
Vous voulez que votre moteur de règles soit sans état. Faites en sorte qu'il traite uniquement les données. Si vous le trouvez comme un goulot d'étranglement, faites en sorte que vous puissiez en exécuter plusieurs derrière un proxy / équilibreur de charge. Pas idéal, mais toujours réalisable.
Passez un peu de temps à déterminer si l'un de vos microservices doit vraiment être intégré à votre moteur de règles. Si vous augmentez la surcharge de votre système de manière si significative juste pour obtenir une "architecture de microservices", vous devez consacrer plus de temps à la planification.
Alternativement, votre moteur de règles peut-il être divisé en morceaux? Vous pouvez obtenir des gains simplement en faisant des morceaux de services spécifiques à votre moteur de règles.
En supposant que ce problème existe après avoir résolu les problèmes ci-dessus, vous devez étudier sérieusement pourquoi cela se produit. Vous avez un cauchemar qui se déroule mais au lieu de comprendre pourquoi (10 secondes? Pour envoyer des données sur le portail d' achat ? Appelez-moi cynique, mais cela semble un peu absurde), vous semblez corriger les symptômes plutôt que de regarder le problème à l'origine des symptômes dans la première place.
Vous avez utilisé l'expression «récupération de données» encore et encore. Ces données sont-elles dans une base de données? Sinon, envisagez de le faire - si vous passez autant de temps à récupérer "manuellement" des données, il semble que l'utilisation d'une vraie base de données serait une bonne idée.
Vous pourrez peut-être avoir une conception avec une base de données pour les données que vous récupérez (selon ce que c'est, vous l'avez mentionné à plusieurs reprises), quelques moteurs de règles et vos clients.
Une dernière remarque est que vous voulez vous assurer que vous utilisez la version appropriée de vos API et services. Une version mineure ne doit pas briser la compatibilité descendante. Si vous vous trouvez à libérer tous vos services en même temps pour qu'ils fonctionnent, vous n'avez pas d'architecture de microservice, vous avez une architecture monolithique distribuée.
Et en fin de compte, les microservices ne sont pas une solution universelle. S'il vous plaît, pour le bien de tout ce qui est saint, ne le faites pas simplement parce que c'est la nouvelle chose branchée.
la source
Avec la quantité d'informations présentées sur le moteur de règles et ses entrées et sorties, je pense que votre suggestion non. 2 est sur la bonne voie.
Les consommateurs actuels du moteur de règles pourraient sous-traiter le processus de collecte des informations requises à un composant à des fins plus spéciales.
Exemple: vous utilisez actuellement le moteur de règles pour calculer les remises qui doivent être appliquées au contenu du panier. Les achats antérieurs, la géographie et les offres actuelles en tiennent compte.
La nouvelle exigence consiste à utiliser une grande partie de ces mêmes informations pour envoyer par e-mail des offres aux clients précédents en fonction des promotions à venir et des achats précédents. Les achats antérieurs, les offres actuelles et à venir en tiennent compte.
J'aurais deux services distincts pour cela. Ils s'appuieraient chacun sur le service du moteur de règles pour certains de ses travaux lourds. Chacun d'eux collecterait les données nécessaires à sa demande auprès du moteur de règles.
Le moteur de règles applique simplement les règles, les consommateurs n'ont pas à se soucier des données exactes dont le moteur de règles a besoin pour le contexte particulier, et ces nouveaux services intermédiaires ne font qu'une chose: assembler le contexte et transmettre la demande au moteur de règles et renvoie la réponse non modifiée.
la source
L'agrégation des données nécessaires à la décision doit être effectuée en dehors du moteur de règles. C'est parce qu'ils sont mieux conçus comme des services apatrides autant que possible. La récupération de données implique nécessairement un traitement asynchrone et un maintien d'état. Peu importe que la récupération soit effectuée par un proxy devant le service de décision, par les appelants ou par un processus métier.
Pour des raisons pratiques de mise en œuvre, je mentionnerai qu'IBM Operational Decision Manager commence à documenter et prend déjà en charge l'utilisation du produit dans des conteneurs Docker . Je suis sûr que d'autres produits fournissent également ce support et qu'il deviendra courant.
la source
Dans ma pensée simple, je suppose que cela aidera à extraire toutes les données requises en effectuant un ensemble d'appels asynchrones aux services de récupération de données dès que le client commence à acheter et à mettre en cache les données. Ainsi, lorsque vous devez appeler le service de règles, les données sont déjà là. Et continuer à être disponible pour d'autres services également pendant la session.
la source