Wiele do wielu skojarzeń w mikrousługach

13

Obecnie mam dwie mikrousługi. Zadzwonimy do nich Ai B.

Baza danych w ramach mikrousługi Azawiera następującą tabelę:

A
|-- users

Baza danych w ramach mikrousługi Bzawiera następującą tabelę:

B
|-- trackers

Wymagania mówią o tym usersi trackersmają relację wiele do wielu.

Nie jestem pewien, jak właściwie sobie z tym poradzić w architekturze mikrousług.

Widziałem, jak działa to na jeden z trzech sposobów:

  1. user_trackersTabeli dodaje microservice A. Działa to podobnie do tabeli łączenia zawierającej „klucze obce” do usersi trackers.
  2. ownersTabeli dodaje microservice B. Ta tabela działa podobnie do polimorficznej tabeli łączenia. Umożliwiłoby to dowolnej usłudze utworzenie powiązania z modułem śledzącym. Może to wyglądać mniej więcej tak: B |-- trackers |-- owners |-- owner_id |-- owner_type |-- tracker_id
  3. Przechowuje dokumentację usersi trackersna każdym microservice. Synchronizuj je z jakimś systemem pubsub.

Pierwotnie zamierzałem wybrać opcję 2, ponieważ podobało mi się, że zachowała granice transakcji. Mogę stworzyć moduł śledzący i powiązać go z czymś atomowo. Wydaje się jednak, że nie jest to możliwe w przypadku mikrousług B. Dlaczego mikrousługa powinna Bprzejmować się tym, że mikrousługa Achce utworzyć powiązanie?

Wydaje mi się, że prawdopodobnie jest tutaj dobry wzór, którego nie jestem świadomy. Czy którakolwiek z przedstawionych opcji ma sens? Czy istnieje inna opcja, która może mieć większy sens?

antonista
źródło

Odpowiedzi:

12

Przede wszystkim zacznę od opisu domeny. Nie wspomniałeś o co chodzi (zgaduję, ale to tylko przypuszczenie). Następnie spróbuję go rozłożyć za pomocą analizy łańcucha wartości lub mapowania zdolności biznesowych . I dopiero potem pomyślałem o wdrożeniu.

Biorąc pod uwagę twój problem, pierwszą rzeczą, która przychodzi mi do głowy, jest to, że źle określiłeś granice swoich usług, ponieważ potrzebują one nawzajem swoich danych. Nie chcesz skończyć z rozproszonym monolitem , prawda?

Po drugie, prawdopodobnie nie przeszedłeś wystarczająco dobrze przez domenę. Jaka koncepcja jest reprezentowana przez userstabelę? Czy to jest registered user, ze wszystkimi informacjami i zachowaniem wymaganymi do rejestracji? Czy na pewno jest to właściwa koncepcja komunikacji z trackers(czymkolwiek to jest)? Więc jeśli dobrze to rozumiem, twoja opcja 2 dotyczy właśnie tego: wprowadzenie ownerkoncepcji, która jest znacznie bliższa twojej domenie. Jeśli tak jest, jestem również za opcją 2.

Wydaje się jednak, że nie ma zastosowania w przypadku mikrousługi B. Dlaczego mikrousługa B powinna dbać o to, aby mikrousługa A chciała utworzyć powiązanie?

Chodzi o granice. Chyba chcesz tworzyć mikrousługi wokół bytów. Właśnie tam SOA zawiodła ze względu na architekturę usług warstwowych . Lepszym podejściem jest tworzenie usług reprezentujących niektóre funkcje biznesowe, aby obejmowały zarówno dane, jak i zachowanie. Z bardziej praktycznego punktu widzenia chodzi o tworzenie usług wokół procesów biznesowych lub przypadków użycia. Na przykład możesz mieć jedną usługę do rejestracji użytkownika. Zawiera dane użytkownika i zachowanie wymagane do zarejestrowania użytkownika. Tak więc koncepcja „ userformuje się” w sposób naturalny i należy ona tylko do usługi A. I to prowadzi mnie do następnego punktu: inny sposób myślenia o usługach jest ograniczony . Dobrą praktyką jest wyrównywanie usług i ograniczonych kontekstów.

Po zarejestrowaniu użytkownika UserCreatedzdarzenie może być emitowane. Twoja druga usługa jest chyba zainteresowana. Tak więc po otrzymaniu go można stworzyć zupełnie inny byt, powiedzmy, Ownerbyt (cokolwiek to jest). Jestem pewien, że istnieje wiele interesujących współpracy między nim a trackerpodmiotem - utrzymuj je w jednej usłudze.

Zachowaj szczególną ostrożność w przypadku opcji 3. Jeśli kopiujesz dane, funkcjonalność następuje. Daje to szczelne połączenie. I nie obejmuj terminem CQRS , nie chodzi o synchronizację danych między usługami za pośrednictwem zdarzeń.

Vadim Samokhin
źródło
Uwielbiam termin „monolit rozproszony”, ale sposób, w jaki został zdefiniowany w podanym linku, wydaje się nie mieć bezpośredniego związku z pytaniem tutaj. Sposób, w jaki myślę, że go używasz, jest związany ze sprzężeniem między usługami, a artykuł koncentruje się na zależnościach binarnych. Myślę, że sposób, w jaki korzystasz, jest lepszy, ale staram się znaleźć odniesienie, które jasno to określa.
JimmyJames,
Zawsze zawarłem usługi czatu w kategorii „rozproszonego monolitu”, co nie jest szeroko rozpowszechnione, powszechny sposób.
Vadim Samokhin,
6

Odpowiedź Zapadlo zawiera wiele dobrych informacji i uzasadnień. W tym miejscu dodam kilka praktycznych porad, które mogą pomóc w rozwiązaniu twoich problemów i porad w tej odpowiedzi.

Sposób, w jaki sformułowałeś swoje pytanie projektowe, dotyczy struktur bazy danych i jak dopasować do tego nowe wymagania dotyczące twoich struktur. Oznacza to, że budujesz projekt usługi na podstawie modelu danych. Na przykład nie widzę, w jaki sposób można uzyskać dostęp do relacji między użytkownikami a modułami śledzącymi lub z nich korzystać.

W projektowaniu usług najważniejsza jest konstrukcja interfejsu. W rzeczywistości wdrożenie jest prawie nieistotne w porównaniu, szczególnie w przypadku mikrousług. Powodem jest to, że po wdrożeniu usługi wszystkie zależności od usługi powinny istnieć tylko w interfejsie. Jeśli masz rację, powinieneś być w stanie całkowicie przepisać implementację bez żadnego konsumenta. I to jest główna zaleta autonomii. Nikt nie dba o to, jak go zbudowałeś. Potrzebują go tylko do działania w sposób, w jaki się komunikowałeś.

Zanim ktokolwiek zdoła ustalić, jak to wygląda w bazie danych lub gdzie tego chcesz, naprawdę musisz wyjaśnić, w jaki sposób te informacje będą wykorzystywane. Czy jest to coś, co zostanie ujawnione za pośrednictwem usługi, czy jest to jakiś rodzaj danych, które chcesz przemieścić w celu analizy?

Na marginesie, unikałbym zależności dwukierunkowych prawie za wszelką cenę. Jeśli masz zależności, naprawdę chcesz, aby tylko jedna strona wiedziała o drugiej. Gdy zależności są w obu kierunkach, usługi stają się zasadniczo jednostką atomową.

JimmyJames
źródło
0

Wiele z nich sprowadza się do samej domeny. Jeśli użytkownik z zerowymi modułami śledzącymi nie ma sensu, usługa użytkownika musi wiedzieć o modułach śledzących. Jeśli moduł śledzący musi mieć użytkownika, musi on wiedzieć o użytkownikach. Jeśli coś takiego jak posiadanie trackera z wieloma właścicielami lub możliwość przeniesienia trackera od jednego użytkownika do drugiego ma sens, być może ta informacja należy do innej usługi.

Znak
źródło
0

Pytanie: Dlaczego twoje dane są rozdzielane wzdłuż Datatables?

Zazwyczaj wybrałbym opcję 3: usługi są całkowicie oddzielne i mogą odpowiedzieć na pytania, na które mogą potrzebować odpowiedzieć. Ponadto są o wiele bardziej odporne. Ale bądź ostrożny, twoje usługi mogą się zsynchronizować, jeśli przegapią zdarzenia, ale można to rozwiązać dzięki ostatecznej spójności.

Możesz również rozważyć połączenie obu usług - jeśli oba nie są w stanie odpowiedzieć bez wiedzy o sobie, po prostu scalę je, ponieważ prawdopodobnie są one częścią jednej domeny.

Christian Sauer
źródło
Jest to część religii mikrousług, że każda usługa potrzebuje pełnej autonomii. Thomas Erl opisuje to jako jedną z zasad zorientowania na usługi w „Zasadach projektowania usług” ok. 2008.
JimmyJames,
@JimmyJames Jak ktoś, kto sam pisze architekturę ms: toczy się wiele dyskusji na temat tego, jak duże powinno być ms. W takim przypadku rozmiar może nawet nie mieć znaczenia, ponieważ usługi mogą być niepoprawnie rozdzielone - np. Nie tnij wzdłuż tabel, tnij wzdłuż domen biznesowych.
Christian Sauer,
Dobrze. Problem polega na tym, że obecnie istnieje duży kult ładunków wokół mikrousług. Widzę wielu ludzi wdrażających mikrousług, ponieważ to właśnie robią fajne dzieci, nie biorąc pod uwagę ani nie rozumiejąc kompromisów. Na przykład mam wrażenie, że wiele osób uważa, że ​​autonomia MS dotyczy technologii i „chmury”. Widzę to jako rozwiązanie problemu organizacyjnego. Wymiana dereferencji na wskaźnikach dla IO sieci jest niezwykle kosztowna. Nie możesz po prostu zastosować tego bezmyślnie i oczekiwać, że wszystko pójdzie dobrze.
JimmyJames,
@JimmyJames Myślę, że może to dotyczyć także technologii - szczególnie, gdy technologie certian są dobrze dostosowane do niektórych domen, ale nie do innych. Używamy C # i Python dla naszych MS. Niektóre z nich wynikają z problemów organizacyjnych („Programowałem c # od 20 lat, nie muszę uczyć się nowych, nietypowych języków!”). - ale także ze względu na charakter naszego systemu. Części do analizy danych najlepiej wykonywać w języku Python, a niektóre zadania związane z infrastrukturą i siecią najlepiej wykonywać w języku C #.
Christian Sauer,
Jasne, to całkiem uzasadniony powód, aby to zrobić. Problem, jaki widzę, polega na tym, że ludzie będą chcieli podzielić każdą usługę na osobny węzeł tylko dlatego, że „wykonujemy mikrousługi”, nawet jeśli wszystko jest napisane z tym samym kodem na tej samej platformie i istnieje mnóstwo zależności między usługami. W takim przypadku mikrousługi naprawdę nie mają wiele zalet, a dodałeś cały zestaw nowych problemów.
JimmyJames,