Czy usługi powinny bezpośrednio ze sobą rozmawiać w architekturze mikrousług?

10

Mam wiele usług internetowych, które tworzą aplikację internetową. Klienci mogą uzyskać dostęp do tych usług za pośrednictwem wywołań interfejsów API REST.

Czy te usługi powinny być w stanie rozmawiać bezpośrednio ze sobą? Jeśli tak, czy nie doprowadziłoby to do ich połączenia, co jest sprzeczne z koncepcją mikrousług?

Czy klient powinien dzwonić do nich bezpośrednio jeden po drugim, aby uzyskać dane potrzebne do załadowania strony internetowej na kliencie?

A może powinienem mieć kolejną warstwę nad usługami, która obsługuje żądanie od klienta, pobiera dane dla tego żądania, a następnie odsyła je z powrotem do klienta?

cod3min3
źródło
Jeśli rzeczy są całkowicie niezwiązane, to są to całkowicie oddzielne produkty. Więc użytkownik musiałby zalogować się do Contoso Login, a następnie Contoso Login powiedziałby „Jesteś teraz zalogowany!” ... a następnie przechodzi do Contoso Sensitive Data Storage, zaznacz pole wyboru „Tak, jestem zalogowany „... następnie skopiuj i wklej dane z tego do procesora danych
Contoso

Odpowiedzi:

16

Jeśli chcesz, aby Twoje usługi wyglądały tak jak na tym zdjęciu, to tak: wprowadź opis zdjęcia tutaj Nie jest tak, że nie możesz tego zrobić, ale przez większość czasu będzie to miało złe konsekwencje. Komunikacja przez REST nie rozdzieli znacząco usług. W przypadku zmiany interfejsu niektórych usług wszystkie usługi zależne najprawdopodobniej muszą zostać zmienione i ponownie wdrożone. Również podczas ponownego wdrażania usługi będziesz musiał odłożyć wszystkie usługi zależne, co nie jest uważane za dobry projekt dla wysokich standardów dostępności.

W końcu będziesz mieć aplikację mikrousług, która jest wolniejsza niż alternatywna aplikacja do monolitu, ale ma prawie te same problemy!

Nie mogę się zgodzić z @Robert Harvey

W praktyce jednak jedna lub więcej z twoich mikrousług (być może wszystkie) będzie komunikować się z jakimś centralnym magazynem danych, takim jak baza danych SQL.

Baza danych integracji jest dobrze znanym antatatternem

O wiele lepszym rozwiązaniem jest użycie wzorca publikowania i subskrybowania, aby komunikacja między usługami była asynchroniczna:

wprowadź opis zdjęcia tutaj

Proszę spojrzeć na sposób wdrożenia tej metody komunikacji przez CQRS / ES, Greg Young i inni faceci oferują mnóstwo fajnych filmów na ten temat. Wystarczy wyszukać słowo kluczowe „CQRS / ES”. Dzięki takiemu podejściu każda usługa stanie się jednocześnie wydawcą i subskrybentem, dzięki czemu usługi będą znacznie mniej połączone.

Oto dobra seria artykułów o mikrousługach, które rzucają światło na kontrowersje wokół tego tematu. Bardzo szczegółowe wyjaśnienie z ładnymi ilustracjami.

IlliakaillI
źródło
2
Po pierwsze, nigdzie nie słyszałem terminu „baza danych integracji” poza Fowler. Nie bierz czegoś za ewangelię tylko dlatego, że powiedział to jeden facet. Po drugie, nie masz wystarczających informacji, aby nazwać to, co opisałem, „integracyjną bazą danych”. Po trzecie, Fowler nazywa takie bazy danych przydatnymi w odpowiednich okolicznościach, w tym samym artykule, który podłączyłeś. Podoba mi się pomysł magistrali zdarzeń, choć nie rozumiem, jak to wszystko różni się od wywoływania zwykłego interfejsu API mikrousług, chyba że można zwiększyć wydajność.
Robert Harvey
Dziękuję Robercie, połączyłem artykuł Fowlera, aby lepiej zilustrować pomysł, a nie kłócić się z autorytetem. Sposób, w jaki opisałeś to podejście, przypomina bardzo integracyjną bazę danych. Jeśli jest inaczej - wcale nie jest to oczywiste. Jeśli chodzi o właściwe okoliczności - myślę, że integracja mikrousług za pośrednictwem bazy danych nie jest dobrym pomysłem, ponieważ spycha nas z powrotem do architektury monolitycznej.
IlliakaillI
1
Pewnie: każda mikrousługa będzie rozmawiać z własną oddzielną bazą danych lub z tabelami w tej samej bazie danych, które nie są powiązane z tabelami innych usług. W ten sposób usługi nigdy nie wymieniają informacji za pośrednictwem bazy danych, co oznacza, że ​​można łatwo skalować w poziomie i będzie znacznie mniej wąskich gardeł. A ponieważ nie dzielą tych samych tabel - zmiany w jednej części aplikacji będą miały mniejszy wpływ na inne części.
IlliakaillI
1
Nie można kategorycznie stwierdzić tego jako absolutnego. Mogą istnieć dwie usługi, które potrzebują tych samych informacji w tej samej bazie danych, potrzebują ich tylko od czasu do czasu, nie ma problemu ze skalowaniem, aby uzyskać do nich dostęp w ten sposób, obie usługi i tak już uzyskują dostęp do bazy danych do innych celów, więc postawienie magistrali usług lub punkt końcowy interfejsu API, aby to osiągnąć, byłoby absurdalne.
Robert Harvey,
1
Ale aby osiągnąć wartość biznesową, chcesz połączyć dane - „pokaż mi wszystkie systemy kanalizacyjne, które będą miały niewystarczającą pojemność, biorąc pod uwagę następujące dane radarowe o nadchodzącym deszczu, i pokoloruj tę mapę gmin, używając wyniku”. Jeśli podzielisz wszystkie swoje dane na usługi, oznacza to, że możesz je połączyć dopiero później. Jeśli zabronisz usługom ze sobą rozmawiać, po prostu zmusisz się do przeniesienia wszystkich danych do jakiegoś klienta i dołączenia do nich. CHCESZ gdzieś sparować dane, bo to w końcu daje wartość aplikacji.
RemcoGerlich,
8

Dostaniesz wiele bardzo dobrych pomysłów, czytając, co Udi Dahan ma do powiedzenia na temat SOA .

Usługa jest organem technicznym dla konkretnej zdolności biznesowej. Każda część danych lub reguła musi być własnością tylko jednej usługi.

Oznacza to, że nawet wtedy, gdy usługi publikują się nawzajem i subskrybują wydarzenia, zawsze wiemy, jakie jest wiarygodne źródło prawdy dla każdego elementu danych i reguł.

Ponadto, patrząc na usługi z perspektywy możliwości biznesowych, widzimy, że wiele interfejsów użytkownika przedstawia informacje należące do różnych możliwości - cena produktu wraz z tym, czy jest on w magazynie, czy nie. Aby zachować zgodność z powyższą definicją usług, prowadzi nas to do zrozumienia, że ​​takie interfejsy użytkownika są w rzeczywistości połączeniem - każda usługa ma fragment interfejsu użytkownika zajmujący się jej konkretnymi danymi.

Szczególnie jeśli chodzi o skład interfejsu użytkownika, artykuł Mauro Servienti na temat składu interfejsu użytkownika jest dobrym punktem wyjścia. Zobacz także wideo Udi, dostępne tutaj .

Czy te usługi powinny być w stanie rozmawiać bezpośrednio ze sobą? Jeśli tak, czy nie doprowadziłoby to do ich połączenia, co jest sprzeczne z koncepcją mikrousług?

Jeśli dwie usługi wymieniają się ze sobą wiadomościami, otrzymasz połączenie. Główną odpowiedzią jest to, że łączą się one z interfejsem API drugiej usługi - umowa, którą usługa obiecuje zachować stabilność, nawet gdy zmieniają się jej elementy wewnętrzne.

Poza tym techniki takie jak wykrywanie usług mogą złagodzić zależność od konkretnego usługodawcy, a brokerzy wiadomości mogą oddzielić producentów i konsumentów (nadal muszą rozumieć się nawzajem i jak wchodzić w interakcje z API brokera wiadomości - nie ma magii ).

VoiceOfUnreason
źródło
7

To zależy od tego, co rozumiesz przez „bezpośrednio”.

Zgodnie z architekturą mikrousług jest w porządku, aby mieć mikrousługi, które wywołują inne mikrousług, na własnym serwerze, a nawet na serwerach zewnętrznych, za pośrednictwem interfejsu takiego jak REST.

To, co nie jest w porządku, polega na tym, że jedna mikrousługa wywołuje inną przy użyciu bezpośrednich wywołań metod; sprawiłoby, że obie mikrousług byłyby częścią tego samego monolitu.

Mike Nakis
źródło
to nie jest w porządku i będzie miało złe konsekwencje. Zobacz moją odpowiedź, aby uzyskać więcej informacji.
IlliakaillI
@IlliakaillI Mówię, że jest w porządku „zgodnie z architekturą mikrousług”. Nie sugeruję, że architektura mikrousług jest wolna od konsekwencji lub że nie można wprowadzić w niej żadnych ulepszeń. Pytanie brzmi „czy X jest według książki, czy nie?” a prawidłowa odpowiedź jest taka, że ​​biorąc pod uwagę poprawną definicję X, jest to książka.
Mike Nakis,
Czy istnieje „podręcznik”, który mówi, jak zbudować prawdziwą „architekturę mikrousług”? Mikrousługi stają się obecnie modnym słowem i wiele osób pisało książki o tym, jak budować monolity na REST. Wystarczy spojrzeć na ten pierwszy schemat w mojej odpowiedzi, nie ma sensu budować systemu w ten sposób. Jeśli robisz to z jakiegoś dziwnego powodu - zdecydowanie robisz to źle. Zamiast tego lepiej iść z monolitem. Jeśli popierasz swoje wybory projektowe, ślepo odwołując się do niektórych książek (argumentując autorytet), nie jest to właściwy sposób podejścia do projektowania oprogramowania.
IlliakaillI
5

Czy te usługi powinny być w stanie rozmawiać bezpośrednio ze sobą? Jeśli tak, czy nie doprowadziłoby to do ich połączenia, co jest sprzeczne z koncepcją mikrousług?

Sprzężenie nie jest złym słowem. Każde zastosowanie ma już pewien stopień sprzężenia; aplikacje komunikujące się z mikrousługami są już połączone z mikrousługami, w przeciwnym razie nie działałyby.

To, czego naprawdę potrzebujesz w mikrousługach, to luźne sprzęganie ; możesz to osiągnąć, po prostu prosząc jedną mikrousługę o przesłuchanie drugiej za pośrednictwem publicznego interfejsu API lub za pomocą magistrali zdarzeń.

W praktyce jednak jedna lub więcej z twoich mikrousług (być może wszystkie) będzie rozmawiać z jakimś centralnym magazynem danych, takim jak baza danych SQL. W zależności od tego, w jaki sposób chcesz osiągnąć swój cel, możesz po prostu zmusić jedną mikrousługę do zmiany danych w jakiś sposób, a druga mikrousługa zapyta o zmianę.

Robert Harvey
źródło
3
„Baza danych integracji” jest dobrze znanym antypatternem, więcej szczegółów można znaleźć w mojej odpowiedzi.
IlliakaillI
2

Wydaje się, że mówiąc o architekturze SOA i ogólnie architekturze, ludzie wpadają w semantykę i żargon. Co sprawia, że ​​usługa jest „mikro”? Ostatecznie jest to pewien zestaw cech, który w jakimkolwiek „systemie punktacji”, którego używasz, wyraźnie nie czyni usługi „niemikro”. Co powiedział sąd najwyższy o nieprzyzwoitości? „Będę wiedział, kiedy to zobaczę”.

Jestem pewien, że niektórzy powiedzą, że to nie jest odpowiedź, ale potem nie rozumieją sedna sprawy. Architektury mikrousług mają na celu uniknięcie kilku problemów, w tym problemu „ścisłego łączenia”. Tak więc, jeśli w końcu stworzysz plątaninę mikrousług, które zależą od zbyt wielu drobnych szczegółów, stworzyłeś ścisłe połączenie, które - niezależnie od tego, czy korzystasz z szyny wiadomości / sub-wiadomości lub połączeń bezpośrednich - niszczy twoja umiejętność komponowania nowych rozwiązań z elementów, rekonfiguracji poszczególnych elementów bez obniżania całego systemu itp

Flickerthing com com
źródło
1

Czy klient powinien dzwonić do nich bezpośrednio jeden po drugim, aby uzyskać dane potrzebne do załadowania strony internetowej na kliencie?

To zależy; sugerowałbym jednak zapewnienie bezpośrednio użytecznych możliwości klientowi i ukrywanie (hermetyzowanie) szczegółów dotyczących sposobu zestawiania wyników (np. za pośrednictwem wielu mikrousług).

Jeśli zbyt duża logika jest zaangażowana w łączenie indywidualnych wyników mikrousług przez klienta, może to przypadkowo spowodować, że pewna logika biznesowa wkradnie się do klienta. Może także ujawnić klientowi większą część wewnętrznej architektury, co utrudnia późniejsze refaktoryzowanie mikrousług.

Oznacza to, że w przypadku mikrousług czasami pomocne jest posiadanie owijającej się mikrousługi, która zapewnia klientowi punkt końcowy mający przydatne abstrakcje i która wykonuje koordynację wyższego poziomu innych (być może teraz bardziej wewnętrznych) mikrousług.


(Co więcej, podróże w obie strony do klienta są prawdopodobnie droższe niż w przypadku wzajemnych mikrousług).


Jeśli spojrzysz na przykład, w którym kierunku podąża GraphQL, zobaczysz, że klienci wysyłają bezpośrednio odpowiednie zapytania do punktu końcowego, które mogą, ale nie muszą być zaimplementowane jako zbiór mikrousług. Ponieważ architektura mikrousług jest ukryta za GraphQL, ułatwia to refaktoryzację architektury i jest bardziej przyjazne dla klienta. Zobacz na przykład https://stackoverflow.com/a/38079681/471129 .

Erik Eidt
źródło
1

Głównym celem mikro-usług jest luźne powiązanie aplikacji. Dlatego usługi nie mogą do siebie dzwonić. W przeciwnym razie będzie wiązany. Ale co zrobimy, jeśli będziemy mieć dwie usługi, które wymagają udostępniania danych? Odpowiedzią jest Message Broker. Tak więc usługa, która pobiera dane od klienta, może udostępniać dane centralnemu brokerowi komunikatów, a następnie usługi muszą z nich korzystać, mogą je wykorzystać, przekształcić i umieścić we własnym magazynie danych. Polecam Kafka, ponieważ możesz łączyć w locie dane z innego tematu za pomocą Kafka Stream. PS. lepiej oddzielić swoje mikro-usługi według funkcji.

Panuwat Anawatmongkhon
źródło