web-dev-qa-db-fra.com

Comment adapter un moteur de règles dans une architecture de microservices quand il nécessite beaucoup de données d'entrée?

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 pouvoir 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 a dû ê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, il est principalement utilisé 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 l'extraction de toutes les données;
  • 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 plutôt lentes à récupérer (10 secondes ou plus), nous avons donc implémenté la prélecture dans shopping-cart de telle sorte que les données sont plus susceptibles d'être présentes avant d'appeler le moteur de règles et de conserver une expérience utilisateur acceptable.

Quelques idées

  1. Laissez le moteur de règles récupérer les données dont il a besoin. Cela ajouterait encore plus de complexité, violant le principe de responsabilité unique ( encore plus… );
  2. Implémentez un proxy μs avant le moteur de règles pour récupérer les données;
  3. 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 à la fois (interrogation composite).
12
Didier L

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. Vous avez:

  • Un grand monolithe (le moteur de règles)
  • Une grande quantité de données non modularisées qui sont envoyées en masse
  • Il est difficile d'obtenir des données vers et depuis le moteur de règles
  • Vous ne pouvez pas supprimer le moteur de règles

D'accord, 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.

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;

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 pourrait utiliser un outil existant ( recherchez les 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 système unique 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.

les demandes adressées au moteur de règles sont complexes;

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. Mon devinez est que vous n'avez pas de plan d'API défini (comme ci-dessus) et avez commencé à écrire REST appelle 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 société d'abord à avoir jamais implémenté 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 considérablement les frais généraux de votre système juste pour obtenir une "architecture de microservices", vous devez consacrer plus de temps à la planification de cette opération.

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.

Nous devons également nous assurer que cela ne devienne pas un goulot d'étranglement - par exemple, certaines données sont plutôt lentes à récupérer (10 s ou même plus)

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 shopping des données de portail autour? 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.

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 microservices, 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.

8
enderland

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.

1
Soren L. Hansen

Dans ma pensée simple, je suppose que cela aidera à pré-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.

0
Ashok

L'agrégation des données nécessaires à la décision doit être effectuée en dehors du moteur de règles. En effet, il est préférable de les concevoir comme des services apatrides lorsque cela est 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 faisant face au service de décision, par les appelants ou par un processus métier.

Pour des raisons pratiques de mise en œuvre, je mentionnerai que IBM Operational Decision Manager est commence à documenter et prend déjà en charge l'utilisation du produit dans les conteneurs Docker . Je suis sûr que d'autres produits fournissent également ce support et qu'il deviendra courant.

0
David Williams