Autonomiczne mikrousługi, kolejki zdarzeń i wykrywanie usług

15

Ostatnio dużo czytałem o mikro-usługach i oto niektóre wnioski, które do tej pory wyciągnąłem (proszę, popraw mnie, jeśli się mylę w dowolnym momencie).

  1. Architektura mikrousług dobrze współgra z projektowaniem opartym na domenie. Zwykle jedno państwo członkowskie reprezentuje jeden ograniczony kontekst.
  2. Jeśli mikrousługa A wymaga funkcji znajdującej się w mikrousługie B , prawdopodobnie mój model jest nieprawidłowy, a A i B powinny w rzeczywistości być jedną mikrousługą / BC.
  3. Synchroniczna komunikacja między mikrousługami (bezpośrednie żądania HTTP) jest zła, ponieważ nie spełnia celu mikro-usług i wprowadza sprzężenie między komponentami.
  4. Pożądana jest asynchroniczna komunikacja między usługami. Usługi powinny publikować zdarzenia w kolejkach komunikatów, aby inne usługi mogły subskrybować i przetwarzać swoją część zdarzenia lub wykorzystywać je do replikacji części danych potrzebnych do ich kontekstu. W ten sposób usługi mogą przetwarzać żądania, nawet gdy inne usługi są wyłączone, co nie byłoby w przypadku komunikacji synchronicznej.
  5. Jeśli mikro-usługa A publikuje zdarzenie, mikro-usługa B subskrybuje to zdarzenie i generuje nowe zdarzenie jako wynik, mikrousługa A nie powinna być tym przetwarzającym nowo utworzone zdarzenie, ponieważ byłaby to zależność cykliczna. W takim przypadku powinniśmy wprowadzić trzecią mikrousługę lub połączyć A i B w mikrousługę AB .
  6. Mikro-usługa jest w rzeczywistości terminem wprowadzającym w błąd. Powinniśmy dążyć do małych kontekstów, ale nie musi tak być. Termin nie powinien być „mikrousługą”, ale „ wystarczająco duży, aby wykonać pracę ”.
  7. Mikro-usługi pozwalają nam wprowadzać nowe funkcjonalności z większą łatwością i bez obawy, że zepsujemy cały system. Można tego dokonać, wprowadzając nową usługę lub refaktoryzując jedną z istniejących.
  8. Każda mikrousługa powinna mieć własne miejsce do przechowywania danych. Replikacja / duplikacja danych jest pożądanym zachowaniem w tej architekturze.

Poza potwierdzeniem mojego zrozumienia tej architektury, moja inna część pytania dotyczy głównie odkrywania usług. Jeśli usługi komunikują się asynchronicznie i korzystają z centralnej kolejki zdarzeń, takiej jak amazon SQS, czy to oznacza, że ​​wykrywanie usług nie ma miejsca w takiej architekturze?

Usługi nie powinny mieć żadnej wiedzy o innych usługach w systemie. Są świadomi tylko swojego kontekstu i wydarzeń, które powinni publikować lub subskrybować?

Robert
źródło

Odpowiedzi:

4

Twoje wnioski wydają się w większości uzasadnione i bardzo dobrze podsumowują drogę do mikrousług.

Jednak nie w pełni poprę 2, 5 i 8:

  • 2) Prosta zależność nie powinna automatycznie prowadzić do fuzji. Musisz wziąć pod uwagę częstotliwość takich zależnych połączeń, a także częstotliwość połączeń z innych usług.

    Jeśli więc mikrousługa A bardzo często wymaga funkcjonalności w mikrousługie B, a mikrousługa B rzadko jest potrzebna innym mikrousługom, powinieneś zakwestionować przewidywaną strukturę i zapytać, czy nie byłoby bardziej odpowiednie grupowanie obu mikrousług.

  • 5) oczywiście musisz unikać niekończącego się cyklicznego przetwarzania wiadomości.

    Ale dodanie pośrednika nie zapobiegnie temu: A może uruchomić komunikat obsługiwany przez C, który uruchamia komunikat obsługiwany przez B, który uruchamia komunikat obsługiwany przez A i tutaj jesteś uwięziony w pętli.

    Problemu nie da się ocenić tylko biorąc pod uwagę poziom mikrousług: tak naprawdę chodzi o rodzaj i treść wiadomości, które mogą prowadzić do cyklu. Dlatego wykres, który modeluje dystrybucję i przetwarzanie wiadomości w ramach usług, musi być analizowany jako całość (w rzeczywistości może być złożony, więc można sobie wyobrazić mikrousługę monitorującą, która wykrywa takie cykle i je przerywa).

  • 8) tak, każda mikrousługa ma swoją dedykowaną pamięć / bazę danych.

    Wymagana jest minimalna replikacja, aby umożliwić niezależność usług. Jednak nie posunąłbym się tak daleko, aby powiedzieć, że replikacja jest pożądana: należy ją ograniczyć do minimum, aby uniknąć ukrytego łączenia poprzez procesy replikacji.

    Mikrousługi dotyczą luźnego sprzężenia. Czasami można to bardziej skutecznie osiągnąć przez wywołanie innej mikrousługi w celu pobrania powiązanych danych zamiast replikowania danych.

Dwie ostatnie nienumerowane afirmacje są zbyt szerokie, aby można było na nie jednoznacznie odpowiedzieć. Myślę, że twoja sugestia jest dobrym punktem wyjścia, ale tak naprawdę zależy od wymagań architektonicznych i ograniczeń.

Christophe
źródło
„Czasami można to bardziej skutecznie osiągnąć, wywołując inną mikrousługę w celu pobrania powiązanych danych, zamiast replikowania danych”. Nie ma nic złego w odrobinie synchronicznej komunikacji i bezpośrednich połączeń (przez HTTP) w celu pobrania części danych, ponieważ dopóki zapytanie nie reprezentuje rozproszonej transakcji / polecenia, w przeciwnym razie nie możemy zagwarantować atomowości tego polecenia?
Robert
1
Nie ma tutaj idealnego rozwiązania: jest to luźne połączenie i hermetyzacja ( microservices.io/patterns/data/database-per-service.html ) w celu zrównoważenia łatwości, ale redundancji ( microservices.io/patterns/data/event-driven-architecture .html ) w kontekście ogólnego obrazu ( microservices.io/patterns/microservices.html )
Christophe
3

Mikro-usługi dotyczą oddzielania różnych domen funkcjonalności. Każda usługa może być rozwijana w innym tempie, przez inny zespół, przy użyciu innego stosu technologii. Zapewnia to elastyczność organizacyjną. Kompromisem jest złożoność operacyjna, w której każda dodatkowa usługa tworzy jeszcze jedną rzecz, którą należy zarządzać w środowisku operacyjnym. Tak więc podstawowy kompromis między monolitem a mikrousługą nie polega na unikaniu zależności, lecz na unikaniu etapowego opracowywania i wdrażania, w którym wszystko musi być wysyłane jednocześnie, ale kosztem konieczności wysyłania częściej, ponieważ istnieją więcej ruchomych części.

Usługi nie powinny mieć żadnej wiedzy o innych usługach w systemie. Są świadomi tylko swojego kontekstu i wydarzeń, które powinni publikować lub subskrybować?

Problemem unikania zależności jest czerwony śledź. Zawsze będziesz mieć zależności między częściami swojego produktu, a to, czy są one w oddzielnej usłudze, czy w części tego samego kodu, nie zmienia faktu, że zależności mogą się zerwać. Mogą się zepsuć na poziomie operacyjnym, ponieważ serwer kluczy przestaje działać, a Ty zarządzasz tym poprzez nadmiarowość operacyjną i praktyki przełączania awaryjnego. Mogą również ulec uszkodzeniu na poziomie integracji, ponieważ części zmieniają się w niekompatybilny sposób, co można wykryć podczas testowania integracji. Tasowanie kodu między usługami nie rozwiązuje problemu potencjalnie zepsutych zależności. Rozwiązaniami pozwalającymi uniknąć przerwanych zależności są testy nadmiarowości operacyjnej i integracji, które nie mają nic wspólnego z rozmiarem twoich usług.

Jeśli usługi komunikują się asynchronicznie i korzystają z centralnej kolejki zdarzeń, takiej jak amazon SQS, czy to oznacza, że ​​wykrywanie usług nie ma miejsca w takiej architekturze?

Aby odpowiedzieć na to pytanie, najpierw odpowiedz na to: dlaczego chcesz komunikować się asynchronicznie? Czy ma to ułatwić niezależny rozwój oddzielnych komponentów? Czy ma to poprawić dostępność operacyjną systemu 24/7? Powiedzmy, że to ten drugi i chcesz użyć kolejek do replikacji danych do lokalnych baz danych. Cóż, teraz Twoje dane mogą być nieaktualne. W pewnym momencie będzie zbyt przestarzały. Jak sobie z tym radzisz? Ponadto, w jaki sposób zapewniasz dostępność operacyjną kolejki, która jest kolejnym komponentem wykonawczym? W jaki sposób zapewniasz dostępność tych lokalnych baz danych? Zamiast zarządzać jednym klastrem bazy danych, teraz masz kilka. Czy Twój zespół operacyjny może poradzić sobie z tym obciążeniem? I naprawdę, czy złożoność jest tego warta, kiedy być może Twoi użytkownicy będą zadowoleni z większej liczby funkcji i kilku godzin przestoju każdego miesiąca, jeśli zbudujesz prosty monolit?

Myślę, że rozumiesz mój punkt widzenia. Projektowanie systemu nie polega na tym, co dobre i złe, ale na wybieraniu spośród szerokiej gamy kompromisów. Wszystko, co jest nie tak, może być właściwe i odwrotnie, jeśli tylko zobaczysz to we właściwym kontekście. Context jest unikalny dla ciebie, więc podczas gdy możemy dać się odpowiedź, że nie będzie odpowiedź. Pamiętaj, kim są twoi odbiorcy, jakie są ich potrzeby, a odpowiedni projekt się ujawni.

Joeri Sebrechts
źródło
2
  1. Architektura mikrousług dobrze współgra z projektowaniem opartym na domenie. Zwykle jedno państwo członkowskie reprezentuje jeden ograniczony kontekst.

Nie zgadzać się. DDD bywa bardzo OO. zamówienie jest dostarczone? Order.Deliver (), podczas gdy mikrousługi miałyby DeliveryService.Deliver (zamówienie)

  1. Jeśli mikrousługa A wymaga funkcji znajdującej się w mikrousługie B, prawdopodobnie mój model jest nieprawidłowy, a A i B powinny w rzeczywistości być jedną mikrousługą / BC.

Nie zgadzam się, powinieneś starać się utrzymać mikro usługi mikro. podziel je na jeszcze mniejsze!

  1. Synchroniczna komunikacja między mikrousługami (bezpośrednie żądania HTTP) jest zła, ponieważ nie spełnia celu mikro-usług i wprowadza sprzężenie między komponentami.

Nie zgadzać się. usługi nie powinny dbać o to, kto do nich dzwoni, a dzwoniący nie powinni dbać o to, że logika jest zaimplementowana w mikrousługach.

  1. Pożądana jest asynchroniczna komunikacja między usługami. Usługi powinny publikować zdarzenia w kolejkach komunikatów, aby inne usługi mogły subskrybować i przetwarzać swoją część zdarzenia lub wykorzystywać je do replikacji części danych potrzebnych do ich kontekstu. W ten sposób usługi mogą przetwarzać żądania, nawet gdy inne usługi są wyłączone, co nie byłoby w przypadku komunikacji synchronicznej.

Kolejki są dobre. Ale twoje rozumowanie jest błędne. jedyną różnicą między odpowiedziami synchronizacyjnymi a asynchronicznymi jest to, że czekasz na jedną synchronizującą. Możesz implementować wywołania w stylu RPC z kolejkami i wieloma pracownikami bez problemu.

  1. Jeśli mikro-usługa A publikuje zdarzenie, mikro-usługa B subskrybuje to zdarzenie i generuje nowe zdarzenie jako wynik, mikrousługa A nie powinna być tym przetwarzającym nowo utworzone zdarzenie, ponieważ byłaby to zależność cykliczna. W takim przypadku powinniśmy wprowadzić trzecią mikrousługę lub połączyć A i B w mikrousługę AB.

Nie zgadzać się. Nie jest to zależność cykliczna, ponieważ mikrousług nie są powiązane. Również chcesz zaspokoić ponowne wysyłanie senarios, SendEmail, EmailFailed, SendAgain nie potrzebuje 3 mikro-usług

  1. Mikro-usługa jest w rzeczywistości terminem wprowadzającym w błąd. Powinniśmy dążyć do małych kontekstów, ale nie musi tak być. Termin nie powinien być „mikrousługą”, ale „wystarczająco duży, aby wykonać pracę”.

Nie zgadzać się. Sprawdź nano-usługi.

  1. Mikro-usługi pozwalają nam wprowadzać nowe funkcjonalności z większą łatwością i bez obawy, że zepsujemy cały system. Można tego dokonać, wprowadzając nową usługę lub refaktoryzując jedną z istniejących.

Nie zgadzać się. Tak, masz rozdzielenie, ale koordynacja mikrousług może być tak zniechęcająca jak każdy projekt monolityczny

  1. Każda mikrousługa powinna mieć własne miejsce do przechowywania danych. Replikacja / duplikacja danych jest pożądanym zachowaniem w tej architekturze.

Nie zgadzać się. Chociaż nie powinieneś współdzielić przestrzeni dyskowej, twoje mikro-usługi powinny starać się być bezstanowe tam, gdzie to możliwe. nie powielaj danych, chyba że jest to inflight

Ewan
źródło
1

Twoje wnioski są fajne, ale nie uniwersalne. Zdarzają się przypadki, gdy najlepszą opcją jest złamanie tych zasad, nawet w projekcie typu greenfield. W niektórych przypadkach najlepszym rozwiązaniem jest komunikacja synchroniczna. W niektórych przypadkach nie jest dobrze połączyć dwie usługi w jedną, nawet jeśli są one połączone komunikacją synchroniczną.

W przypadku drugiego pytania wykrywanie usług nie jest wymagane w przypadku komunikacji opartej na kolejce.

Gudmundur Orn
źródło
0

Mówisz tylko o programowaniu obiektowym. A przynajmniej to, co pierwotnie miało być: niezależne fragmenty działającego kodu komunikujące się ze sobą za pomocą komunikatów.

Alan Kay wymyślił OOP wzorowany na układach biologicznych, w których komórki są względnie niezależne od siebie i komunikują się za pośrednictwem komunikatów podłączanych do zewnętrznych interfejsów innych komórek.

Dlaczego więc przestajemy myśleć o tym jako OOP tylko dlatego, że wszystkie obiekty nie działają na tym samym komputerze? Jeśli już, jest to nawet bardziej zorientowane obiektowo niż na tym samym komputerze i części tej samej aplikacji, ponieważ jeśli wszystkie obiekty znajdują się w tej samej aplikacji, programiści często przerywają OOP, używając zmiennych globalnych wspólnych dla wszystkich klas i w tym te same nagłówki w każdym pliku itp. Gdy wszystkie obiekty zależą od tych samych rzeczy, nie są tak enkapsulowane, jak gdyby były całkowicie od siebie niezależne, a enkapsulacja to cały punkt OOP.

Na przykład prawie wszystko, co powiedziano w innych odpowiedziach, to podręczniki o OOP.

CommaToast
źródło
0

Ponieważ często spotykam się z niewłaściwym rozumieniem tak ważnej koncepcji, jak Ograniczony kontekst i domena podstawowa, chciałbym rozwinąć nieco tę kwestię.

Uważam, że niezwykle opłacalne jest myślenie o subdomenach jako o możliwościach biznesowych. Możliwości biznesowe to coś, co robi Twoja organizacja. Jest to jedna z jego funkcji biznesowych. Ponieważ naszym celem jest dostosowanie biznesu do IT , zdecydowanie chcę, aby miały one stosunek 1: 1 do moich służb technicznych .

Ten proces sprowadza się do następujących kwestii. Najpierw definiuję możliwości biznesowe wyższego poziomu. Powinien przybierać formę rzeczownika i czasownika (lub innej formy pochodnej). Zwykle jest mniej niż 10 możliwości biznesowych. Potem jestem głębiej, identyfikując zagnieżdżone możliwości. I tak dalej, dopóki nie będzie nic do podzielenia. Możliwości, które przyszedłeś przy użyciu tego podejścia, odzwierciedlają rzeczywistą domenę, rzeczywisty sposób działania organizacji. Funkcje te będą wewnętrznie luźno powiązane, więc jeśli zmapujesz swoje usługi techniczne na te możliwości, będą one autonomiczne i sterowane zdarzeniami. Proces ten nazywa się mapowaniem zdolności biznesowych , ale istnieją inne sposoby znalezienia usług, z których najbardziej widoczna to prawdopodobnie analiza łańcucha wartości .

Oto przykład identyfikacji granic usług przy użyciu tego podejścia.

Zapadło
źródło