Jak dopasować silnik reguł do architektury mikrousług, gdy wymaga dużo danych wejściowych?


12

Obecna sytuacja

Wdrażamy (i obecnie utrzymujemy) aplikację internetową do zakupów online w architekturze mikrousług.

Jednym z wymagań jest to, że firma musi być w stanie stosować zasady dotyczące tego, co nasi klienci dodają do koszyka, w celu dostosowania ich doświadczenia i ostatecznego zamówienia. Z pewnością trzeba było wprowadzić silnik reguł biznesowych i wdrożyliśmy do tego specyficzną „mikrousługę” (jeśli nadal moglibyśmy to tak nazwać).

W ciągu roku ten silnik reguł stawał się coraz bardziej złożony, wymagając coraz większej ilości danych (np. Zawartości koszyka, ale także informacji o użytkowniku, jego roli, istniejących usługach, niektórych danych rozliczeniowych itp.), Aby móc obliczyć te reguły.

Na razie nasza shopping-cartmikrousługa zbiera wszystkie te dane z innych mikrousług. Mimo że część tych danych jest używana przez shopping-cartwiększość czasu, są one głównie wykorzystywane do zasilania silnika reguł.

Nowe wymagania

Teraz pojawia się potrzeba, aby inne aplikacje / mikrousługi ponownie wykorzystały silnik reguł do podobnych wymagań. W obecnej sytuacji musieliby zatem przesyłać ten sam rodzaj danych, wywoływać te same mikrousługi i budować (prawie) te same zasoby, aby móc wywołać silnik reguł.

Kontynuując, napotkamy kilka problemów:

  • każdy (wywołujący silnik reguł) musi ponownie wdrożyć pobieranie danych, nawet jeśli nie potrzebuje ich dla siebie;
  • żądania do silnika reguł są złożone;
  • kontynuując w tym kierunku, będziemy musieli przetransportować te dane w całej sieci dla wielu żądań (pomyśl o μs A wywołującej μs B wywołującej silnik reguł, ale A ma już niektóre dane, których potrzebuje silnik reguł);
  • shopping-cart stał się ogromny z powodu pobierania wszystkich danych;
  • Prawdopodobnie zapominam o wielu…

Co możemy zrobić, aby uniknąć tych problemów?

Idealnie byłoby uniknąć dodawania większej złożoności do silnika reguł. Musimy również upewnić się, że nie stanie się ono wąskim gardłem - na przykład niektóre dane są dość wolno pobierane (10 s lub nawet więcej), więc wdrożyliśmy wstępne pobieranie, shopping-carttak aby dane były bardziej prawdopodobne przed wywołaniem reguł silnik i zadbaj o komfort użytkowania.

Jakieś pomysły

  1. Pozwól, aby silnik reguł pobierał potrzebne dane. Zwiększyłoby to jeszcze bardziej złożoność, naruszając zasadę pojedynczej odpowiedzialności ( nawet więcej… );
  2. Zaimplementuj serwer proxy μs przed mechanizmem reguł, aby pobrać dane;
  3. Zaimplementuj „moduł pobierania danych” μs, który wywołuje silnik reguł, aby pobrać wszystkie potrzebne dane naraz (zapytanie złożone).

Pozwól, że podsumuję to (pytaniami): masz kilka mikrousług dla sklepu. Jednym z nich jest wózek na zakupy . W koszyku jest wbudowany silnik reguł (homebrew lub jakiś produkt), prawda? Gdy użytkownik dodaje element do koszyka, silnik reguł uruchamia się w ramach logiki biznesowej i jakoś modyfikuje koszyk (np. Produkty rabatowe lub pakietowe), prawda? Teraz inna mikrousługa chce również stosować reguły, które mogą być oparte na podobnych danych wejściowych, prawda? A dane wejściowe są dostarczane przez inne mikrousługi, prawda? Dlaczego pobieranie danych jest tak skomplikowane?
Andy

3
Najlepszym sposobem na uniknięcie tych problemów jest pozbycie się silnika reguł.
whatsisname

@Andy Silnik reguł jest osobną mikrousługą. Jego interfejs API jest nieco dostosowany shopping-cart, ale możemy dość łatwo dostosować go do potrzeb innych mikrousług (nadal są one związane z użytkownikami, produktami i zamówieniami). Jak widzimy, będą potrzebować tych samych danych wejściowych, zwłaszcza, że ​​firma jest w stanie wybrać predykaty do zastosowania. Wszystkie dane są dostarczane przez inne mikrousługi z wyjątkiem samej zawartości koszyka. Pobieranie danych nie jest skomplikowane per se , ale staje się skomplikowana, kiedy trzeba zadzwonić ~ 10 innych microservices i utrzymać strukturę oczekiwanego przez silnik reguł.
Didier L

@whatsisname Nie jestem wielkim fanem posiadania silnika reguł w ogóle, ale obecnie musimy sobie z tym poradzić i tak, a firma zmienia swoją konfigurację z dnia na dzień. Nawet gdybyśmy się go pozbyli, nadal potrzebowalibyśmy konfigurowalnego komponentu, aby wykonać te same czynności, wymagając tych samych danych wejściowych ... Byłby to nadal silnik reguł, tylko z inną nazwą, i nadal mielibyśmy te same problemy.
Didier L

Odpowiedzi:


8

Cofnijmy się o sekundę i oceńmy nasze początkowe miejsce, zanim wypiszemy tę odpowiedź, która prawdopodobnie będzie nowością. Ty masz:

  • Duży monolit (silnik reguł)
  • Duża ilość niemodularnych danych, które są wysyłane masowo
  • Trudno jest uzyskać dane do iz silnika reguł
  • Nie można usunąć silnika reguł

Ok, to nie jest tak świetne dla mikrousług. Natychmiast rażącym problemem jest to, że wydajecie się, że nie rozumiecie, czym są mikrousługi.

każdy (wywołujący silnik reguł) musi ponownie wdrożyć pobieranie danych, nawet jeśli nie potrzebuje ich dla siebie;

Musisz zdefiniować jakiś interfejs API lub metodę komunikacji, z której będą korzystać Twoje mikrousługi i aby były one powszechne. Może to być biblioteka, którą wszystkie mogą importować. Być może definiuje protokół wiadomości. Może używać istniejącego narzędzia ( poszukaj magistrali komunikatów mikrousług jako dobrego miejsca początkowego).

Kwestia komunikacji między służbami nie jest sama w sobie „rozwiązanym” problemem, ale w tym momencie nie jest też problemem „rzuć własnym”. Wiele istniejących narzędzi i strategii może ułatwić Ci życie.

Niezależnie od tego, co robisz, wybierz jeden system i spróbuj dostosować interfejsy API komunikacji, aby z niego korzystać. Bez określonego sposobu interakcji między usługami będziesz miał wszystkie wady mikrousług i usług monolitycznych i żadnej z nich.

Z tego wynika większość problemów.

żądania do silnika reguł są złożone;

Uczyń je mniej złożonymi.

Znajdź sposoby, aby uczynić je mniej złożonymi. Poważnie. Wspólne modele danych, podziel silnik pojedynczych reguł na mniejsze lub coś takiego. Spraw, aby silnik reguł działał lepiej. Nie bierz „zakleszczenia wszystkiego w zapytaniu i po prostu komplikuj je” - poważnie przyjrzyj się temu, co robisz i dlaczego.

Zdefiniuj protokół dla swoich danych. Moje przypuszczenie to macie nie określono planu API (zgodnie z powyższym) i zaczęli pisać REST wzywa ad hoc w razie potrzeby. To staje się coraz bardziej skomplikowane, ponieważ teraz musisz utrzymywać każdą mikrousługę za każdym razem, gdy coś zostanie zaktualizowane.

Co więcej, nie jesteś pierwszą firmą, która wdrożyła narzędzie do zakupów online. Idź zbadać inne firmy.

Co teraz...

Następnie co najmniej trzy najważniejsze problemy.

Kolejnym problemem jest to pytanie dotyczące silnika reguł. Mam nadzieję, że jest to dość bezpaństwowiec, dzięki czemu można go skalować. Jeśli tak, to chociaż nieoptymalne, przynajmniej nie umrzesz w blasku chwały ani nie zbudujesz szalonych obejść.

Chcesz, aby silnik reguł był bezstanowy. Ustaw tak, aby przetwarzał tylko dane. Jeśli okaże się, że jest to wąskie gardło, zrób to, abyś mógł uruchomić kilka serwerów proxy / modułu równoważenia obciążenia. Nie idealny, ale wciąż wykonalny.

Poświęć trochę czasu na zastanowienie się, czy któraś z twoich mikrousług naprawdę powinna zostać wprowadzona do silnika reguł. Jeśli tak znacznie zwiększasz obciążenie systemu, aby osiągnąć „architekturę mikrousług”, musisz poświęcić więcej czasu na planowanie tego.

Alternatywnie, czy silnik reguł można podzielić na części? Możesz zyskać, robiąc części swoich usług specyficznych dla silnika reguł.

Musimy również upewnić się, że nie stanie się ono wąskim gardłem - na przykład niektóre dane są dość wolno pobierane (10 s lub więcej)

Zakładając, że problem występuje po rozwiązaniu powyższych problemów, musisz poważnie zbadać, dlaczego tak się dzieje. Masz koszmar, który się rozwija, ale zamiast dowiedzieć się, dlaczego (10 sekund? Na przesłanie danych z portalu zakupowego ? Zadzwoń do mnie cynicznie, ale wydaje się to nieco absurdalne), wydajesz się raczej łatać objawy, niż patrzeć na problem powodujący objawy w pierwsze miejsce.

Używałeś wyrażenia „pobieranie danych” w kółko. Czy te dane są w bazie danych? Jeśli nie, zastanów się nad tym - jeśli spędzasz tyle czasu na „ręcznym” pobieraniu danych, wydaje się, że dobrym pomysłem byłoby użycie prawdziwej bazy danych.

Być może będziesz mógł mieć projekt z bazą danych dla pobieranych danych (w zależności od tego, co to jest, wspominałeś o tym wiele razy), kilkoma silnikami reguł i klientami.

Ostatnia uwaga: upewnij się, że używasz odpowiedniej wersji swoich interfejsów API i usług. Drobne wydanie nie powinno naruszać kompatybilności wstecznej. Jeśli uwolnisz wszystkie swoje usługi w tym samym czasie, aby działały, nie masz architektury mikrousług, masz rozproszoną architekturę monolityczną.

I ostatecznie, mikrousługi nie są rozwiązaniem uniwersalnym. Proszę, ze względu na wszystko, co święte, nie róbcie tego tylko dlatego, że jest to nowa modna rzecz.


Dziękuję za odpowiedź, @enderland. Rzeczywiście architektura mikrousług jest dla nas wciąż stosunkowo nowa, stąd to pytanie. Ten silnik reguł ewoluował nieco organicznie, aby nas tu doprowadzić, dlatego potrzebujemy wskazówek, jak to naprawić. Jest (na szczęście) całkowicie bezstanowy, stąd ilość danych pobieranych jako dane wejściowe. I tym właśnie chcielibyśmy się zająć, aby był to element wielokrotnego użytku. Ale jak zmniejszyć ilość danych wejściowych bez zmniejszania liczby dostępnych predykatów? Wydaje mi się, że potrzebujemy interfejsu API, który byłby w stanie pobrać dane samodzielnie, ale jak poprawnie je skonstruować?
Didier L

Jeśli chodzi o problemy z wydajnością, pochodzą one z mikrousług, które faktycznie wywołują wolne usługi JMS i SOAP zaimplementowane przez back-endy. Mają własne bazy danych, ale wydajność nie jest tak naprawdę ich pierwszym celem (pod warunkiem, że obsługuje obciążenie). I jest ich zbyt wielu, aby rozważyć replikację danych i utrzymanie ich (jednak niektórym to robimy). Najlepsze, co możemy zrobić, to buforowanie i pobieranie wstępne.
Didier L,

Kiedy więc wspominasz o „ kilku silnikach reguł ”, rozumiem, że masz na myśli wyspecjalizowane silniki reguł, które oceniają predykaty tylko dla 1 rodzaju danych wejściowych, prawda? Czy zasugerowałbyś, aby pobrali potrzebne dane, czy też powinny zostać pobrane z góry? Potrzebowalibyśmy również jakiegoś komponentu, aby zaaranżować kombinację predykatów, prawda? I pamiętaj, aby nie dodawać zbyt dużego obciążenia sieci z powodu tej aranżacji.
Didier L

1

Biorąc pod uwagę ilość informacji przedstawionych na temat silnika reguł oraz jego danych wejściowych i wyjściowych, myślę, że twoja sugestia nie. 2 jest na dobrej drodze.

Obecni konsumenci silnika reguł mogliby zlecić proces zbierania wymaganych informacji komponentowi bardziej specjalnego przeznaczenia.

Przykład: obecnie używasz silnika reguł do obliczania rabatów, które należy zastosować w odniesieniu do zawartości koszyka. Uwzględniają wcześniejsze zakupy, położenie geograficzne i aktualne oferty.

Nowym wymogiem jest wykorzystanie wielu tych samych informacji do wysyłania pocztą elektroniczną ofert do poprzednich klientów w oparciu o nadchodzące promocje i poprzednie zakupy. Uwzględniają poprzednie zakupy, aktualne i nadchodzące oferty.

Miałem do tego dwie osobne usługi. Każdy z nich polegałby na serwisie silnika reguł w zakresie niektórych ciężkich zadań podnoszenia. Każdy z nich zbierałby wymagane dane potrzebne do przesłania żądania do silnika reguł.

Mechanizm reguł po prostu stosuje reguły, konsumenci nie muszą się martwić o to, jakie dokładnie dane potrzebuje silnik reguł dla konkretnego kontekstu, a te nowe usługi pośredniczące robią tylko jedną rzecz: Zbierz kontekst i przekaż żądanie silnikowi reguł i zwraca odpowiedź niezmodyfikowaną.


0

Agregowanie danych wymaganych do podjęcia decyzji powinno odbywać się poza silnikiem reguł. Wynika to z tego, że najlepiej je zaprojektować jako usługi bezstanowe, o ile to możliwe. Pobieranie danych musi koniecznie obejmować przetwarzanie asynchroniczne i przechowywanie stanu. Nie ma większego znaczenia, czy pobieranie odbywa się przez serwer proxy na czele usługi decyzyjnej, przez osoby dzwoniące czy przez proces biznesowy.

Jako praktyczną kwestię do wdrożenia wspomnę, że IBM Operational Decision Manager zaczyna dokumentować i już obsługuje użycie produktu w kontenerach dokerów . Jestem pewien, że inne produkty również zapewniają to wsparcie i że zostanie ono włączone do głównego nurtu.


0

Wydaje mi się, że w moim prostym podejściu pomoże to wstępnie pobrać wszystkie wymagane dane, wykonując zestaw asynchronicznych wywołań do usług wyszukiwania danych, gdy tylko klient zacznie kupować i buforować dane. Kiedy więc musisz zadzwonić do serwisu reguł, dane już tam są. I nadal będą dostępne dla innych usług podczas sesji.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.