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


12

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-cartmicroservice 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-carttelle 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

  1. 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… );
  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 en même temps (interrogation composite).

Permettez-moi de résumer cela (avec des questions): vous avez plusieurs microservices mis en œuvre pour une boutique. L'un d'eux est un panier d'achat . Incorporé dans le panier est un moteur de règles (soit homebrew ou un produit), non? Lorsqu'un utilisateur ajoute un article au panier, le moteur de règles entre en jeu dans le cadre de la logique métier et modifie le panier d'une manière ou d'une autre (par exemple, remise ou produits groupés), n'est-ce pas? Maintenant, un autre microservice veut également utiliser des règles qui peuvent être basées sur des données d'entrée similaires, non? Et les données d'entrée sont fournies par d'autres microservices, non? Pourquoi la récupération des données est-elle si complexe?
Andy

3
Votre meilleur pari pour éviter ces problèmes est de vous débarrasser du moteur de règles.
whatsisname

@Andy Le moteur de règles est un microservice distinct. Son API est un peu adaptée 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.
Didier L

@whatsisname Je ne suis pas non plus un grand fan d'avoir un moteur de règles en général, mais à l'heure actuelle, nous devons y faire face et de toute façon, et l'entreprise change sa configuration au jour le jour. Même si nous nous en débarrassions, nous aurions encore besoin de certains composants configurables pour faire les mêmes choses, nécessitant les mêmes données d'entrée ... Ce serait toujours un moteur de règles, juste avec un autre nom, et nous ferions toujours face aux mêmes problèmes.
Didier L

Réponses:


8

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:

  • 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 depuis et vers le moteur de règles
  • Vous ne pouvez pas supprimer le moteur de règles

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.

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

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

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)

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.


Merci pour votre réponse, @enderland. En effet, l'architecture des microservices est encore relativement nouvelle pour nous, d'où cette question. Ce moteur de règles a évolué un peu de manière organique pour nous conduire ici, nous avons donc maintenant besoin d'un itinéraire pour y remédier. Il est (heureusement) complètement sans état, d'où la quantité de données qu'il prend en entrée. Et c'est ce que nous aimerions aborder en premier pour en faire un composant réutilisable. Mais comment réduire la quantité de données d'entrée sans réduire le nombre de prédicats disponibles? Je suppose que nous avons besoin d'une API capable de récupérer les données par elle-même, mais comment les architecturer correctement?
Didier L

Concernant les problèmes de performances, ceux-ci proviennent de microservices qui appellent en fait des services JMS et SOAP lents implémentés par des back-end. Ils ont leurs propres bases de données, mais les performances ne sont pas vraiment leur premier objectif (tant qu'il gère la charge). Et ils sont trop nombreux pour envisager de répliquer leurs données et de les maintenir (pour certains, nous le faisons cependant). Le mieux que nous puissions faire est donc la mise en cache et la prélecture.
Didier L

Donc, lorsque vous mentionnez « quelques moteurs de règles », je comprends que vous voulez dire des moteurs de règles spécialisés qui n'évaluent que les prédicats pour un type d'entrée, n'est-ce pas? Suggérez-vous qu'ils récupèrent les données dont ils ont besoin ou devraient-ils être récupérés à l'avance? Nous aurions également besoin d'un composant pour orchestrer la combinaison de prédicats, non? Et faites attention à ne pas ajouter trop de surcharge réseau en raison de cette orchestration.
Didier L

1

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.


0

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.


0

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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.