Wątek przeniesiony 2020-08-15 20:34 z Java przez Shalom.

Mikroserwisy zależności do innych mikroserwisów

0

Czy to normalne, że mikroserwisy mają dependencies do innych mikroserwisów tak że nie skompilujesz 1 mikroserwisu bez pozostałych?

6

Wtedy to chyba ciężko nazwać mikroserwisem :D
Generalnie mikroserwisy mają być od siebie niezależne. Komunikują się w określony sposób (zapewne REST).
Może chodzi ci o bibliotekę?

0

Wiedziałem, ech...

2

Pierwsza odpowiedź jaka się nasuwa to że to nie są mikroserwisy. Z drugiej jednak strony, jeśli wszystkie znajdują się w tym samym repo/projekcie (nie wiem co jest odpowiednikiem solucji z .Net) to jestem w stanie sobie wyobrazić że mają jakieś referencje do DTO czy też messages (jeśli mamy jakąś kolejkę/Service bus) zamiast korzystać z tych klas poprzez paczki (NuGet, Maven). Wtedy takie poszczególne serwisy mogą faktycznie nadal być oddzielnie deployowane i komunikować się sieciowo, a więc na poziomie architektury nadal być mikroserwisami. Na poziomie zarządzania kodem będą jednak w sprzeczności z pewnymi ideami mikroserwisów, między innymi niezależność rozwoju poszczególnych serwisów itp.

1
Aventus napisał(a):

Pierwsza odpowiedź jaka się nasuwa to że to nie są mikroserwisy. Z drugiej jednak strony, jeśli wszystkie znajdują się w tym samym repo/projekcie (nie wiem co jest odpowiednikiem solucji z .Net) to jestem w stanie sobie wyobrazić że mają jakieś referencje do DTO czy też messages (jeśli mamy jakąś kolejkę/Service bus) zamiast korzystać z tych kaps poprzez paczki (NuGet, Maven). Wtedy takie poszczególne serwisy mogą faktycznie nadal być oddzielnie deployowane i komunikować się sieciowo, a więc na poziomie architektury nadal być mikroserwisami. Na poziomie zarządzania kodem będą jednak w sprzeczności z pewnymi ideami mikroserwisów, między innymi niezależność rozwoju poszczególnych serwisów itp.

*Jeśli są w tych samych rękach, a cięcie wynika z wymogów runtime, tzn A będzie miała 50 instancji a B tylko 3. *
Taki argument sobie postawiłem przed oczy na własne pytanie "Są zbyt drobno pocięte. Dlaczego ich nie zmonolityzować?"
Się tylko pytam ....

@Julian_ Dlaczego rozdzieliłeś tak, jak rozdzieliłeś. Jak to nie jest tajemnicą, co konkretnie robią?

EDIT. Jak będą zależne na runtimie, tj A zawsze / często będzie robiła synchroniczny call do B, to się wydajnościowo źle skończy, i lepszy byłby mikro-monolit

4

To nie jest normalne, to jest rozproszony monolit, a jak bez tych innych serwisów nawet nie skompilujesz swojego serwisu to dodatkowo brzmi jak wielka micha spaghetti w repo / zarządzaniu zależnościami.

Jak to wygląda? Masz monorepo i mikroserwisy żyją sobie w jakichś podprojektach i podbierają od siebie klasy innych mikroserwisów, czy trzymasz artefakty w jakimś swoim Maven repo / Artifactory i kod mikroserwisu może wylądować jako zależność innego? Tak czy siak nawet bez wspominania o mikroserwisach brzmi to jak preludium do niezłego piekiełka.

0

to nie mój kod

2

@superdurszlak: rozproszony monolit to zbyt daleko idący wniosek przy tak małej ilości informacji. Wprowadza również w błąd czytelników sugerując że jak tylko masz kod wszystkich serwisów w jednym repo to masz rozproszony monolit. Nic z tych rzeczy.

Jak już wcześniej pisałem równie dobrze te zależności mogą polegać na referencjach do DTO czy też messages wymienianych między serwisami. W takim przypadku poszczególne serwisy nadal mogą mieć dobrze zamodelowane procesy biznesowe, wyznaczone granice odpowiedzialności, posiadać swoje własne źródła danych, ograniczać do niezbędnego minimum wzajemną komunikację itp. Oczywiście bardzo prawdopobne ze tak nie jest i że faktycznie jest tam jeden wielki bałagan. Piję jednak do tego że nie możesz jednoznacznie stwierdzić że ma się do czynienia z rozproszonym monolitem, bo zwyczajnie nie masz wystarczająco dużo informacji. Chyba że nie rozumiesz czym jest rozproszony monolit, o co Cię nie podejrzewam.

0

A co to za zależności?

1
Julian_ napisał(a):

Czy to normalne, że mikroserwisy mają dependencies do innych mikroserwisów tak że nie skompilujesz 1 mikroserwisu bez pozostałych?

Nie.

Z definicji opisu mikroserwisów wynika aby były niezależne, czyli kompilowały się, budowały bez żadnych przeszkód. Jednak pracowałem w projekcie, gdzie jeden mikroserwis w zbudowaniu go, był zależny od innego mikroserwisu, dochodziło wtedy wtedy to sytuacji że programiści przez tydzień nic nie robili, albo Lead Developer kazał robić jakieś śmieszne "stuby" i wszyscy czekali aż ten jeden Developer naprawi zepsuty mikroserwis. To był patologiczny projekt, ale chcę pokazać do czego takie coś może prowadzić.

4

Gdyby to było monorepo to mogło by wyglądać tak:

serviceA
serviceA-api
serviceB
serviceB-api
itd.

czyli każdy serwis ma paczkę kliencką i inne serwisy mogą do paczki klienckiej api się odwoływać. Klasy z api korzystają pod spodem z jakiegoś mechanizmu który wspiera wersjonowanie API itp. Do tego są feature-flagi tak żeby nie używać nowego api jak jeszcze nie jest dostępne "na dwóch końcach". No ale to monorepo które jest poza zasięgiem większości firm.

Opcja 2 to repo per serwis, serwisy wystawiają api przez swagger/graphgl/grpc, klientów się generuje lub pisze deklaratywnie. Oczywiście trzeba dbać o wersjonowanie i pilnować kiedy dana wersja api jest deprecate'owana. Niektórzy używają consumer-driven contracts tak żeby mieć pewność że api używane przez klienta jest dostępne na danym serwisie.

Sporo osób kładzie na tym lachę i robi po swojemu czyli łączy opcje 1 i 2: publikuje api jako paczki Nuget/Maven z typami. Jeżeli dba się o to że api są zawsze kompatybilne wstecz to i z tym podejściem można daleko zajechać.

W każdej z tych 3 opcji mamy wyraźne rozdzielenie między api serwisu a jego implementację. Jeżeli w twoim przypadku są zależności pomiędzy implementacjami serwisów to bardzo niedobrze. Coś jest wyraźnie nie tak.

1

To nie są mikroserwisy, ponieważ nie ma niezależności developmentu i wdrożeń.

2

To zależy o jakich zależnościach mówisz. Zależność do clienta (czyli modułu który ma jakieś DTO + np. http clienta z informacjami o endpointach) to normalna rzecz. Dzięki temu ktoś kto używa serwisu w ogóle nie musi wiedzieć jakie są adres endpointów albo jak konwertować odpowiedzi z jsona na DTO - o to dba autor serwisu publikując clienta do artifact repository.

0

Na przykładzie "allegro dla biedaków", jak zrobiłbym serwisy, które się nie komunikują przez content providery i takie tam cuda tyko kulturalnie przez bazę danych lub kafkę to można taką architekturę uznać za mikroserwisową?
Serwisy współdzielą tylko model (publiczne dto).

title

3

@Julian_ xD Tak sie pisało 40 lat temu i to jest co najwyżej "rozproszony monolit". Przez tą bazę w środku wszystko jest ze wszystkim powiązane.

2

1

@Shalom:
@Julian_ użył słowa serwisy, a nie mikroserwisy. Dobry adwokat by na tej podstawie go obronił.

@Julian_ zakładam, że masz świadomość, serwisy (środek projektowania obiektowego WEWNĄTRZ aplikacji) a mikroserwisy (temat tego wątku), to mocno różniące się słowa, choć 60% literek mają takie same.

0

to nie wiem.

A kupiłem specjalnie książkę "Spring microservices in action" żeby się dowiedzieć, jestem po 3 rozdziałach i dalej nie wiem.

0

a teraz?

title

1

@Julian_ zadaj sobie takie pytania:

  • Czy możesz skalować serwisy niezależnie od siebie? Nie, bo masz bottleneck na bazie.
  • Czy możesz wymienić któryś serwis zupełnie, bez ingerowania w inne? Nie, bo inne serwisy zalezą od tego, ze piszesz coś do jakichś tabel w bazie.
  • Czy można developować te serwisy niezależnie od siebie? Nie, bo są powiązane przez to w jaki sposób działają (że np. piszą coś gdzieś do bazy) a nie przez przejawiane zachowanie.
4

Julian, spójrz na to - układ na podstawie danych IDzD:

screenshot-20200815180158.png

A teraz porównaj z diagramami które rysujesz:

screenshot-20200815181253.png

Widzisz na czym polega różnica?

Żaden serwis nie dłubie w bebechach drugiego, nie widzi jego bazy ani nic - to, co i gdzie trzyma każdy serwis to jego prywatna sprawa. Jak chce o czymś poinformować drugi serwis, to nie dopisuje mu niczego do bazy, tylko powiedzmy wysyła event. Nie ma znaczenia, że pierwszy ma jakąś instancję Aurory 24xlarge, a drugi sobie używa Redisa, a trzeci to nawet bazy nie ma.

Zależności między nimi sprowadzają się do tego, że jest jakiś kontrakt na zasadzie "A i B komunikują się ze sobą tak i śmak" - czy to przez jakieś message, czy eventy, czy przez dowolny inny protokół komunikacji jaki tam sobie developerzy uzgodnią.

1

różnica polega na tym, że jak jeden serwis chce coś od drugiego to nie odpytuje bazy tego drugiego tylko odpytuje jego serwis i ten seriws odpytuje dla niego swoją bazę -

Zaraz, jeśli dobre rozumiem to ten "negocjator" ma wpólną bazę danych, więc de facto po prostu dokładasz sobie tylko narzut wykaniania HTTP/kolejki etc. a i tak efekt jest ten sam.
Każda aplikacja powinna mieć swoją warstwę persystencji niezależną od innych, i to wcale nie musi być baza danych w klasycznym znaczeniu, może to być ram system plików, NoSQL, SQL, jakaś usługa inna itd

2

@Julian_:

różnica polega na tym, że jak jeden serwis chce coś od drugiego to nie odpytuje bazy tego drugiego tylko odpytuje jego serwis i ten seriws odpytuje dla niego swoją bazę

No tak i nie. Serwisy mogą, ale nie muszą komunikować się synchronicznie - zresztą nadmiar synchronicznej komunikacji może mieć przykre konsekwencje pod postacią lawiny żądań i systemu, który wieczorem będzie odpowiadał na requesty sprzed południa. Równie dobrze to serwis będący ownerem danych może przy zapisie wysyłać w świat informację, że coś się wydarzyło - i wtedy nie ma potrzeby odpytywania ani serwisu, ani tym bardziej jego bazy.

Zresztą, dobijając się do danych poprzez serwis przynajmniej nie wysadzisz w powietrze drugiego, jeśli kiedyś zmieni się schemat bazy. Inna sprawa, że jeśli inne serwisy czytają/piszą do bazy serwisu-właściciela, to nie może w żadnej sposób wyegzekwować choćby kontroli dostępu do danych albo walidacji, czyli dość podstawowych rzeczy.

0

Zresztą, dobijając się do danych poprzez serwis przynajmniej nie wysadzisz w powietrze drugiego, jeśli kiedyś zmieni się schemat bazy.

A co z deserializacją tego co se odbierają mikroserwisy? Każdy mikroserwis ma swój deserializator otrzymywanych wiadomości? ("Message Event Receiver") oraz swój model danych dla mikroserwisów od których dostaje odp?

.

Przykładowo:

client-microservice wysyła żądanie do finance-microservice o InvoiceDoc.

finance-microserice przygotowuje InvoiceDoc, mapuje do InvoiceDocDto, serializuje do jsona i wysyła.

client-microservice odbiera jsona, deserializuje go do financeMicroserviceInvoiceDocDto i mapuje na financeMicroserviceInvoiceDoc.

Skąd client-microservice wie jak to deserializowac i mapowac.

Jak w finance-microservice w klasie InvoiceDoc zmienię String productName na Product product to client-microservice (message handler receiver) nie będzie wymagał zmiany?

1

@Julian_ pisałem wyżej, serwisy wystawiają sobie nawzwajem clienty a DTO są ich częścią. Więc twój dupa-microservice odbiera obiekt InvoiceDocDto za pomocą FinanceClient i obie te klasy przychodzą z jakiegoś artefaktu finance-client i co sobie z nim potem robi to jego sprawa.
Jak finance-microservice coś sobie wewnętrznie zmieni to jego sprawa, o ile interfejs nie ulega zmianie albo co najwyżej jest przyrostowy. Ale jakby co to oczywiscie ten serwis publikuje nowego klienta, którego dupa-microservice powinien sobie wciągnąć.
Często w publicznych serwisach utrzymuje się kilka wersji API, właśnie dlatego żeby zachować kompatybilność.

Może też tak być że nie ma clienta i wtedy musisz go sobie sam napisać. Ot uderzasz do serwisu, patrzysz na jsona i piszesz.

0

różnica polega na tym, że jak jeden serwis chce coś od drugiego to nie odpytuje bazy tego drugiego tylko odpytuje jego serwis i ten seriws odpytuje dla niego swoją bazę

Dodatkowy plus takiego podejścia: można zrobić cache w jednym serwisie, a nie na wszystkich, które by korzystały z tej bazy.

0
Shalom napisał(a):

Może też tak być że nie ma clienta i wtedy musisz go sobie sam napisać. Ot uderzasz do serwisu, patrzysz na jsona i piszesz.

No i oprócz tego jest też trzecia opcja, czyli napisanie / wygenerowanie tego klienta na podstawie definicji API, o ile są dostępne - no ale gdyby dwa zespoły w obrębie jednej firmy ich sobie nie udostępniły, to byłaby niezła patologia :D

Choć tak szczerze, to do takich generatorów kodu jestem nastawiony mocno sceptycznie - te, które widziałem były w stanie jako-tako ogarnąć DTO i interfejsy na podstawie YAMLa / JSONa, ale jak próbowały dogenerować resztę to wychodziła sieczka. Podobno niektóre firmy mają jakieś swoje rozwiązania, które sprawdzają się naprawdę fajnie, ale nie uwierzę póki nie zobaczę :]

3

@Julian_: przeczytaj sobie książkę Sama Newmana o mikroserwisach + Evolutionary architecture Neala Forda, a nie jakieś Springowe dziadostwa. Następnie przeczytaj jeszcze raz i zwróć uwagę na problem współdzielenia czegokolwiek w takiej architekturze.

1

Po pierwsze, nie rób mikroserwisow, no chyba, że jesteś googlem lub netflixem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1