Parent dla mikroserwisów

0

Cześć. Załóżmy, że mamy dość spory system składający się z 50+ mikroserwisów napisanych w Javie opierających się na Spring Boot.
Czy w takim wypadku powinniśmy dziedziczyć każdy mikroserwis ze spring-boot-starter-parent czy też powinniśmy zrobić osobny projekt "patentowy", który dziedziczy z tego Spring, ale wnosi jakieś wspólne funkcjonalności, które są share'owane między mikroserwisami?

Dlaczego zastanawiam się nad drugą opcją.. bardzo dużo rzeczy dla tych mikroserwisów jest wspólna, jak np te same DTO, auto konfiguracje cache, security, klienty do różnych usług itp. Ponad to dzięki takiemu customowemu patentowi możemy centralnie zarządzać wersjami różnych bibliotek jak np sterownika psql czy czego tam używamy.

Z drugiej strony mikroserwisy powinny być niezależne, a taki wspólny customowy Parent je spina.

Reasumując. Czy taki Parent to dobry pomysł? Ewentualnie gdzie przebiega granica i które elementy powinny być po prostu wyniesione do osobnych, małych bibliotek?

Pozdrawiam

5

Proponuję posiadanie jak najmniej wspólnych zależności. Obecnie zakładasz wspólną wersję springa dla wszystkich mikroserwisów. Dlaczego? Jeżeli projekt jest wystarczająco stary, używasz spring boota 2, i nagle wychodzi wersja 3. Podbicie major wersji to nie jest hop siup, jeden mikroserwis może być malutki, a drugi dużo większy, i podbicie wersji może zająć dość długo. Podbijając coś w parencie masz zatem dużą szansę na breaking changes w child projektach. Nie podbijając, blokujesz gotowe mikroserwisy. Niech każdy mikroserwis zarządza sam sobą.

Do DTOsów często stosuje się jeszcze osobne repozytorium, które może być publikowane jako osobny artefakt, i importowany przez zainteresowane serwisy. Security tak samo, osobna biblioteka.

Nie widzę potrzeby centralnego sterowania wersją psql - każdy mikroserwis i tak powinien mieć swoją osobną bazę danych. Niech jeden korzysta z Postgresa 9.6, a drugi z 9.7 - w czym problem? Trzeci może w ogóle nie potrzebować relacyjnego SQLa, a np MongoDB.

Im mniej zależności masz, tym lepiej. Polecam używanie renovate bota, który periodycznie wrzuca pull requesty z podbijaniem wersji bibliotek do najnowszych - to jest jeden z łatwiejszych patternów na zapewnienie "świeżości" zależności w projekcie. A każdy mikroserwis/zespół już niech zarządza swoimi zależnościami osobno.

6

Czyli macie mikroserwisy i chcecie z tego zrobic rozproszony monolit. Kciuk w gore =)

0

Po prostu jakiś wydzielony projekt core z konfiguracjami oraz wydzielony projekt base-api z DTOsami i każdy z projektów (jeśli potrzebuje) ma zależność do tych projektów.

0

Kojarzę, że allegro stosuje takie podejście współdzielenia pewnych rzeczy między usługami z możliwością ich zastąpienia jeżeli zespół tak zadecyduje ale niestety nie mam linku do żadnego artykułu bo słyszałem o tym w ich podcaście ale myślę, że to dobry punkt zaczepienia by podrążyć a może nawet zagadać do jakiegoś tl'a na linkedin i podpytać o szczególy.

0

Jest ok, jeśli zaprojektujesz wszystko tak, że deploy jednego serwisu nie wymaga koordynacji pomiędzy resztą serwisów. Niezależność nie musi być na poziomie kodu, ale bez niezależnego kodu jest dużo prościej zaliczyć wtopę

Tak czy owak taki super lib, który zawiera wszystko to zły pomysł. Ciężko wersjonować takie coś np. wydasz v2 biblioteki do obsługi bazy danych. Jeśli to wszystko jest w jednej bibliotece to nie jesteś w stanie przemigrować tylko część serwisów. Dużo lepiej jest zrobić osobną bibliotekę do każdego odzielnnego kontekstu

1
Bambo napisał(a):

Cześć. Załóżmy, że mamy dość spory system składający się z 50+ mikroserwisów napisanych w Javie opierających się na Spring Boot.
Czy w takim wypadku powinniśmy dziedziczyć każdy mikroserwis ze spring-boot-starter-parent czy też powinniśmy zrobić osobny projekt "patentowy", który dziedziczy z tego Spring, ale wnosi jakieś wspólne funkcjonalności, które są share'owane między mikroserwisami?

Dlaczego zastanawiam się nad drugą opcją.. bardzo dużo rzeczy dla tych mikroserwisów jest wspólna, jak np te same DTO, auto konfiguracje cache, security, klienty do różnych usług itp. Ponad to dzięki takiemu customowemu patentowi możemy centralnie zarządzać wersjami różnych bibliotek jak np sterownika psql czy czego tam używamy.

Z drugiej strony mikroserwisy powinny być niezależne, a taki wspólny customowy Parent je spina.

Reasumując. Czy taki Parent to dobry pomysł? Ewentualnie gdzie przebiega granica i które elementy powinny być po prostu wyniesione do osobnych, małych bibliotek?

Pozdrawiam

A czemu nie jakaś biblioteka na zasadzie dependencji? Stworzyć jakiś projekt javy, nazwać project-name-shared, wrzucić tam DTO, wspólne beany i dołączyć do każdego projektu tą bibliotekę? Bez ruszania spring-boot-parent, ta biblioteka nie powinna byc parantem tylko po prostu zależnością, której używa każdy mikroserwis

0

Ze swojego doświadczenia powiem że nie warto.
W byłej firmie mieliśmy takie "shared" komponenty i to same problemy.
Mieliśmy jeden model, po którym dziedziczyły modele konkretnych serwisów.
Teraz każda zmiana w tej bibliotece, pociągła za sobą konieczność podbijania jej wersji we wszystkich repozytoriach.
Generalnie w tym momencie masz mikro serwis ze wszystkimi jego "ułomnościami" i bez ani jednego "bonusu" za jego używanie

0
Black007 napisał(a):

Ze swojego doświadczenia powiem że nie warto.
W byłej firmie mieliśmy takie "shared" komponenty i to same problemy.
Mieliśmy jeden model, po którym dziedziczyły modele konkretnych serwisów.
Teraz każda zmiana w tej bibliotece, pociągła za sobą konieczność podbijania jej wersji we wszystkich repozytoriach.
Generalnie w tym momencie masz mikro serwis ze wszystkimi jego "ułomnościami" i bez ani jednego "bonusu" za jego używanie

Wystarczy:

  • zwiększyć granulację bibliotek, żeby zminimalizować konieczność podbijania wersji
  • programować z głową, projektować rozszerzalny kod, na pewno nie wspólny model do dziedziczenia, bo dziedziczenie to największe powiązanie pomiędzy dwiema klasami

Do takiego stylu programowania trzeba programistów, którzy umieją into programowanie bibliotek. Niestety wiele osób nigdy nie miało doświadczenia z pisaniem tego typu kodu i wychodzą takie kwiatki

W takim stylu programowania pomaga też monorepo, bo po samym diffie idzie ogarnąć, czy zmiana nie wywraca całego świata do góry nogami

2
Bambo napisał(a):

Cześć. Załóżmy, że mamy dość spory system składający się z 50+ mikroserwisów napisanych w Javie opierających się na Spring Boot.
Czy w takim wypadku powinniśmy dziedziczyć każdy mikroserwis ze spring-boot-starter-parent czy też powinniśmy zrobić osobny projekt "patentowy", który dziedziczy z tego Spring, ale wnosi jakieś wspólne funkcjonalności, które są share'owane między mikroserwisami?

Nie ma to jak stworzyć mikroserwisy, żeby były niezależne od siebie; a potem dodac do nich zależność z dziedziczeniem (czyli najsilniejszą jaka jest).

To po co te mikroserwisy w ogóle?

1

Pomijając kwestie ideologiczne jak bardzo i w jaki sposób jeden mikroserwis powinien być niezależny od drugiego, to copy paste paru plików to max godzina roboty na sztukę, a rozwiązywanie problemów związanych z tymi splątaniami może zająć tygodnie.

1
slsy napisał(a):
  • zwiększyć granulację bibliotek, żeby zminimalizować konieczność podbijania wersji

Poszedlbym krok dalej i zwiekszyl granulacje do poziomu ze kazdy mikroserwis ma swoja i problem rozwiazany. Skoro juz idzie sie w mikroserwisy to robmy mikroserwisy a nie badziew gorszy od monolitu

2

Jeśli znajdujesz się w sytuacji, że mikroserwisy mają tyle wspólnych części, że potrzebujesz je wydzielać do "commonsów" to tak na prawdę to nigdy nie były mikroserwisy, tylko monolit pod przykrywką.

1

Pracuję przy gigantycznej odziedziczonej Java kobyle która ma dokładnie taki setup jak opisałeś.

Czyli: super-projekt (super w sensie Java dziedziczenia, nie jest on super) z którego wychodzą child-mikroserwisy... nawet nazwa się zgadza bo ma w sobie człon "starter".

Dokładnie też do tego jest użyty też: "możemy centralnie zarządzać wersjami różnych bibliotek jak np sterownika psql czy czego tam używamy".

Nie twierdzę że to jest dobre podejście, po prostu widzę że świat Javy już do takiego doszedł lata temu.

0
marian pazdzioch napisał(a):

Pracuję przy gigantycznej odziedziczonej Java kobyle która ma dokładnie taki setup jak opisałeś.

Czyli: super-projekt (super w sensie Java dziedziczenia, nie jest on super) z którego wychodzą child-mikroserwisy... nawet nazwa się zgadza bo ma w sobie człon "starter".

Dokładnie też do tego jest użyty też: "możemy centralnie zarządzać wersjami różnych bibliotek jak np sterownika psql czy czego tam używamy".

Nie twierdzę że to jest dobre podejście, po prostu widzę że świat Javy już do takiego doszedł lata temu.

Tylko że to nie ma sensu, bo cały powód dodania mikroserwisów jest taki że mają być jaknajmniej zależne od siebie :D

0

Skoro jest tyle mikroserwisów, to pewnie mają jakiś wspólny kod związany z samą "infrastrukturą" (mam tu na myśli np. service discovery), który można by wydzielić do wspólnej parenta i myślę, że to jest ok. To przecież nie wprowadza wzajemnych zależności pomiędzy serwisami, a zmniejszy ilość kodu do utrzymania.

Jednak jeśli chodzi pakowanie do takiego parenta rzeczy typu DTO lub centralnie sterowanie wersjami bibliotek, to unikałbym.

4

Wspólny parent (jeśli mówimy o Mavenie) może być dobrym rozwiązaniem, ale tylko wtedy, jeśli serwisy bazujące na jego różnych wersjach nadal są niezależne.

Przykład: w parencie mamy ważną libkę w wersji 1. Wychodzi wersja 2 - prosta sprawa - wydajemy nową wersję parenta, w systemie nie ma prawa się nic zmienić, dalej wszystkie serwisy korzystają ze starego. Później bierzemy jeden serwis i podbijamy parenta do nowej wersji, lecimy z testami, wdrażamy tylko to. Cały system powinien nadal działać.

Więc to nie jest tak, że podbicie w parencie natychmiast wymusza aktualizacje w każdym projekcie, no chyba że ktoś leci na prodzie na snapshotach i latestach, ale to jest sam sobie winien :P

0

Parent taki jak mówi @kelog i dodatkowo aktualny template, każdy zespół nie będzie chciał rozwiązywać tych samych problemów od nowa.

0
Productionserver napisał(a):

Parent taki jak mówi @kelog i dodatkowo aktualny template, każdy zespół nie będzie chciał rozwiązywać tych samych problemów od nowa.

W takim parencie (dalej idąc przykładem Mavena i Springa) fajnie jakby się znalazły:

  • zależności "oczywiste" typu podstawowy Spring, jakieś commonsy, lomboki, junity etc.
  • zależności do infrastruktury, typu libki do Postgresa, Kafki, chmury etc. plus ich domyślne konfiguracje (czyli np. baza domyślnie na localhost:5432/nazwa_projektu)
  • bardzo podstawowe configi powyższych, czyli np. endpointy do metryk, domyślne pule wątków do weba i baz, pattern logowania, konfigi tracingu czy zipkina etc.

Tylko tak jak pisałem, to wszystko każdy mikroserwis może wciągnąć i np. wyexcludować sobie coś, jak mu nie pasuje. Dalej są niezależne. W ogóle serwis nie musi używać tego parenta, ale wtedy zespół jest odpowiedzialny za swoje samoróbki :)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.