Megosztás a következőn keresztül:


API-átjárók implementálása az Ocelottal

Jótanács

Ez a tartalom egy részlet a '.NET Microservices Architecture for Containerized .NET Applications' című eBook-ból, amely elérhető a .NET Docs oldalon, vagy ingyenesen letölthető PDF formátumban, amely offline módban is olvasható.

.NET mikroszolgáltatások architektúrája konténerizált .NET alkalmazásokhoz e-könyv borító miniatűr.

Fontos

Az eShopOnContainers referencia mikroszolgáltatási alkalmazás jelenleg az Envoy által biztosított funkciókat használja az API Gateway implementálásához a korábbi hivatkozott Ocelot helyett. Az Envoy beépített WebSocket protokoll támogatása miatt döntöttünk így, amit az eShopOnContainersben megvalósított új gRPC szolgáltatások közötti kommunikáció igényel. Ezt a szakaszt azonban megtartottuk az útmutatóban, így az Ocelot egyszerű, képes és egyszerűsített API Gatewayként tekinthető, amely éles környezetben használható. Emellett a legújabb Ocelot-verzió kompatibilitástörő változást is tartalmaz a json-sémáján. Fontolja meg az Ocelot < 16.0.0-s verziójának használatát, vagy használja a kulcsútvonalakat a ReRoutes helyett.

API-átjárók tervezése és építészeti kialakítása

Az alábbi architektúradiagram bemutatja, hogyan implementálták az API Gatewayeket az Ocelottal az eShopOnContainersben.

Az eShopOnContainers architektúrát bemutató ábra.

6-28. ábra. eShopOnContainers architektúra API-átjárókkal

Ez a diagram bemutatja, hogy az egész alkalmazás hogyan van üzembe helyezve egyetlen Docker-gazdagépen vagy fejlesztői PC-ben a "Docker for Windows" vagy a "Docker for Mac" használatával. Azonban bármelyik orchestrátorba való üzembe helyezés hasonló lenne, és az ábrán bármelyik konténer felskálázható az orchestrátorban.

Emellett az infrastruktúra-eszközöket, például az adatbázisokat, a gyorsítótárat és az üzenetközvetítőket ki kell tölteni a vezénylőből, és magas rendelkezésre állású infrastruktúra-rendszerekbe kell üzembe helyezni, például az Azure SQL Database-ben, az Azure Cosmos DB-ben, az Azure Redisben, az Azure Service Busban vagy bármely helyszíni HA-fürtözési megoldásban.

Ahogy azt a diagramon is láthatja, a több API Gateway használatával több fejlesztői csapat is önálló lehet (ebben az esetben marketingfunkciók és vásárlási funkciók) a mikroszolgáltatásaik és saját kapcsolódó API-átjárók fejlesztésekor és üzembe helyezésekor.

Ha egyetlen monolitikus API-átjáróval rendelkezik, amely egyetlen pontot jelentene, amelyet több fejlesztői csapat is frissítene, ami az összes mikroszolgáltatást összekapcsolhatja az alkalmazás egyetlen részével.

A kialakításban sokkal tovább haladva néha egy finom szemcsés API Gateway a választott architektúrától függően egyetlen üzleti mikroszolgáltatásra is korlátozható. Ha az API Gateway határait az üzlet vagy a tartomány szabja meg, az segít a jobb tervezésben.

Az API Gateway-szint finom részletessége például különösen hasznos lehet a mikroszolgáltatásokon alapuló összetettebb felhasználói felületi alkalmazások esetében, mivel a részletes API Gateway fogalma hasonló a felhasználói felületi összetételű szolgáltatáshoz.

Az előző szakaszban részletesebben is bemutatjuk, hogyan hozhat létre összetett felhasználói felületet mikroszolgáltatások alapján.

Kulcsfontosságú szempont, hogy sok közepes és nagy méretű alkalmazás esetében az egyénileg létrehozott API Gateway-termék használata általában jó módszer, de nem egyetlen monolitikus aggregátorként vagy egyedi központi egyéni API Gatewayként, kivéve, ha az API Gateway több független konfigurációs területet tesz lehetővé a több fejlesztési csapat számára, amelyek autonóm mikroszolgáltatásokat hoznak létre.

Minta mikroszolgáltatások/tárolók az API-átjárókon keresztüli átirányításhoz

Az eShopOnContainers például körülbelül hat belső mikroszolgáltatás-típussal rendelkezik, amelyeket közzé kell tenni az API-átjárókon keresztül, ahogy az alábbi képen is látható.

Képernyőkép a Szolgáltatások mappa almappáiról.

6–29. ábra. Mikroszolgáltatási mappák az eShopOnContainers megoldásban a Visual Studióban

Az Identity Service-t illetően a tervezés során kimaradt az API Gateway útválasztásából, mivel ez az egyetlen keresztirányú probléma a rendszerben, bár az Ocelottal az átirányítási listák részeként is felvehető.

Ezek a szolgáltatások jelenleg ASP.NET Core Webes API-szolgáltatásokként vannak implementálva, ahogy a kódból is látható. Koncentráljunk az egyik mikroszolgáltatásra, például a katalógus mikroszolgáltatási kódjára.

A Catalog.API projekt tartalmát megjelenítő Megoldáskezelő képernyőképe.

6–30. ábra. Minta webes API-mikroszolgáltatás (katalógus mikroszolgáltatás)

Láthatja, hogy a Katalógus mikroszolgáltatás egy tipikus ASP.NET Core Web API-projekt, amely számos vezérlővel és metódussal rendelkezik, például az alábbi kódban.

[HttpGet]
[Route("items/{id:int}")]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
[ProducesResponseType(typeof(CatalogItem),(int)HttpStatusCode.OK)]
public async Task<IActionResult> GetItemById(int id)
{
    if (id <= 0)
    {
        return BadRequest();
    }
    var item = await _catalogContext.CatalogItems.
                                          SingleOrDefaultAsync(ci => ci.Id == id);
    //…

    if (item != null)
    {
        return Ok(item);
    }
    return NotFound();
}

A HTTP-kérés a mikroszolgáltatás-adatbázishoz hozzáférő C#-kódot és minden további szükséges műveletet futtat.

Ami a mikroszolgáltatás URL-címét illeti, amikor a tárolók a helyi fejlesztőszámítógépen (helyi Docker-gazdagépen) vannak üzembe helyezve, minden mikroszolgáltatás tárolója mindig rendelkezik egy belső porttal (általában a 80-as porttal) a dockerfile-ban, ahogyan az alábbi dockerfile esetében is:

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80

A kódban látható 80-os port belső a Docker-gazdagépen belül, így az ügyfélalkalmazások nem tudják elérni.

Az ügyfélalkalmazások csak a telepítéskor közzétett külső portokat érhetik el (ha vannak ilyenek).docker-compose

Ezeket a külső portokat nem szabad közzétenni éles környezetben való üzembe helyezéskor. Ezért érdemes az API Gatewayt használni, hogy elkerülje az ügyfélalkalmazások és a mikroszolgáltatások közötti közvetlen kommunikációt.

A fejlesztés során azonban közvetlenül szeretné elérni a mikroszolgáltatást/tárolót, és a Swaggeren keresztül futtatni. Ezért az eShopOnContainersben a külső portok akkor is meg vannak adva, ha az API Gateway vagy az ügyfélalkalmazások nem fogják használni őket.

Íme egy példa a docker-compose.override.yml katalógus mikroszolgáltatás fájljára:

catalog-api:
  environment:
    - ASPNETCORE_ENVIRONMENT=Development
    - ASPNETCORE_URLS=http://0.0.0.0:80
    - ConnectionString=YOUR_VALUE
    - ... Other Environment Variables
  ports:
    - "5101:80"   # Important: In a production environment you should remove the external port (5101) kept here for microservice debugging purposes.
                  # The API Gateway redirects and access through the internal port (80).

Láthatja, hogy a docker-compose.override.yml konfigurációban a katalógustároló belső portja a 80-as port, a külső hozzáférés portja azonban 5101. Ezt a portot azonban az alkalmazás nem használhatja API Gateway használatakor, csak a katalógus mikroszolgáltatásának hibakeresésére, futtatására és tesztelésére.

Általában nem a docker-compose használatával helyezünk üzembe egy éles környezetben, mert a mikroszolgáltatásokhoz megfelelő éles környezet egy olyan orchesztráló, mint a Kubernetes vagy a Service Fabric. Ezeken a környezeteken való üzembe helyezéskor különböző konfigurációs fájlokat használ, amelyekben nem fog közvetlenül közzétenni külső portot a mikroszolgáltatásokhoz, de mindig az API Gateway fordított proxyját fogja használni.

Futtassa a katalógus mikroszolgáltatását a helyi Docker-gazdagépen. Futtassa a teljes eShopOnContainers megoldást a Visual Studio alkalmazásból (ez az összes szolgáltatást futtatja a docker-compose fájlokban), vagy indítsa el a Katalógus mikroszolgáltatást a következő docker-compose paranccsal a CMD vagy PowerShell terminálon, abban a mappában, ahol a docker-compose.yml és docker-compose.override.yml található.

docker-compose run --service-ports catalog-api

Ez a parancs csak a catalog-api szolgáltatástárolót és a docker-compose.yml megadott függőségeket futtatja. Ebben az esetben az SQL Server-tároló és a RabbitMQ-tároló.

Ezután közvetlenül elérheti a katalógus mikroszolgáltatást, és megtekintheti annak metódusait a Swagger felhasználói felületén keresztül, amely közvetlenül ezen a "külső" porton keresztül érhető el, ebben az esetben http://host.docker.internal:5101/swagger:

Képernyőkép a Swagger felhasználói felületéről a Catalog.API REST API-val.

6–31. ábra. A katalógus mikroszolgáltatásának tesztelése a Swagger felhasználói felületével

Ezen a ponton beállíthat egy töréspontot c#-kódban a Visual Studióban, tesztelheti a mikroszolgáltatást a Swagger felhasználói felületén közzétett metódusokkal, és végül mindent megtisztíthat a docker-compose down paranccsal.

A mikroszolgáltatással – ebben az esetben az 5101 külső porton keresztül – történő közvetlen hozzáférésű kommunikáció pontosan az, amit el akar kerülni az alkalmazásban. Ezt elkerülheti az API Gateway (Ocelot, ebben az esetben) további közvetettségi szintjének beállításával. Így az ügyfélalkalmazás nem fog közvetlenül hozzáférni a mikroszolgáltatáshoz.

API-átjárók implementálása az Ocelottal

Az Ocelot alapvetően egy olyan köztes szoftverkészlet, amelyet egy adott sorrendben alkalmazhat.

Az Ocelot csak ASP.NET Core használatára lett tervezve. A csomag legújabb verziója a 18.0, amely a .NET 6-ot célozza, ezért nem alkalmas .NET-keretrendszer-alkalmazásokhoz.

Az Ocelotot és annak függőségeit az ASP.NET Core-projektben az Ocelot NuGet-csomagjával telepítheti a Visual Studióból.

Install-Package Ocelot

Az eShopOnContainers api Gateway-implementációja egy egyszerű ASP.NET Core WebHost-projekt, és az Ocelot köztes szoftvere kezeli az API Gateway összes funkcióját, ahogyan az alábbi képen látható:

Képernyőkép a Megoldáskezelőről, amelyen az Ocelot API Gateway-projekt látható.

6–32. ábra. Az OcelotApiGw alapprojekt az eShopOnContainersben

Ez a ASP.NET Core WebHost-projekt két egyszerű fájlból áll: Program.cs és Startup.cs.

A Program.cs csak létre kell hoznia és konfigurálnia kell a tipikus ASP.NET Core BuildWebHostot.

namespace OcelotApiGw
{
    public class Program
    {
        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args)
        {
            var builder = WebHost.CreateDefaultBuilder(args);

            builder.ConfigureServices(s => s.AddSingleton(builder))
                    .ConfigureAppConfiguration(
                          ic => ic.AddJsonFile(Path.Combine("configuration",
                                                            "configuration.json")))
                    .UseStartup<Startup>();
            var host = builder.Build();
            return host;
        }
    }
}

Az Ocelot számára fontos pont az a configuration.json fájl, amelyet a AddJsonFile() metóduson keresztül kell biztosítania az építő számára. Itt configuration.json adhatja meg az ÖSSZES API Gateway ReRoutes-t, vagyis az adott portokkal rendelkező külső végpontokat és a korrelált belső végpontokat, amelyek általában különböző portokat használnak.

{
    "ReRoutes": [],
    "GlobalConfiguration": {}
}

A konfigurációnak két szakasza van. Egy ReRoutes-tömb és egy GlobalConfiguration. A ReRoutes azok az objektumok, amelyek közlik az Ocelot-nak, hogyan kell kezelni egy felsőbb rétegbeli kérést. A globális konfiguráció lehetővé teszi a ReRoute-beállítások felülbírálását. Ez akkor hasznos, ha nem szeretne sok ReRoute-beállítást kezelni.

Íme egy egyszerűsített példa az eShopOnContainers egyik API-átjárójának ReRoute-konfigurációs fájljára .

{
  "ReRoutes": [
    {
      "DownstreamPathTemplate": "/api/{version}/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "catalog-api",
          "Port": 80
        }
      ],
      "UpstreamPathTemplate": "/api/{version}/c/{everything}",
      "UpstreamHttpMethod": [ "POST", "PUT", "GET" ]
    },
    {
      "DownstreamPathTemplate": "/api/{version}/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "basket-api",
          "Port": 80
        }
      ],
      "UpstreamPathTemplate": "/api/{version}/b/{everything}",
      "UpstreamHttpMethod": [ "POST", "PUT", "GET" ],
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "IdentityApiKey",
        "AllowedScopes": []
      }
    }

  ],
    "GlobalConfiguration": {
      "RequestIdKey": "OcRequestId",
      "AdministrationPath": "/administration"
    }
  }

Az Ocelot API Gateway fő funkciója a bejövő HTTP-kérések fogadása és továbbítása egy alárendelt szolgáltatásba, amely jelenleg egy másik HTTP-kérés. Az Ocelot az egyik kérés átirányítását egy másikhoz reRoute-ként írja le.

Vegyük például a fent említett configuration.json egyik ReRoutes-t, a Basket mikroszolgáltatás konfigurációját.

{
      "DownstreamPathTemplate": "/api/{version}/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "basket-api",
          "Port": 80
        }
      ],
      "UpstreamPathTemplate": "/api/{version}/b/{everything}",
      "UpstreamHttpMethod": [ "POST", "PUT", "GET" ],
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "IdentityApiKey",
        "AllowedScopes": []
      }
}

A DownstreamPathTemplate, a Séma és a DownstreamHostAndPorts létrehozza azt a belső mikroszolgáltatás-URL-címet, amelybe a kérés továbbítva lesz.

A port a szolgáltatás által használt belső port. Konténerek használatakor a port a dockerfile-ban van megadva.

Ez Host egy szolgáltatásnév, amely a használt szolgáltatásnév felbontásától függ. Docker-compose használata esetén a szolgáltatások nevét a Docker-gazdagép adja meg, amely a docker-compose fájlokban megadott szolgáltatásneveket használja. Ha olyan vezénylőt használ, mint a Kubernetes vagy a Service Fabric, ezt a nevet az egyes vezénylők által megadott DNS- vagy névfeloldással kell feloldani.

A DownstreamHostAndPorts egy tömb, amely tartalmazza a kéréseket továbbítani kívánt alsóbb rétegbeli szolgáltatások gazdagépét és portját. Ez a konfiguráció általában csak egy bejegyzést tartalmaz, de előfordulhat, hogy terheléselosztási kéréseket szeretne használni az alsóbb rétegbeli szolgáltatásokhoz, és az Ocelot lehetővé teszi, hogy több bejegyzést adjon hozzá, majd válasszon ki egy terheléselosztót. De ha az Azure-t és bármely vezénylőt használ, akkor valószínűleg jobb ötlet a terheléselosztás a felhővel és a vezénylő infrastruktúrával.

Az UpstreamPathTemplate az az URL-cím, amellyel az Ocelot azonosítja, hogy melyik DownstreamPathTemplate-ot használja az ügyfél egy adott kéréséhez. Végül a UpstreamHttpMethodot használja, hogy az Ocelot különbséget tegyen a különböző kérések (GET, POST, PUT) között ugyanazon AZ URL-címen.

Ezen a ponton egyetlen Ocelot API Gateway (ASP.NET Core WebHost) lehet egy vagy több egyesített configuration.json fájl használatával, vagy a konfigurációt egy consul KV-tárolóban is tárolhatja.

Az architektúra és a tervezés szakaszaiban bemutatottak szerint azonban, ha valóban autonóm mikroszolgáltatásokat szeretne használni, jobb lehet, ha ezt az egyetlen monolitikus API Gatewayt több API Gatewayre és/vagy BFF-re (a Frontend háttérrendszerére) osztja fel. Ebből a célból nézzük meg, hogyan valósítható meg ez a megközelítés a Docker-tárolókkal.

Egyetlen Docker-tárolórendszerkép használata több különböző API Gateway/BFF-tárolótípus futtatásához

Az eShopOnContainersben egyetlen Docker-tárolórendszerképet használunk az Ocelot API Gateway használatával, de futtatáskor különböző szolgáltatásokat/tárolókat hozunk létre az API-Gateway/BFF egyes típusaihoz egy másik configuration.json fájl biztosításával, egy Docker-kötet használatával, hogy az egyes szolgáltatásokhoz egy másik PC-mappát érhessenek el.

Egyetlen Ocelot-átjáró Docker-rendszerképének diagramja az összes API-átjáróhoz.

6–33. ábra. Egyetlen Ocelot Docker-rendszerkép újrafelhasználása több API Gateway-típusban

Az eShopOnContainersben az "Általános Ocelot API Gateway Docker Image" az "OcelotApiGw" nevű projekttel és a docker-compose.yml fájlban megadott "eshop/ocelotapigw" képnévvel jön létre. Ezután a Dockerben való üzembe helyezéskor négy API-Gateway tároló jön létre ugyanabból a Docker-lemezképből, ahogyan az a docker-compose.yml fájl alábbi kivonatában látható.

  mobileshoppingapigw:
    image: eshop/ocelotapigw:${TAG:-latest}
    build:
      context: .
      dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile

  mobilemarketingapigw:
    image: eshop/ocelotapigw:${TAG:-latest}
    build:
      context: .
      dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile

  webshoppingapigw:
    image: eshop/ocelotapigw:${TAG:-latest}
    build:
      context: .
      dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile

  webmarketingapigw:
    image: eshop/ocelotapigw:${TAG:-latest}
    build:
      context: .
      dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile

Ezenkívül, amint az alábbi docker-compose.override.yml fájlban látható, az API Gateway-tárolók között az egyetlen különbség az Ocelot konfigurációs fájl, amely minden szolgáltatástároló esetében eltérő, és futásidőben van megadva egy Docker-köteten keresztül.

mobileshoppingapigw:
  environment:
    - ASPNETCORE_ENVIRONMENT=Development
    - IdentityUrl=http://identity-api
  ports:
    - "5200:80"
  volumes:
    - ./src/ApiGateways/Mobile.Bff.Shopping/apigw:/app/configuration

mobilemarketingapigw:
  environment:
    - ASPNETCORE_ENVIRONMENT=Development
    - IdentityUrl=http://identity-api
  ports:
    - "5201:80"
  volumes:
    - ./src/ApiGateways/Mobile.Bff.Marketing/apigw:/app/configuration

webshoppingapigw:
  environment:
    - ASPNETCORE_ENVIRONMENT=Development
    - IdentityUrl=http://identity-api
  ports:
    - "5202:80"
  volumes:
    - ./src/ApiGateways/Web.Bff.Shopping/apigw:/app/configuration

webmarketingapigw:
  environment:
    - ASPNETCORE_ENVIRONMENT=Development
    - IdentityUrl=http://identity-api
  ports:
    - "5203:80"
  volumes:
    - ./src/ApiGateways/Web.Bff.Marketing/apigw:/app/configuration

Az előző kód miatt, és ahogy az alábbi Visual Studio Explorerben is látható, az egyes üzleti/BFF API Gateway-átjárók meghatározásához csak egy configuration.json fájl szükséges, mivel a négy API Gateway ugyanazon Docker-rendszerképen alapul.

Képernyőkép az összes API-átjáróról configuration.json fájlokkal.

6-34. ábra. Az egyes API Gateway/BFF Ocelottal való definiálásához csak egy konfigurációs fájl szükséges

Az API Gateway több API Gatewayre való felosztásával a mikroszolgáltatások különböző részhalmazaira összpontosító különböző fejlesztői csapatok önálló Ocelot-konfigurációs fájlok használatával kezelhetik saját API Gateway-jüket. Emellett ugyanazt az Ocelot Docker-lemezképet is újra felhasználhatják.

Most, ha az API-átjárókkal futtat eShopOnContainerst (a VS alapértelmezés szerint tartalmazza eShopOnContainers-ServicesAndWebApps.sln megoldás megnyitásakor vagy a "docker-compose up" futtatásakor), a következő mintaútvonalak lesznek végrehajtva.

Ha például a webshoppingapigw API Gateway által kiszolgált felső URL-címet http://host.docker.internal:5202/api/v1/c/catalog/items/2/ látogatja meg, ugyanazt az eredményt kapja a Docker-gazdagép belső alsóbb rétegbeli URL-címétől http://catalog-api/api/v1/2 , mint a következő böngészőben.

Képernyőkép egy böngészőről, amelyen az API-átjárón keresztüli válasz látható.

6–35. ábra. Mikroszolgáltatás elérése az API Gateway által megadott URL-címen keresztül

Tesztelési vagy hibakeresési okokból, ha a Katalógus Docker-tárolóhoz (csak a fejlesztői környezetben) szeretne közvetlenül hozzáférni anélkül, hogy áthalad az API Gatewayen, mivel a "catalog-api" a Docker-gazdagépen belüli DNS-feloldás (a docker-compose szolgáltatásnevek által kezelt szolgáltatásfelderítés), a tároló közvetlen elérésének egyetlen módja a docker-compose.override.yml közzétett külső porton keresztül történik, amely csak fejlesztési tesztekhez érhető el, például http://host.docker.internal:5101/api/v1/Catalog/items/1 a következő böngészőben.

Képernyőkép egy böngészőről, amely a Catalog.api-ra adott közvetlen választ jeleníti meg.

6–36. ábra. Mikroszolgáltatásokhoz való közvetlen hozzáférés tesztelés céljából

Az alkalmazás azonban úgy van konfigurálva, hogy az api-átjárókon keresztül férhessen hozzá az összes mikroszolgáltatáshoz, nem pedig a közvetlen port "parancsikonjaival".

Az átjáró aggregációs mintája az eShopOnContainersben

A korábban bemutatottak szerint a kérések összesítésének rugalmas módja az egyéni szolgáltatások használata, kód alapján. Az összesítés eShopOnContainersben való implementálásának kiválasztott módja az egyes összesítőkhöz tartozó explicit ASP.NET Core Web API-szolgáltatás.

Ennek a megközelítésnek megfelelően az API Gateway összeállítási diagramja a valóságban egy kicsit hosszabb, amikor figyelembe veszi azokat az összesítő szolgáltatásokat, amelyek nem jelennek meg a korábban bemutatott egyszerűsített globális architektúradiagramon.

Az alábbi ábrán azt is láthatja, hogyan működnek az összesítő szolgáltatások a kapcsolódó API-átjárókkal.

Az eShopOnContainers architektúrájának diagramja az összesítő szolgáltatásokról.

6–37. ábra. eShopOnContainers architektúra összesítő szolgáltatásokkal

Az alábbi képen látható "Vásárlás" üzleti területen további nagyítással láthatja, hogy az ügyfélalkalmazások és a mikroszolgáltatások közötti csevegés csökken az API-átjárók összesítő szolgáltatásainak használatakor.

Az eShopOnContainers architektúra nagyítását bemutató ábra.

6–38. ábra. Az Aggregator-szolgáltatások képének nagyítása

Megfigyelheti, hogy ha a diagram az API-átjárókból érkező lehetséges kéréseket jeleníti meg, az hogyan válik összetettké. Ha viszont az összesítő mintát használja, láthatja, hogy a kék nyilak hogyan egyszerűsítik az ügyfélalkalmazások szempontjából a kommunikációt. Ez a minta nem csak a csevegés és a késés csökkentésében segít a kommunikációban, hanem jelentősen javítja a felhasználói élményt a távoli alkalmazások (mobil- és SPA-alkalmazások) esetében is.

A "Marketing" üzleti terület és mikroszolgáltatások esetében ez egy egyszerű használati eset, így nem volt szükség aggregátorok használatára, de szükség esetén lehetséges is lehet.

Hitelesítés és engedélyezés az Ocelot API-átjárókban

Az Ocelot API Gateway-nél a hitelesítési szolgáltatás, mint például egy ASP.NET Core Web API szolgáltatás az IdentityServer használatával, amely az autentikációs tokent biztosítja, elhelyezhető akár az API Gatewayen kívül, akár belül.

Mivel az eShopOnContainers több, BFF és üzleti területek alapján határolt API-átjárót használ, az Identity/Auth szolgáltatás kimarad az API-átjárókból, amint az a következő ábrán sárga színnel van kiemelve.

Az API-átjáró alatti Identitás mikroszolgáltatást bemutató ábra.

6–39. ábra. Az identitásszolgáltatás pozíciója az eShopOnContainersben

Az Ocelot azonban támogatja az Identity/Auth mikroszolgáltatásnak az API-átjáró határain belüli ülését is, ahogyan a másik ábrán is látható.

Egy Ocelot API Gateway hitelesítését bemutató ábra.

6-40. ábra. Hitelesítés az Ocelotban

Ahogy az előző ábrán látható, amikor az Identitás mikroszolgáltatás az API-átjáró (AG) alatt található: 1) Az AG hitelesítési jogkivonatot kér az identitás mikroszolgáltatástól, 2) Az identitás mikroszolgáltatás jogkivonatot ad vissza az AG-nek, 3–4) AG-kéréseket a mikroszolgáltatásoktól az auth token használatával. Mivel az eShopOnContainers alkalmazás az API Gatewayt több BFF-re (előtérbeli háttérrendszerre) és üzleti területekre osztotta fel az API Gateway-eket, egy másik lehetőség egy további API Gateway létrehozása lett volna a horizontális problémák kezelésére. Ez a választás tisztességes lenne egy összetettebb mikroszolgáltatás-alapú architektúrában, több horizontális szempontú mikroszolgáltatással. Mivel az eShopOnContainersben csak egyetlen keresztirányú probléma van, úgy döntöttek, hogy az egyszerűség kedvéért csak az API Gateway területéről kezelik a biztonsági szolgáltatást.

Mindenesetre, ha az alkalmazás az API Gateway szintjén van védve, az Ocelot API Gateway hitelesítési modulja először meg lesz látogatva, amikor bármilyen biztonságos mikroszolgáltatást próbál használni. Ez átirányítja a HTTP-kérést az Identity vagy hitelesítési mikroszolgáltatáshoz, hogy megszerezze a hozzáférési token-t, így meglátogathatja a védett szolgáltatásokat a access_token-nel.

Az API Gateway szintjén bármely szolgáltatás hitelesítéssel történő biztonságossá tétele az AuthenticationProviderKey kulcs beállításával történik a configuration.jsonkapcsolatban szereplő beállításokban.

    {
      "DownstreamPathTemplate": "/api/{version}/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "basket-api",
          "Port": 80
        }
      ],
      "UpstreamPathTemplate": "/api/{version}/b/{everything}",
      "UpstreamHttpMethod": [],
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "IdentityApiKey",
        "AllowedScopes": []
      }
    }

Az Ocelot futtatásakor megtekinti a ReRoutes AuthenticationOptions.AuthenticationProviderKey elemet, és ellenőrzi, hogy van-e regisztrálva egy hitelesítésszolgáltató a megadott kulccsal. Ha nincs, akkor az Ocelot nem indul el. Ha van ilyen, akkor a ReRoute ezt a szolgáltatót fogja használni a végrehajtáskor.

Mivel az Ocelot WebHost úgy van konfigurálva, hogy hitelesítést igényel, amikor a szolgáltatásnak bármilyen hitelesítési jogkivonat nélküli kérése van.

namespace OcelotApiGw
{
    public class Startup
    {
        private readonly IConfiguration _cfg;

        public Startup(IConfiguration configuration) => _cfg = configuration;

        public void ConfigureServices(IServiceCollection services)
        {
            var identityUrl = _cfg.GetValue<string>("IdentityUrl");
            var authenticationProviderKey = "IdentityApiKey";
                         //…
            services.AddAuthentication()
                .AddJwtBearer(authenticationProviderKey, x =>
                {
                    x.Authority = identityUrl;
                    x.RequireHttpsMetadata = false;
                    x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
                    {
                        ValidAudiences = new[] { "orders", "basket", "locations", "marketing", "mobileshoppingagg", "webshoppingagg" }
                    };
                });
            //...
        }
    }
}

Ezután meg kell adnia az [Engedélyezés] attribútummal való engedélyezést minden olyan erőforráson, amely a mikroszolgáltatásokhoz hasonlóan elérhető, például a következő Basket mikroszolgáltatás-vezérlőben.

namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
{
    [Route("api/v1/[controller]")]
    [Authorize]
    public class BasketController : Controller
    {
      //...
    }
}

A ValidAudience-ek, például a "kosár" korrelálnak az egyes mikroszolgáltatásokban meghatározott célközönséggel AddJwtBearer() az indítási osztály ConfigureServices() osztályában, például az alábbi kódban.

// prevent from mapping "sub" claim to nameidentifier.
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

var identityUrl = Configuration.GetValue<string>("IdentityUrl");

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

}).AddJwtBearer(options =>
{
    options.Authority = identityUrl;
    options.RequireHttpsMetadata = false;
    options.Audience = "basket";
});

Ha megpróbál hozzáférni bármilyen biztonságos mikroszolgáltatáshoz, például a Basket mikroszolgáltatáshoz, ami az API Gateway alapú ReRoute URL-en keresztül van elérhető, akkor 401-es jogosulatlan hibaüzenetet kap, hacsak nem ad meg érvényes tokent. Ha viszont hitelesíti a ReRoute URL-címét, az Ocelot meghívja a hozzá társított alsóbb rétegbeli sémát (a belső mikroszolgáltatás URL-címét).

Engedélyezés az Ocelot ReRoutes szintjén. Az Ocelot támogatja a hitelesítés után kiértékelt jogcímalapú engedélyezést. Az engedélyezést útvonalszinten állíthatja be az alábbi sorokkal a ReRoute-konfigurációhoz.

"RouteClaimsRequirement": {
    "UserType": "employee"
}

Ebben a példában az engedélyezési köztes szoftver meghívásakor az Ocelot megkeresi, hogy a felhasználónak van-e "UserType" jogcímtípusa a jogkivonatban, és hogy a jogcím értéke "alkalmazott"-e. Ha nem, akkor a felhasználó nem lesz jogosult, és a válasz 403 tiltott lesz.

A Kubernetes Ingress és az Ocelot API átjárók használata

A Kubernetes használatakor (például egy Azure Kubernetes Service-fürtben) általában az összes HTTP-kérést az Nginx alapján a Kubernetes Bejövő forgalom rétegen keresztül egyesíti.

A Kubernetesben, ha nem használ semmilyen ingress megközelítést, akkor a szolgáltatások és podok IP-címei csak a fürthálózaton belül irányíthatók.

Ha azonban bemeneti megközelítést használ, akkor az internet és a szolgáltatások (beleértve az API Gateway-eket is) között egy középső réteg lesz, amely fordított proxyként működik.

Definíció szerint az Ingress egy olyan szabálygyűjtemény, amely lehetővé teszi a bejövő kapcsolatok számára a klaszterszolgáltatásokhoz való kapcsolódást. Az ingress úgy van konfigurálva, hogy külsőleg elérhető URL-eket, terheléselosztást, SSL-lekapcsolást és egyebeket biztosítson. A felhasználók POST kéréssel küldik az Ingress erőforrást az API szerverre a hozzáférés érdekében.

Az eShopOnContainersben helyi fejlesztéskor és csak a fejlesztőgép docker-gazdagépként való használata esetén nem használ bejövő forgalmat, hanem csak a több API-átjárót.

A Kubernetesen alapuló „éles” környezet megcélzásakor azonban az eShopOnContainers egy ingresszt használ az API-átjárók előtt. Így az ügyfelek továbbra is ugyanazt az alap URL-címet hívják, de a kérések több API-átjáróhoz vagy BFF-hez lesznek irányítva.

Az API-átjárók olyan előtér- vagy homlokzatok, amelyek csak a szolgáltatásokat használják, a webalkalmazásokat azonban nem, amelyek általában nem tartoznak a hatókörükbe. Emellett előfordulhat, hogy az API Gatewayek elrejtenek bizonyos belső mikroszolgáltatásokat.

A bejövő forgalom azonban csak átirányítja a HTTP-kéréseket, de nem próbál elrejteni semmilyen mikroszolgáltatást vagy webes alkalmazást.

A Kubernetesben a webalkalmazások előtt elhelyezett ingress Nginx réteg, valamint a több Ocelot API Gateway és BFF az ideális architektúra, ahogyan az alábbi ábrán látható.

Egy diagram, amely bemutatja, hogyan illeszkedik egy bejövő szint az AKS-környezetbe.

6-41. ábra Az eShopOnContainers bejövő szintje a Kubernetesben való üzembe helyezéskor

A Kubernetes Ingress fordított proxyként működik az összes alkalmazás felé irányuló forgalom számára, beleértve azokat a webalkalmazásokat is, amelyek nem tartoznak az API átjáró hatókörébe. Az eShopOnContainers Kubernetesben való üzembe helyezésekor csak néhány szolgáltatást vagy végpontot tesz elérhetővé bejövő forgalomon keresztül, alapvetően az URL-címek postfixjeinek alábbi listája:

  • / az ügyfél SPA-webalkalmazáshoz
  • /webmvc az ügyfél MVC-webalkalmazásához
  • /webstatus az állapot-/állapotellenőrzéseket megjelenítő ügyfél-webalkalmazás esetében
  • /webshoppingapigw a webes BFF-hez és a vásárlási üzleti folyamatokhoz
  • /webmarketingapigw a webes BFF-hez és a marketing üzleti folyamatokhoz
  • /mobileshoppingapigw a mobil BFF-hez és a vásárlási üzleti folyamatokhoz
  • /mobilemarketingapigw a mobil BFF és a marketing üzleti folyamatok esetében

A Kubernetesben való üzembe helyezéskor minden Ocelot API-átjáró egy másik "configuration.json" fájlt használ az API-átjárókat futtató podokhoz. Ezek a "configuration.json" fájlok az "ocelot" nevű Kubernetes konfigurációs térkép alapján létrehozott kötet csatlakoztatásával (eredetileg a deploy.ps1 szkripttel) érhetők el. Minden tároló a kapcsolódó konfigurációs fájlt a /app/configuration nevű mappájába csatolja a tárolóban.

Az eShopOnContainers forráskódfájljaiban az eredeti "configuration.json" fájlok találhatók a k8s/ocelot/ mappában. Minden BFF/APIGatewayhez egy fájl tartozik.

További keresztvágási funkciók az Ocelot API Gatewayben

Az Ocelot API Gateway használata esetén a kutatásnak és a használatnak egyéb fontos funkciói is vannak, amelyeket az alábbi hivatkozások mutatnak be.