Architektura GraphQL i Microservice

176

Próbuję zrozumieć, gdzie GraphQL jest najbardziej odpowiedni do użycia w architekturze mikrousług.

Trwa debata na temat posiadania tylko 1 schematu GraphQL, który działa jako brama interfejsu API, przekazując żądanie do docelowych mikrousług i wymuszając ich odpowiedź. Mikrousługi nadal używałyby protokołu REST / Thrift do komunikacji.

Innym podejściem jest posiadanie wielu schematów GraphQL, po jednym na mikrousługę. Posiadanie mniejszego serwera bramy interfejsu API, który kieruje żądanie do docelowej mikrousługi ze wszystkimi informacjami o żądaniu + kwerendą GraphQL.

Podejście 1

Posiadanie 1 schematu GraphQL jako bramy API będzie miało wadę polegającą na tym, że za każdym razem, gdy zmieniasz wejście / wyjście kontraktu mikrousług, musimy odpowiednio zmienić schemat GraphQL po stronie bramy interfejsu API.

Podejście 2

Jeśli używasz wielu schematów GraphQL na mikrousługi, ma to sens, ponieważ GraphQL wymusza definicję schematu, a konsument będzie musiał przestrzegać danych wejściowych / wyjściowych podanych z mikrousługi.

pytania

  • Czy uważasz, że GraphQL jest odpowiedni do projektowania architektury mikrousług?

  • Jak zaprojektowałbyś bramę API z możliwą implementacją GraphQL?

Fabrizio Fenoglio
źródło

Odpowiedzi:

242

Zdecydowanie podejście nr 1.

Komunikowanie się klientów z wieloma usługami GraphQL (jak w podejściu nr 2) całkowicie mija się z celem używania GraphQL w pierwszej kolejności, którym jest zapewnienie schematu obejmującego wszystkie dane aplikacji, aby umożliwić pobranie ich w jednej rundzie.

Posiadanie wspólnej architektury „ nic” może wydawać się rozsądne z punktu widzenia mikrousług, ale w przypadku kodu po stronie klienta jest to absolutny koszmar, ponieważ za każdym razem, gdy zmieniasz jedną z mikrousług, musisz zaktualizować wszystkich swoich klientów. Na pewno tego pożałujesz.

GraphQL i mikrousługi są idealnie dopasowane, ponieważ GraphQL ukrywa przed klientami fakt, że masz architekturę mikrousług. Z perspektywy zaplecza chcesz podzielić wszystko na mikrousługi, ale z perspektywy frontendu chciałbyś, aby wszystkie dane pochodziły z jednego interfejsu API. Korzystanie z GraphQL to najlepszy znany mi sposób, który pozwala ci robić jedno i drugie. Umożliwia podzielenie zaplecza na mikrousługi, jednocześnie zapewniając jeden interfejs API dla całej aplikacji i umożliwiając łączenie danych z różnych usług.

Jeśli nie chcesz używać REST do swoich mikrousług, możesz oczywiście mieć każdy z nich z własnym GraphQL API, ale nadal powinieneś mieć bramę API. Powodem, dla którego ludzie używają bram interfejsu API, jest ułatwienie wywoływania mikrousług z aplikacji klienckich, a nie dlatego, że dobrze pasuje do wzorca mikrousług.

pomocnik
źródło
2
@helfer: To naprawdę ma sens :) dzięki. Oprócz tej wspaniałej odpowiedzi mam kilka pytań. - Mówisz, że GraphQL musi być używany jako brama API? - Powiedzmy, że mam mikrousługę zamówienia, która ujawnia punkt końcowy REST lub GraphQL. Po zakończeniu muszę zaktualizować główny schemat GraphQL, aby odzwierciedlić dokładnie te same dane, które ujawni mikrousługa? Czy nie brzmi to powielanie lub odchodzenie od kultury mikrousług, która powinna być wdrażana niezależnie? Jakiekolwiek zmiany w mikrousłudze muszą zostać odzwierciedlone / zduplikowane w głównym schemacie GraphQL?
Fabrizio Fenoglio
13
@Fabrizio fajną rzeczą w GraphQL jest to, że nawet jeśli zmieni się wewnętrzny interfejs REST API, schemat GraphQL może pozostać taki sam, o ile istnieje sposób na uzyskanie danych, które wcześniej ujawniono przez usługę REST. Jeśli ujawnia więcej danych, kanonicznym sposobem radzenia sobie z tym jest po prostu dodanie nowych pól / typów do istniejącego schematu. Ludzie z Facebooka, którzy stworzyli GraphQL, powiedzieli mi, że nigdy nie dokonali przełomowej zmiany w swoim schemacie przez cztery lata. Wszystkie wprowadzone przez nich zmiany były addytywne, co oznacza, że ​​nowi klienci mogliby korzystać z nowej funkcjonalności, podczas gdy starzy klienci mogliby kontynuować pracę.
pomocnik
4
Dobrze! :) Dziękuję za napisanie tego! Śledzę Cię na Medium i na githubie przez repozytoria Apollo! Twoje artykuły i posty są bardzo cenne! :) Tak trzymaj! Myślę też, że średni artykuł z tematem GraphQL + Microservices będzie bardzo przyjemny do przeczytania!
Fabrizio Fenoglio
1
Dzięki, będę o tym pamiętać. Zdecydowanie planuję w którymś momencie pisać o GraphQL i Microservices, ale prawdopodobnie nie w ciągu najbliższych kilku tygodni.
pomocnik
A co z kombinacją opcji nr 2 i github.com/AEB-labs/graphql-weaver ?
Mohsen
35

Zobacz artykuł tutaj , który mówi, jak i dlaczego podejście nr 1 działa lepiej. Spójrz także na poniższe zdjęcie zaczerpnięte z artykułu o którym wspomniałem: wprowadź opis obrazu tutaj

Jedną z głównych zalet posiadania wszystkiego za jednym punktem końcowym jest to, że dane mogą być kierowane bardziej efektywnie, niż gdyby każde żądanie miało własną usługę. Chociaż jest to często reklamowana wartość GraphQL, zmniejszenie złożoności i pełzania usług, wynikowa struktura danych umożliwia również bardzo dobrze zdefiniowane i jasno określone prawa własności do danych.

Kolejną zaletą przyjęcia GraphQL jest fakt, że można zasadniczo zapewnić większą kontrolę nad procesem ładowania danych. Ponieważ proces ładowania danych przechodzi do własnego punktu końcowego, można albo częściowo, w całości, albo z zastrzeżeniami honorować żądanie, a tym samym kontrolować sposób przesyłania danych w niezwykle szczegółowy sposób.

Poniższy artykuł bardzo dobrze wyjaśnia te dwie korzyści wraz z innymi: https://nordicapis.com/7-unique-benefits-of-using-graphql-in-microservices/

Enayat
źródło
Cześć, przepraszam za pytania noob, ale czy twoja bramka GraphQL nie jest nowym punktem przechowywania? Np. Jeśli mam usługę koszyka, która nagle przestała działać, czy moja brama GraphQL również się nie zepsuje? Zasadniczo nie jestem pewien jego roli, ta brama ma zawierać wiele resolverów dla każdej usługi?
Eric Burel
1
@EricBurel Dzięki za pytanie. Właściwie, o ile zrozumiałem z artykułu, wszystkie schematy z różnych usług są ujednolicone w jednym schemacie GraphQL, więc jak wspomniałeś, inne usługi nadal znajdują się w swoich własnych zbiorach danych. Jeśli chodzi o możliwość wystąpienia pojedynczego źródła awarii bramy GraphQL, zawsze istnieją inne opcje, takie jak zapewnienie planu tworzenia kopii zapasowych. Przeczytaj ten artykuł ( labs.getninjas.com.br/… ), aby uzyskać więcej informacji. Mam nadzieję że to pomoże.
Enayat
Jak testujesz centralną bramę API i poszczególne usługi? Czy wykonujesz integrację lub mockujesz odpowiedź http?
Jaime Sangcap
7

W przypadku podejścia nr 2, w rzeczywistości jest to sposób, który wybrałem, ponieważ jest znacznie łatwiejszy niż ręczne utrzymywanie irytującej bramy API. W ten sposób możesz samodzielnie rozwijać swoje usługi. Ułatw sobie życie: P.

Jest kilka świetnych narzędzi do łączenia schematów w jeden, np. Graphql-weaver i graphql-tools apollo , których używam graphql-weaver, jest łatwy w użyciu i działa świetnie.

HFX
źródło
Używanie GraphQL w systemie Android jest konieczne, żebym utworzył plik .graphql ze wszystkimi zapytaniami? Czy mogę po prostu utworzyć je w kodzie bez tego pliku?
MauroAlexandro
1
@MauroAlexandro Nie jestem androidem, ale możesz mieć zapytania w różnych plikach. To bardziej problem projektowy. IMHO, wolę ten pierwszy :)
HFX
5

Od połowy 2019 r. Rozwiązanie dla pierwszego podejścia nosi teraz nazwę „ Schema Federationwymyśloną przez ludzi z Apollo (wcześniej było to często określane jako szycie GraphQL). Proponują również moduły @apollo/federationi @apollo/gatewaydo tego.

DODAJ: Należy pamiętać, że w przypadku Federacji schematu nie można modyfikować schematu na poziomie bramy. Więc dla każdego bitu, którego potrzebujesz w swoim schemacie, musisz mieć osobną usługę.

vanthome
źródło
ważne jest również, aby wiedzieć, że to rozwiązanie wymaga serwera Apollo, który jest nieco ograniczony w wersji bezpłatnej (maksymalnie 25 milionów zapytań miesięcznie)
Marx
0

Od 2019 r. Najlepszym sposobem jest pisanie mikrousług, które implementują specyfikację bramy apollo, a następnie sklejanie tych usług za pomocą bramy zgodnie z podejściem nr 1. Najszybszym sposobem zbudowania bramy jest obraz dockera, taki jak ten. Następnie użyj docker-compose, aby uruchomić wszystkie usługi jednocześnie:

version: '3'

services:
    service1:
        build: service1
    service2:
        build: service2
    gateway:
        ports:
            - 80:80
        image: xmorse/apollo-federation-gateway
        environment: 
            - CACHE_MAX_AGE=5
            - "FORWARD_HEADERS=Authorization, X-Custom-Header" # default is Authorization, pass '' to reset
            - URL_0=http://service1
            - URL_1=http://service2
Morse
źródło
0

Ze sposobu, w jaki jest to opisane w tym pytaniu, uważam, że użycie niestandardowej bramy API jako usługi orkiestracji może mieć duży sens w przypadku złożonych aplikacji ukierunkowanych na przedsiębiorstwa. GraphQL może być dobrym wyborem technologii dla tej usługi orkiestracji, przynajmniej w zakresie zapytań. Zaletą pierwszego podejścia (jeden schemat dla wszystkich mikrousług) jest możliwość łączenia danych z wielu mikrousług w jednym żądaniu. Może to być bardzo ważne, ale nie musi, w zależności od Twojej sytuacji. Jeśli interfejs GUI wywołuje jednoczesne renderowanie danych z wielu mikrousług, to podejście może uprościć kod klienta, tak że pojedyncze wywołanie może zwrócić dane odpowiednie do powiązania danych z elementami GUI takich struktur, jak Angular lub React. Ta zaleta nie dotyczy mutacji.

Wadą jest ścisłe powiązanie między interfejsami API danych a usługą orkiestracji. Wydania nie mogą już być atomowe. Jeśli powstrzymasz się od wprowadzania wstecznych zmian w interfejsach API danych, może to spowodować złożoność tylko podczas wycofywania wersji. Na przykład, jeśli masz zamiar wydać nowe wersje dwóch interfejsów API danych z odpowiednimi zmianami w usłudze orkiestracji i musisz wycofać jedną z tych wersji, ale nie drugą, i tak będziesz zmuszony wycofać wszystkie trzy.

W tym porównaniu GraphQL vs REST przekonasz się, że GraphQL nie jest tak wydajne jak RESTful API, więc nie polecałbym zastępowania REST przez GraphQL dla danych API.

Glenn
źródło
0

Na pytanie 1, Intuit potwierdził moc GraphQL kilka lat temu, kiedy ogłosił przejście na ekosystem One Intuit API ( https://www.slideshare.net/IntuitDeveloper/building-the-next-generation-of-quickbooks-app-integrations -quickbooks-connect-2017 ). Intuit wybrał podejście 1. Wada, o której wspomniałeś, w rzeczywistości uniemożliwia programistom wprowadzanie przełomowych zmian schematu, które mogłyby potencjalnie zakłócać działanie aplikacji klienckich.

GraphQL pomógł zwiększyć produktywność programistów na wiele sposobów.

  1. Projektując nową mikrousługę dla domeny, inżynierowie (zaplecze / frontend / udziałowcy) uzgadniają schemat dla jednostek domeny. Po zatwierdzeniu schematu jest on łączony ze schematem domeny głównej (uniwersalny) i wdrażany w Gateway. Inżynierowie frontendu mogą rozpocząć kodowanie aplikacji klienckich za pomocą tego schematu, podczas gdy inżynierowie zaplecza implementują tę funkcjonalność. Posiadanie jednego uniwersalnego schematu oznacza, że ​​nie ma dwóch mikrousług z nadmiarową funkcjonalnością.
  2. GraphQL pomógł aplikacjom klienckim stać się prostszymi i szybszymi. Chcesz pobierać dane z / aktualizować dane do wielu mikrousług? Wszystko, co muszą zrobić aplikacje klienckie, to wystrzelić JEDNO żądanie GraphQL, a warstwa abstrakcji API Gateway zajmie się pobieraniem i sortowaniem danych z wielu źródeł (mikrousług). Struktury open source, takie jak Apollo ( https://www.apollographql.com/ ), przyspieszyły tempo wdrażania GraphQL.

  3. Ponieważ urządzenia mobilne są pierwszym wyborem dla nowoczesnych aplikacji, ważne jest, aby projektować pod kątem mniejszych wymagań dotyczących przepustowości danych od zera. GraphQL pomaga, pozwalając aplikacjom klienckim na żądanie tylko określonych pól.

Na pytanie 2: stworzyliśmy niestandardową warstwę abstrakcji w API Gateway, która wie, która część schematu należy do której usługi (dostawcy). Gdy nadejdzie żądanie zapytania, warstwa abstrakcji przekazuje je do odpowiednich usług. Gdy usługa podstawowa zwróci odpowiedź, warstwa abstrakcji jest odpowiedzialna za zwrócenie żądanych pól.

Jednak obecnie istnieje kilka platform (serwer Apollo, graphql-yoga itp.), Które pozwalają szybko zbudować warstwę abstrakcji GraphQL.

Nacharya
źródło
0

Pracowałem z GraphQL i mikroserwisami

Opierając się na moim doświadczeniu, to, co działa dla mnie, to połączenie obu podejść w zależności od funkcjonalności / zastosowania, nigdy nie będę miał pojedynczej bramy, jak w podejściu 1 ... ale poniżej wykresu Graphql dla każdej mikrousługi jako podejścia 2.

Na przykład na podstawie obrazu odpowiedzi z Enayat, co bym zrobił w tym przypadku to mieć 3 bramki grafowe (nie 5 jak na obrazku)

wprowadź opis obrazu tutaj

  • Aplikacja (produkt, koszyk, wysyłka, zapasy, potrzebne / połączone z innymi usługami)

  • Zapłata

  • Użytkownik

W ten sposób musisz zwrócić szczególną uwagę na projekt niezbędnych / połączonych minimalnych danych ujawnionych z zależnych usług, takich jak token autoryzacji, identyfikator użytkownika, identyfikator płatności, status płatności.

Na przykład z mojego doświadczenia wynika, że ​​mam bramę "Użytkownik", w której GraphQL mam zapytania / mutacje użytkownika, logowanie, logowanie, wylogowanie, zmianę hasła, odzyskanie adresu e-mail, potwierdzenie adresu e-mail, usunięcie konta, edycję profilu, załadowanie zdjęcia , itd ... ten wykres sam w sobie jest dość duży !, jest oddzielony, ponieważ na końcu inne usługi / bramy dbają tylko o wynikowe informacje, takie jak identyfikator użytkownika, nazwa lub token.

W ten sposób łatwiej ...

  • Skaluj / wyłączaj różne węzły bram w zależności od ich użycia. (na przykład ludzie nie zawsze edytują swój profil lub płacą ... ale wyszukiwanie produktów może być używane częściej).

  • Gdy brama dojrzeje, rozrosnie się, zostanie rozpoznane użycie lub będziesz miał więcej wiedzy na temat domeny, możesz zidentyfikować, która część schematu może mieć własną bramę (... zdarzyło mi się z ogromnym schematem, który współdziała z repozytoriami git , Oddzieliłem bramę, która współdziała z repozytorium i zobaczyłem, że jedyne potrzebne / połączone informacje to ... ścieżka folderu i oczekiwana gałąź)

  • Historia twoich repozytoriów jest bardziej przejrzysta i możesz mieć repozytorium / programistę / zespół poświęcony bramie i związanym z nią mikrousługom.

AKTUALIZACJA:

Mam klaster kubernetes online, który używa tego samego podejścia, które opisałem tutaj, ze wszystkimi backendami używającymi GraphQL, wszystkie open source, tutaj jest główne repozytorium: https://github.com/vicjicaman/microservice-realm

To jest aktualizacja mojej odpowiedzi, ponieważ uważam, że lepiej jest, jeśli odpowiedź / podejście zawiera kopię zapasową kodu, który działa i można się z nią zapoznać / przejrzeć, mam nadzieję, że to pomoże.

Victor Jimenez
źródło
-3

Ponieważ architektura mikrousług nie ma odpowiedniej definicji, nie ma konkretnego modelu dla tego stylu, ale większość z nich będzie miała kilka istotnych cech.W przypadku architektury mikrousług każdą usługę można podzielić na pojedyncze małe komponenty, które można podzielić na indywidualnie dostosowywane i wdrażane bez wpływu na integralność aplikacji. Oznacza to, że możesz po prostu zmienić kilka usług bez konieczności ponownego wdrażania aplikacji poprzez tworzenie aplikacji niestandardowych mikrousług .

Demetrius Franco
źródło
Nawet jeśli brakuje „właściwej definicji”, jest to pojęcie dobrze zrozumiałe i wyraźnie odgraniczone w kontekście pytania. Poza tym twoja odpowiedź w ogóle nie odnosi się do pytania.
Roy Prins,
-7

Więcej o mikrousługach, myślę, że GraphQL może również działać idealnie w architekturze bezserwerowej. Nie używam GraphQL, ale mam własny podobny projekt . Używam go jako agregatora, który wywołuje i koncentruje wiele funkcji w jednym wyniku. Myślę, że możesz zastosować ten sam wzorzec dla GraphQL.

Giap Nguyen
źródło
2
Przepraszamy, ale to w ogóle nie dotyczy pytania PO. Pytanie dotyczy dwóch konkretnych podejść do korzystania z GraphQL. Lepiej byłoby to zamieścić jako komentarz.
tiomno