Ankieta - mikroserwisy a współdzielenie kodu

4

cześć
Temat stary jak świat i wiadomo że współdzielenie kodu miedzy mikroserwisami raczej przysparza problemów.

(mówiąc dalej "paczka" mam na myśli np. .jar w JVM, paczke w node, nuget w c# itd.)
Realia jednak są takie, że czasami to się zdarza. Nie tyle współdzielony kod biznesowy, co np. osobna paczka do logowania w okreslonym standardzie projektowym, osobna paczka dla konsumerów i producerów Kafki, osobna dla konfiguracji połączenia z bazą (nawet majac baza per serwis), osobna konfigurująca GraphQL itd.
Albo - jedna paczka która służy jako baza dla każdego mikroserwisu, zawierająca wszystko z czego korzysta większość z nich. Np większosc używa Kafki, Postgresa, jakiegoś loggera itd.

Pewne rzeczy to upraszcza, ale też powoduje oczywiste komplikacje.

Może jestem w błędzie, ale mam wrażenie, że taki dylemat rzadziej występuje jak w projekcie używany jest powiedzmy Spring, który praktycznie do wszystkiego ma paczkę, która wystarczy wrzucic na classpath i mamy coś skonfigurowane. Natomiast używając mniejsze biblioteki np. jakieś (strzelam) Akka HTTP, Ktor, Quarkus, Micronaut i tak dalej - często trzeba niektóre rzeczy trzeba po prostu sobie napisać ;)

Stoję teraz trochę przed takim dylematem. Przekopałem już cały internet, ale mam niedosyt.
Zachęcam do odpowiedzi w ankiecie. Będę wdzieczny za jakieś odpowiedzi jak to u was jest i jak to się z tym żyje :) (chyba warto wspomnieć z jaką ilościa mikrosvc pracujecie)

Dzięki!

1
azalut napisał(a):

Temat stary jak świat i wiadomo że współdzielenie kodu miedzy mikroserwisami raczej przysparza problemów.

Podobnie jak odwrotność, rozpi..l i totalna wolnoamerykanka, założenie, ze nic wspólnego
No dobra, opowiem wam dlacze...

3

Brakuje mi odpowiedzi w stylu "mamy wiele paczek odpowiadających za dzielenie wspólnego kodu takiego jak DTO, dostęp do infrastruktury itp.". Tutaj najbliżej jest opcja trzecia ale aż tak drobnego podziału nie mamy.

1

W projekcie, w którym obecnie pracuję mamy monorepo, ale każdy z serwisów jest wdrażany ciągle i niezależnie. Każdy serwis, to osobny projekt gradlowy. Podobnie z kodem specyficznym pod względem logowania ze względu na wymogi dotyczące SoC i audytu, czy z kodem odpowiedzialnym za:

  • dostęp do infrastruktury,
  • instrumentowanie zależności, których Elastic APM z pudełka nie instrumentuje.

To wszystko są oddzielne projekty w monorepo. Niektóre z nich publikujemy do użytku wewnątrz organizacji.

Jeśli już współdzielimy kod pomiędzy serwisami, to właśnie tylko ten wyżej wspomniany. Jeśli mamy komunikację pomiędzy serwisami, to model i klientów powielamy tu i tu albo generujemy je na podstawie YAMLa (OpenAPI).

Właściwie to trzymamy się tego, że jeśli nasz serwis ma wystawione API po HTTP, to publikujemy odpowiednią definicję w OpenAPI. Na podstawie tej definicji generujemy kod serwera, z którego sami korzystamy odcinając się na adapterze, żeby upewnić się, że jest YAML aktualny i czy nie ma z nim problemów.

1
  1. Każdy serwis ma moduł client budowany jako osobny artefakt i inne serwisy go sobie wciągają, żeby nie musieć myśleć o takich rzeczach jak nazwy endpointów czy mapowanie odpowiedzi na DTO
  2. Oprócz tego jest kilka artefaktów commons-* z jakimiś wspólnymi boilerplatami.
0

@Shalom: A co robicie gdy endpointy się zmieniają? Wersjonujecie klienta a stare utrzymujecie do końca świata?

1

@Fedaykin a co robisz w dowolnym innym przypadku kiedy endpointy sie zmieniają? :) Artefakty są w repo i są wersjonowane, a czy trzymamy stare API czy nie, to zależy od sytuacji. Jeśli wiem dokładnie kto korzysta to mówie im zeby podbili wersje klienta i oram stare endpointy. W innym wypadku możesz wersjonować sobie API.
Niemniej tak czy siak, twoje pytanie nijak sie ma do samego faktu robienia artefaktu z klientem, a raczej do problemu wersjonowania API jako takiego.

0

@Shalom: Rozumiem. Trochę tak, trochę nie - mając np. monorepo z bezpośrednimi zależnościami zmiana API / obiektów powinna spowodować brak kompilacji / błędy w testach jednostkowych/akceptacyjnych innych serwisów. W takim przypadku łatwiej jest sprawdzić wszystkie użycia i ewentualnie je updatować jeżeli nie chcemy wersjonować.

Dodatkowo breaking zmiany w commonach też powodują j/w, to powoduje przeniesienie części odpowiedzialności na osoby robiące tam zmiany bo nie mogą sobie po prostu podbić wersji i zapomnieć o backwards compatibility. Co może być i dobre i złe zależnie od struktury organizacji.

0

@Fedaykin bardzo śmiałe założenie że z twojego API korzystają tylko "wewnętrzne" zależości i zmiana w monorepo wszystko "automatycznie naprawi" ;) No i znów bardzo śmiałe założenie że jesteś w stanie "naprawić" inne serwisy które właśnie popsułeś swoją zmianą. Bo wyobraź sobie że nie zmieniłeś nazwy endpointu, tylko np. dane które są zwracane mają inną postać. Naprawienie innego serwisu który z tego korzysta może być mocno nietrywialne...

Dodatkowo breaking zmiany w commonach też powodują j/w, to powoduje przeniesienie części odpowiedzialności na osoby robiące tam zmiany bo nie mogą sobie po prostu podbić wersji i zapomnieć o backwards compatibility. Co może być i dobre i złe zależnie od struktury organizacji.

Nie bardzo rozumiem w jaki niby sposób. Przecież nikt w twoim projekcie ci nie podbija wersji commonów o_O Tobie wszystko nadal działa tak jak działało, bo lecisz na starej wersji. Dopiero jak sam będziesz podbijać wersje to zobczysz ze coś jest niekompatybilne i musisz to u siebie naprawić. To właśnie pomysł z monorepo i barkiem wersjonowania może powodować takie fuckupy, że coś nagle przestało ci działać, bo kto w innym miejscu coś sobie zmienił, a ty nie miałeś 100% pokrycia testami...

0

@Shalom: W przypadku wewnętrznych systemów bazowanych na mikroserwisach to rozsądne założenie, zazwyczaj zewnętrzne systemy w takim przypadku nawet nie są w tej samej sieci. End-pointy wychodzące na świat zewnętrzny mają ten problem nadal, ale jest ich zazwyczaj zdecydowanie mniej. Oczywiście że to nic "automatycznie nie naprawia", to jedynie pokazuje problemy po stronie wprowadzającej zmiany. Może być mocno nietrywialne i to jest ok, wtedy wiemy kto jest za ten serwis odpowiedzialny i angażujemy go do zmian.

Nie bardzo rozumiem w jaki niby sposób. Przecież nikt w twoim projekcie ci nie podbija wersji commonów o_O Tobie wszystko nadal działa tak jak działało, bo lecisz na starej wersji. Dopiero jak sam będziesz podbijać wersje to zobczysz ze coś jest niekompatybilne i musisz to u siebie naprawić. To właśnie pomysł z monorepo i barkiem wersjonowania może powodować takie fuckupy, że coś nagle przestało ci działać, bo kto w innym miejscu coś sobie zmienił, a ty nie miałeś 100% pokrycia testami...

Dokładnie monorepo miałem na myśli! I to jest fuckup z jednej strony, z drugiej wymusza na wprowadzających zmiany nieco ostrożniejsze/bardziej kolaboracyjne podejście. Brak dobrych testów w tym przypadku będzie prowadzić do problemów tak czy inaczej, bo w modelu nie-monorepo i tak będzie strach w momencie podbijania zależności, więc pewnie będą podbijane tylko gdy jest to absolutnie koniecznie. A tak wszyscy muszą być up-to-date czy tego chcą czy nie.

To absolutnie nie jest złoty graal, inne rozłożenie odpowiedzialności i problemów. Nawet nie jestem przekonany czy jestem fanem takiego podejścia.

1

i tak będzie strach w momencie podbijania zależności

Zawsze jest, ale czym innym jest sytuacja kiedy wiesz ze podbijasz i patrzysz szczegółowo czy coś się nie sypnęło, a czym innym kiedy nawet nie wiesz ze ktoś coś zmienia w monorepo ;)

więc pewnie będą podbijane tylko gdy jest to absolutnie koniecznie

Wręcz przeciwnie, podbijasz tak szybko kiedy to możliwe, bo poprawki po jednej małej zmianie są proste, a jak podbijesz się o 100 wersji w góre nagle to może się okazać że bardzo cięzko ogarnąć wszystkie potrzebne zmiany.

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