Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Wskazówka
Ta treść jest fragmentem eBooka "Architektura mikrousług .NET dla konteneryzowanych aplikacji .NET", dostępnego na .NET Docs lub jako bezpłatny plik PDF do pobrania i czytania w trybie offline.
W architekturze mikrousług każda mikrousług uwidacznia zestaw (zazwyczaj) precyzyjnych punktów końcowych. Ten fakt może mieć wpływ na komunikację między klientem a mikrousługą, jak wyjaśniono w tej sekcji.
Bezpośrednia komunikacja między klientem a mikrousługą
Możliwe jest użycie bezpośredniej architektury komunikacji między klientem a mikrousługą. W tym podejściu aplikacja kliencka może wysyłać żądania bezpośrednio do niektórych mikrousług, jak pokazano na rysunku 4–12.
Rysunek 4–12. Używanie bezpośredniej architektury komunikacji między klientem a mikrousługą
W tym podejściu każda mikrousługa ma publiczny punkt końcowy, czasami z innym portem TCP dla każdej mikrousługi. Przykładem adresu URL dla określonej usługi może być następujący adres URL na platformie Azure:
http://eshoponcontainers.westus.cloudapp.azure.com:88/
W środowisku produkcyjnym opartym na klastrze ten adres URL będzie odpowiadać modułowi równoważenia obciążenia używanemu w obrębie klastra, który następnie rozdziela żądania pomiędzy mikrousługi. W środowiskach produkcyjnych możesz mieć kontroler dostarczania aplikacji (ADC), taki jak usługa Azure Application Gateway między mikrousługami a Internetem. Ta warstwa działa jako przezroczysta warstwa, która nie tylko wykonuje równoważenie obciążenia, ale zabezpiecza usługi, oferując kończenie żądań SSL. Takie podejście zmniejsza obciążenie hostów poprzez przenoszenie wymagającego intensywnego użycia CPU kończenia sesji SSL oraz innych obowiązków związanych z routingiem do usługi Azure Application Gateway. W każdym razie, load balancer i kontroler dostępu aplikacji (ADC) są przezroczyste z punktu widzenia architektury aplikacji logicznej.
Bezpośrednia architektura komunikacji między klientem a mikrousługą może być wystarczająca dla małej aplikacji opartej na mikrousługach, zwłaszcza jeśli aplikacja kliencka jest aplikacją internetową po stronie serwera, na przykład aplikacją MVC ASP.NET. Jednak podczas tworzenia dużych i złożonych aplikacji opartych na mikrousługach (na przykład w przypadku obsługi kilkudziesięciu typów mikrousług), a zwłaszcza gdy aplikacje klienckie są zdalnymi aplikacjami mobilnymi lub aplikacjami internetowymi SPA, to podejście ma kilka problemów.
Podczas tworzenia dużej aplikacji na podstawie mikrousług należy wziąć pod uwagę następujące pytania:
- Jak aplikacje klienckie mogą zminimalizować liczbę żądań do zaplecza i zmniejszyć komunikację z wieloma mikrousługami?
Interakcja z wieloma mikrousługami w celu utworzenia jednego ekranu interfejsu użytkownika zwiększa liczbę rund w Internecie. Takie podejście zwiększa opóźnienie i złożoność po stronie interfejsu użytkownika. W idealnym przypadku odpowiedzi powinny być efektywnie agregowane po stronie serwera. Takie podejście zmniejsza opóźnienie, ponieważ wiele fragmentów danych wraca równolegle, a niektóre interfejsy użytkownika mogą wyświetlać dane natychmiast po ich gotowości.
- Jak można obsługiwać przekrojowe kwestie, takie jak autoryzacja, przekształcenia danych i dynamiczne kierowanie żądań?
Implementowanie zabezpieczeń i zagadnień obejmujących wiele zagadnień, takich jak zabezpieczenia i autoryzacja dla każdej mikrousługi, może wymagać znacznego nakładu pracy programistycznej. Możliwe jest użycie tych usług na hoście platformy Docker lub klastrze wewnętrznym w celu ograniczenia bezpośredniego dostępu do nich z zewnątrz oraz zaimplementowania tych problemów krzyżowych w scentralizowanym miejscu, na przykład w usłudze API Gateway.
- W jaki sposób aplikacje klienckie mogą komunikować się z usługami korzystającymi z protokołów niezwiązanych z Internetem?
Protokoły używane po stronie serwera (takie jak protokół AMQP lub protokoły binarne) nie są obsługiwane w aplikacjach klienckich. W związku z tym żądania muszą być wykonywane za pośrednictwem protokołów, takich jak HTTP/HTTPS, i tłumaczone na inne protokoły później. Podejście man-in-the-middle może pomóc w tej sytuacji.
- Jak można kształtować fasadę specjalnie utworzoną dla aplikacji mobilnych?
Interfejs API wielu mikrousług może nie być dobrze zaprojektowany pod kątem potrzeb różnych aplikacji klienckich. Na przykład potrzeby aplikacji mobilnej mogą być inne niż potrzeby aplikacji internetowej. W przypadku aplikacji mobilnych może być konieczne jeszcze większe zoptymalizowanie, aby odpowiedzi na dane były bardziej wydajne. Możesz to zrobić, agregując dane z wielu mikrousług i zwracając pojedynczy zestaw danych, a czasami eliminując wszelkie dane w odpowiedzi, które nie są potrzebne przez aplikację mobilną. Oczywiście możesz skompresować te dane. Ponownie fasada lub interfejs API między aplikacją mobilną a mikrousługami mogą być wygodne w tym scenariuszu.
Dlaczego warto rozważyć użycie bram interfejsu API zamiast bezpośredniej komunikacji między klientem a mikrousługą
W architekturze mikrousług aplikacje klienckie zwykle muszą korzystać z funkcji z więcej niż jednej mikrousługi. Jeśli korzystanie jest realizowane bezpośrednio, klient musi sobie radzić z wieloma wywołaniami do punktów końcowych mikrousługi. Co się stanie w przypadku rozwoju aplikacji i wprowadzenia nowych mikrousług lub zaktualizowania istniejących mikrousług? Jeśli aplikacja ma wiele mikrousług, obsługa tak wielu punktów końcowych z aplikacji klienckich może być koszmarem. Ponieważ aplikacja kliencka zostanie połączona z tymi wewnętrznymi punktami końcowymi, rozwój mikrousług w przyszłości może spowodować duży wpływ na aplikacje klienckie.
W związku z tym posiadanie pośredniej warstwy (bramy) może być wygodne dla aplikacji opartych na mikrousługach. Jeśli nie masz bram API, aplikacje klienckie muszą wysyłać żądania bezpośrednio do mikrousług, co powoduje problemy, takie jak następujące:
Sprzęganie: bez wzorca usługi API Gateway aplikacje klienckie są powiązane z wewnętrznymi mikrousługami. Aplikacje klienckie muszą wiedzieć, jak wiele obszarów aplikacji jest rozłożonych w mikrousługach. Podczas rozwijania i refaktoryzacji wewnętrznych mikrousług, te działania wpływają na konserwację, ponieważ wprowadzają zmiany powodujące niezgodność w aplikacjach klienckich, gdyż aplikacje klienckie bezpośrednio odwołują się do wewnętrznych mikrousług. Aplikacje klienckie muszą być często aktualizowane, co utrudnia rozwijanie rozwiązania.
Zbyt wiele rund: pojedyncza strona/ekran w aplikacji klienckiej może wymagać kilku wywołań wielu usług. Takie podejście może spowodować wiele rund sieci między klientem a serwerem, dodając znaczne opóźnienie. Agregacja obsługiwana na poziomie pośrednim może zwiększyć wydajność i środowisko użytkownika aplikacji klienckiej.
Problemy z zabezpieczeniami: bez bramy wszystkie mikrousługi muszą być widoczne dla "świata zewnętrznego", co powoduje, że atak jest większy niż w przypadku ukrycia wewnętrznych mikrousług, które nie są bezpośrednio używane przez aplikacje klienckie. Tym mniejsza jest powierzchnia ataku, tym bezpieczniejsza może być aplikacja.
Problemy przekrojowe: Każda publicznie dostępna mikrousługa musi obsługiwać takie kwestie jak autoryzacja i protokół SSL. W wielu sytuacjach te obawy mogą być obsługiwane w jednej warstwie, dzięki czemu wewnętrzne mikrousługi są uproszczone.
Jaki jest wzorzec bramy interfejsu API?
Podczas projektowania i kompilowania dużych lub złożonych aplikacji opartych na mikrousługach z wieloma aplikacjami klienckimi dobrym rozwiązaniem może być brama interfejsu API. Ten wzorzec jest usługą, która zapewnia pojedynczy punkt wejścia dla niektórych grup mikrousług. Jest on podobny do wzorca fasady z projektu zorientowanego obiektowo, ale w tym przypadku jest częścią systemu rozproszonego. Wzorzec bramy interfejsu API jest również czasami nazywany "zapleczem frontonu" (BFF), ponieważ tworzysz go podczas myślenia o potrzebach aplikacji klienckiej.
W związku z tym brama interfejsu API znajduje się między aplikacjami klienckimi a mikrousługami. Działa jako serwer proxy odwrócony, rozsyłając żądania od klientów do usług. Może również udostępniać inne funkcje krzyżowe, takie jak uwierzytelnianie, kończenie żądań SSL i pamięć podręczna.
Rysunek 4–13 pokazuje, jak niestandardowa brama interfejsu API może zmieścić się w uproszczonej architekturze opartej na mikrousługach z zaledwie kilkoma mikrousługami.
Rysunek 4–13. Używanie bramy interfejsu API zaimplementowanej jako usługa niestandardowa
Aplikacje łączą się z pojedynczym punktem końcowym, bramą interfejsu API, który jest skonfigurowany do przekazywania żądań do poszczególnych mikrousług. W tym przykładzie brama interfejsu API zostanie zaimplementowana jako niestandardowa usługa ASP.NET Core WebHost działająca jako kontener.
Ważne jest, aby podkreślić, że na tym diagramie będziesz używać jedną niestandardową usługę API Gateway, która obsługuje wiele różnych aplikacji klienckich. Może to być ważne ryzyko, ponieważ usługa API Gateway będzie rozwijać się i ewoluować w oparciu o wiele różnych wymagań aplikacji klienckich. Ostatecznie rozrośnie się on ze względu na te różne potrzeby i efektywnie może stać się podobny do aplikacji monolitycznej lub usługi monolitycznej. Dlatego zdecydowanie zaleca się podzielenie bramy API na wiele usług lub wiele mniejszych bram API, na przykład po jednej na typ formatu aplikacji klienckiej.
Podczas implementowania wzorca bramy interfejsu API należy zachować ostrożność. Zazwyczaj nie jest dobrym pomysłem, aby jedna brama interfejsu API agreguje wszystkie wewnętrzne mikrousługi aplikacji. Jeśli tak, działa jako agregator monolityczny lub orkiestrator i narusza autonomię mikrousług przez sprzężenie wszystkich mikrousług.
W związku z tym bramy interfejsu API powinny być segregowane na podstawie granic biznesowych i aplikacji klienckich, a nie działać jako pojedynczy agregator dla wszystkich wewnętrznych mikrousług.
Podczas dzielenia warstwy Gateway API na kilka bram API, jeśli aplikacja posiada wiele aplikacji klienckich, może to stanowić kluczowy punkt odniesienia przy określaniu typów tych bram, umożliwiając stworzenie odrębnej fasady dla potrzeb każdej aplikacji klienckiej. Ten przypadek jest wzorcem o nazwie "Backend for Frontend" (BFF), w którym każda brama interfejsu API może zapewnić inny interfejs API dostosowany do każdego typu aplikacji klienckiej, możliwe, że nawet na podstawie formatu urządzenia klienckiego, przez zaimplementowanie określonego kodu adaptera, który pod spodem wywołuje wiele wewnętrznych mikrousług, jak pokazano na poniższej ilustracji.
Rysunek 4–13.1. Używanie wielu niestandardowych bram API
Rysunek 4–13.1 przedstawia bramy interfejsu API podzielone według typu klienta; jeden dla klientów mobilnych i jeden dla klientów internetowych. Tradycyjna aplikacja internetowa łączy się z mikrousługą MVC korzystającą z internetowej bramy interfejsu API. W przykładzie przedstawiono uproszczoną architekturę z wieloma precyzyjnymi bramami interfejsu API. W takim przypadku zidentyfikowane granice dla każdego API Gateway są oparte wyłącznie na wzorcu "Backend for Frontend" (BFF), zatem tylko na API wymaganym dla aplikacji klienckiej. Jednak w większych aplikacjach należy również wykraczać poza standardowe rozwiązania i utworzyć inne bramy interfejsu API oparte na granicach biznesowych jako drugi punkt odniesienia w projektowaniu.
Główne funkcje we wzorcu API Gateway
Brama interfejsu API może oferować wiele funkcji. W zależności od produktu może oferować bogatsze lub prostsze funkcje, jednak najważniejsze i podstawowe funkcje dla każdej bramy api są następującymi wzorcami projektowymi:
Zwrotny routing serwera proxy lub bramy. Brama API oferuje zwrotny serwer proxy do przekierowywania lub kierowania żądań (routing L7, zazwyczaj żądań HTTP) do punktów końcowych wewnętrznych mikrousług. Brama udostępnia pojedynczy punkt końcowy lub adres URL dla aplikacji klienckich, a następnie wewnętrznie mapuje żądania na grupę wewnętrznych mikrousług. Ta funkcja routingu pomaga oddzielić aplikacje klienckie od mikrousług, ale jest również wygodna podczas modernizacji monolitycznego API. Brama API jest umieszczona pomiędzy monolitycznym API a aplikacjami klienckimi, dzięki czemu można dodawać nowe API jako nowe mikrousługi, jednocześnie korzystając ze starszego, monolitycznego API, dopóki nie zostanie ono podzielone na wiele mikrousług w przyszłości. Ze względu na bramę interfejsu API aplikacje klienckie nie będą zauważać, czy używane interfejsy API są implementowane jako wewnętrzne mikrousługi lub monolityczny interfejs API, a co ważniejsze, podczas ewolucji i refaktoryzacji monolitycznego interfejsu API do mikrousług dzięki routingowi usługi API Gateway aplikacje klienckie nie będą mieć wpływu na żadną zmianę identyfikatora URI.
Aby uzyskać więcej informacji, zobacz Wzorzec routingu bramy.
Agregacja żądań. W ramach wzorca bramy można agregować wiele żądań klienta (zazwyczaj żądań HTTP) przeznaczonych dla wielu wewnętrznych mikrousług w jednym żądaniu klienta. Ten wzorzec jest szczególnie wygodny, gdy strona/ekran klienta potrzebuje informacji z kilku mikrousług. Dzięki temu aplikacja kliencka wysyła pojedyncze żądanie do bramy interfejsu API, która wysyła kilka żądań do wewnętrznych mikrousług, a następnie agreguje wyniki i wysyła wszystko z powrotem do aplikacji klienckiej. Główną korzyścią i celem tego wzorca projektowego jest zmniejszenie rozmów między aplikacjami klienckimi a interfejsem API zaplecza, co jest szczególnie ważne w przypadku zdalnych aplikacji z centrum danych, w którym działają mikrousługi, takie jak aplikacje mobilne lub żądania pochodzące z aplikacji SPA pochodzących z języka JavaScript w przeglądarkach zdalnych klienta. W przypadku zwykłych aplikacji internetowych wykonujących żądania w środowisku serwera (takich jak aplikacja internetowa ASP.NET Core MVC), ten wzorzec nie jest tak ważny, ponieważ opóźnienie jest znacznie mniejsze niż w przypadku zdalnych aplikacji klienckich.
W zależności od używanego produktu usługi API Gateway może być możliwe przeprowadzenie tej agregacji. Jednak w wielu przypadkach bardziej elastyczne jest tworzenie mikrousług agregacji w zakresie bramy interfejsu API, więc można zdefiniować agregację w kodzie (czyli kod C#):
Aby uzyskać więcej informacji, zobacz Schemat agregacji bramy.
Problemy związane z przecięciem krzyżowym lub odciążanie bramy. W zależności od funkcji oferowanych przez poszczególne produkty API Gateway, można odciążyć funkcje poszczególnych mikrousług do bramki, co upraszcza implementację każdej mikrousługi, konsolidując przekrojowe aspekty w jednej warstwie. Takie podejście jest szczególnie wygodne w przypadku wyspecjalizowanych funkcji, które mogą być złożone w celu prawidłowego wdrożenia w każdej wewnętrznej mikrousłudze, takiej jak następujące funkcje:
- Uwierzytelnianie i autoryzacja
- Integracja odnajdywania usług
- Buforowanie odpowiedzi
- Zasady ponawiania, wyłącznik i QoS
- Ograniczanie szybkości i ograniczanie przepustowości
- Równoważenie obciążenia
- Rejestrowanie, śledzenie, korelacja
- Nagłówki, ciągi zapytaniowe i przekształcenia roszczeń
- Lista dozwolonych adresów IP
Aby uzyskać więcej informacji, zobacz Wzorzec odciążania bramy.
Używanie produktów z funkcjami usługi API Gateway
W zależności od implementacji, produkty API Gateway mogą oferować wiele dodatkowych ogólnych aspektów. Przyjrzymy się tutaj:
Azure API Management
Usługa Azure API Management (jak pokazano na rysunku 4–14) nie tylko rozwiązuje potrzeby usługi API Gateway, ale udostępnia funkcje takie jak zbieranie szczegółowych informacji z interfejsów API. Jeśli korzystasz z rozwiązania do zarządzania interfejsami API, brama API jest tylko częścią tego pełnego rozwiązania do zarządzania interfejsami API.
Rysunek 4–14. Korzystanie z usługi Azure API Management dla bramy interfejsu API
Usługa Azure API Management rozwiązuje potrzeby bramy interfejsu API i zarządzania, takie jak rejestrowanie, zabezpieczenia, pomiary itp. W takim przypadku w przypadku korzystania z produktu takiego jak Usługa Azure API Management fakt, że może istnieć jedna brama interfejsu API, nie jest tak ryzykowna, ponieważ tego rodzaju bramy interfejsu API są "cieńsze", co oznacza, że nie implementujesz niestandardowego kodu języka C#, który może ewoluować w kierunku składnika monolitycznego.
Produkty API Gateway zazwyczaj działają jak odwrotny serwer proxy dla komunikacji przychodzącej. W tej jednolitej warstwie można filtrować interfejsy API z wewnętrznych mikrousług oraz stosować autoryzację do opublikowanych interfejsów API.
Szczegółowe informacje dostępne w systemie usługi API Management pomagają zrozumieć, jak są używane interfejsy API i jak działają. Wykonują one te działania, umożliwiając wyświetlanie raportów analizy w czasie rzeczywistym i identyfikowanie trendów, które mogą mieć wpływ na Twoją firmę. Ponadto możesz mieć dzienniki dotyczące działań dotyczących żądań i odpowiedzi w celu dalszej analizy online i offline.
Usługa Azure API Management umożliwia zabezpieczanie interfejsów API przy użyciu klucza, tokenu i filtrowania adresów IP. Te funkcje umożliwiają wymuszanie elastycznych i precyzyjnych przydziałów i limitów szybkości, modyfikowanie kształtu i zachowania interfejsów API przy użyciu zasad oraz zwiększanie wydajności dzięki buforowaniu odpowiedzi.
W tym przewodniku i przykładowej aplikacji referencyjnej (eShopOnContainers) architektura jest ograniczona do prostszej i niestandardowej architektury konteneryzowanej, aby skupić się na zwykłych kontenerach bez używania produktów PaaS, takich jak Usługa Azure API Management. Jednak w przypadku dużych aplikacji opartych na mikrousługach wdrożonych na platformie Microsoft Azure zachęcamy do oceny usługi Azure API Management jako podstawy dla bram interfejsu API w środowisku produkcyjnym.
Ocelot
Ocelot to uproszczona brama interfejsu API zalecana w przypadku prostszych podejść. Ocelot to oparta na platformie .NET Core brama interfejsu API typu open source, szczególnie dla architektur mikrousług, które wymagają ujednoliconych punktów wejścia do swoich systemów. Jest lekki, szybki i skalowalny oraz zapewnia routing i uwierzytelnianie wśród wielu innych funkcji.
Głównym powodem wybrania rozwiązania Ocelot dla aplikacji referencyjnej eShopOnContainers 2.0 jest to, że rozwiązanie Ocelot jest uproszczoną bramą interfejsu API platformy .NET Core, którą można wdrożyć w tym samym środowisku wdrażania aplikacji, w którym wdrażasz mikrousługi/kontenery, takie jak host platformy Docker, platforma Kubernetes itp. A ponieważ jest oparta na platformie .NET Core, jest to międzyplatformowa platforma umożliwiająca wdrażanie w systemie Linux lub Windows.
Poprzednie diagramy, które przedstawiają niestandardowe bramy interfejsu API działające w kontenerach, pokazują dokładnie, jak można uruchomić Ocelot w aplikacjach opartych na kontenerach i mikrousługach.
Ponadto na rynku dostępnych jest wiele innych produktów oferujących funkcjonalności bram API, takie jak Apigee, Kong, MuleSoft, WSO2 oraz inne rozwiązania, takie jak Linkerd i Istio, które zapewniają funkcje kontrolera ingress siatki usług.
Po początkowych sekcjach objaśnień architektury i wzorców w następnych sekcjach opisano sposób implementowania bram interfejsu API za pomocą rozwiązania Ocelot.
Wady wzorca bramy interfejsu API
Najważniejszą wadą jest to, że przy wdrażaniu bramy interfejsu API wiążesz tę warstwę do wewnętrznych mikrousług. Takie sprzężenie może spowodować poważne problemy z aplikacją. Clemens Vaster, architekt zespołu Azure Service Bus, nazywa te potencjalne trudności „nowym ESB” podczas sesji "Obsługa komunikatów i mikrousług" na GOTO 2016.
Użycie bramy API mikrousług tworzy dodatkowy, możliwy punkt jednopunktowej awarii.
Brama interfejsu API może spowodować wydłużenie czasu odpowiedzi ze względu na dodatkowe wywołanie sieciowe. Jednak to dodatkowe wywołanie zwykle ma mniejszy wpływ niż interfejs klienta, który jest nadmiernie rozmowny, bezpośrednio wywołując wewnętrzne mikrousługi.
Jeśli brama API Gateway nie zostanie prawidłowo rozszerzona, może stać się wąskim gardłem.
Brama interfejsu API wymaga dodatkowych kosztów programowania i przyszłej konserwacji, jeśli obejmuje niestandardową logikę i agregację danych. Deweloperzy muszą zaktualizować bramę interfejsu API, aby uwidocznić punkty końcowe każdej mikrousługi. Ponadto zmiany w implementacji wewnętrznych mikrousług mogą prowadzić do zmian w kodzie na poziomie bramy interfejsu API. Jeśli jednak brama interfejsu API stosuje tylko zabezpieczenia, rejestrowanie i przechowywanie wersji (tak jak w przypadku korzystania z usługi Azure API Management), ten dodatkowy koszt programowania może nie mieć zastosowania.
Jeśli usługa API Gateway jest opracowywana przez jeden zespół, może wystąpić wąskie gardło programistyczne. Ten aspekt jest kolejnym powodem, dla którego lepszym rozwiązaniem jest posiadanie kilku precyzyjnych bram interfejsów API, które odpowiadają na różne potrzeby klientów. Bramę interfejsu API można również podzielić wewnętrznie na wiele obszarów lub warstw należących do różnych zespołów pracujących nad wewnętrznymi mikrousługami.
Dodatkowe zasoby
Chris Richardson. Wzorzec: brama API / zaplecze dla Front-End
https://microservices.io/patterns/apigateway.htmlWzorzec bramy interfejsu API
https://learn.microsoft.com/azure/architecture/microservices/gatewayWzorzec agregacji i kompozycji
https://microservices.io/patterns/data/api-composition.htmlAzure API Management
https://azure.microsoft.com/services/api-management/Udi Dahan. Kompozycja zorientowana na usługi
https://udidahan.com/2014/07/30/service-oriented-composition-with-video/Clemens Vasters. Komunikaty i mikrousługi na GOTO 2016 (wideo)
https://www.youtube.com/watch?v=rXi5CLjIQ9kUsługa API Gateway w programie NutShell (seria samouczków ASP.NET Core API Gateway)
https://www.pogsdotnet.com/2018/08/api-gateway-in-nutshell.html