Dela via


Implementera API Gateways med Ocelot

Dricks

Det här innehållet är ett utdrag från eBook, .NET Microservices Architecture for Containerized .NET Applications, tillgängligt på .NET Docs eller som en kostnadsfri nedladdningsbar PDF som kan läsas offline.

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

Viktigt!

Referensprogrammet eShopOnContainers använder för närvarande funktioner som tillhandahålls av Envoy för att implementera API Gateway i stället för den tidigare refererade Ocelot. Vi gjorde det här designvalet på grund av Envoys inbyggda stöd för WebSocket-protokollet, vilket krävs av den nya gRPC-kommunikation mellan tjänster som implementeras i eShopOnContainers. Vi har dock behållit det här avsnittet i guiden så att du kan betrakta Ocelot som en enkel, kapabel och enkel API Gateway som lämpar sig för scenarier i produktionsklass. Dessutom innehåller den senaste Ocelot-versionen en icke-bakåtkompatibel ändring av dess json-schema. Överväg att använda Ocelot < v16.0.0 eller använd nyckelvägarna i stället för ReRoutes.

Skapa och utforma dina API Gateways

Följande arkitekturdiagram visar hur API Gateways implementerades med Ocelot i eShopOnContainers.

Diagram showing the eShopOnContainers architecture.

Bild 6-28. eShopOnContainers-arkitektur med API Gateways

Diagrammet visar hur hela programmet distribueras till en enskild Docker-värd eller utvecklingsdator med "Docker för Windows" eller "Docker för Mac". Distribution till valfri orkestrerare skulle dock vara liknande, men alla containrar i diagrammet kan skalas ut i orkestreraren.

Dessutom bör infrastrukturtillgångar som databaser, cacheminnen och meddelandeköer avlastas från orkestreraren och distribueras till högtillgängliga system för infrastruktur, till exempel Azure SQL Database, Azure Cosmos DB, Azure Redis, Azure Service Bus eller valfri lokal HA-klustringslösning.

Som du också kan se i diagrammet gör flera API Gateways att flera utvecklingsteam kan vara autonoma (i det här fallet marknadsföringsfunktioner jämfört med shoppingfunktioner) när de utvecklar och distribuerar sina mikrotjänster plus sina egna relaterade API Gateways.

Om du hade en enda monolitisk API Gateway skulle det innebära att en enda punkt skulle uppdateras av flera utvecklingsteam, vilket skulle kunna koppla ihop alla mikrotjänster med en enda del av programmet.

Om du går mycket längre i designen kan ibland en detaljerad API Gateway också begränsas till en enda affärsmikrotjänst beroende på den valda arkitekturen. Genom att låta API Gateway-gränserna styras av företaget eller domänen kan du få en bättre design.

Till exempel kan fin kornighet på API Gateway-nivån vara särskilt användbar för mer avancerade sammansatta gränssnittsprogram som baseras på mikrotjänster, eftersom begreppet en detaljerad API Gateway liknar en UI-sammansättningstjänst.

Vi går in på mer information i föregående avsnitt Skapa sammansatt användargränssnitt baserat på mikrotjänster.

För många medelstora och stora program är det vanligtvis en bra metod att använda en anpassad API Gateway-produkt, men inte som en enda monolitisk aggregering eller unik central anpassad API Gateway om inte API Gateway tillåter flera oberoende konfigurationsområden för flera utvecklingsteam som skapar autonoma mikrotjänster.

Exempel på mikrotjänster/containrar för att omdirigera via API Gateways

EShopOnContainers har till exempel cirka sex interna mikrotjänsttyper som måste publiceras via API Gateways, enligt följande bild.

Screenshot of the Services folder showing its subfolders.

Bild 6-29. Mikrotjänstmappar i eShopOnContainers-lösningen i Visual Studio

Om identitetstjänsten är den i designen utelämnad från API Gateway-routningen eftersom det är det enda övergripande problemet i systemet, men med Ocelot är det också möjligt att inkludera den som en del av omdirigeringslistorna.

Alla dessa tjänster implementeras för närvarande som ASP.NET Core Web API-tjänster, som du kan se från koden. Nu ska vi fokusera på en av mikrotjänsterna, till exempel katalogens mikrotjänstkod.

Screenshot of Solution Explorer showing Catalog.API project contents.

Bild 6-30. Exempel på webb-API-mikrotjänst (katalogmikrotjänst)

Du kan se att katalogmikrotjänsten är ett typiskt ASP.NET Core Web API-projekt med flera kontrollanter och metoder som i följande kod.

[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();
}

HTTP-begäran kommer att köra den typen av C#-kod som kommer åt mikrotjänstdatabasen och eventuella ytterligare nödvändiga åtgärder.

När det gäller mikrotjänst-URL:en, när containrarna distribueras i din lokala utvecklingsdator (lokal Docker-värd), har varje mikrotjänsts container alltid en intern port (vanligtvis port 80) angiven i sin dockerfile, som i följande dockerfile:

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

Port 80 som visas i koden är intern i Docker-värden, så den kan inte nås av klientappar.

Klientappar kan bara komma åt de externa portar (om några) som publiceras när de distribueras med docker-compose.

Dessa externa portar bör inte publiceras när du distribuerar till en produktionsmiljö. Av den här specifika anledningen, varför du vill använda API Gateway, för att undvika direkt kommunikation mellan klientapparna och mikrotjänsterna.

Men när du utvecklar vill du komma åt mikrotjänsten/containern direkt och köra den via Swagger. Därför anges de externa portarna fortfarande i eShopOnContainers även när de inte används av API Gateway eller klientapparna.

Här är ett exempel på docker-compose.override.yml filen för katalogmikrotjänsten:

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).

Du kan se hur den interna porten för katalogcontainern i docker-compose.override.yml konfiguration är port 80, men porten för extern åtkomst är 5101. Men den här porten bör inte användas av programmet när du använder en API Gateway, bara för att felsöka, köra och testa bara katalogmikrotjänsten.

Normalt distribuerar du inte med docker-compose till en produktionsmiljö eftersom rätt produktionsdistributionsmiljö för mikrotjänster är en orkestrerare som Kubernetes eller Service Fabric. När du distribuerar till dessa miljöer använder du olika konfigurationsfiler där du inte publicerar någon extern port direkt för mikrotjänsterna, men du använder alltid den omvända proxyn från API Gateway.

Kör katalogmikrotjänsten i din lokala Docker-värd. Kör antingen den fullständiga eShopOnContainers-lösningen från Visual Studio (den kör alla tjänster i docker-compose-filerna) eller starta katalogmikrotjänsten med följande docker-compose-kommando i CMD eller PowerShell placerad i mappen där docker-compose.yml och docker-compose.override.yml placeras.

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

Det här kommandot kör endast containern catalog-api service plus beroenden som anges i docker-compose.yml. I det här fallet SQL Server-containern och RabbitMQ-containern.

Sedan kan du komma åt katalogmikrotjänsten direkt och se dess metoder via Swagger-användargränssnittet direkt via den "externa" porten, i det här fallet http://host.docker.internal:5101/swagger:

Screenshot of Swagger UI showing the Catalog.API REST API.

Bild 6-31. Testa katalogmikrotjänsten med sitt Swagger-användargränssnitt

Nu kan du ange en brytpunkt i C#-kod i Visual Studio, testa mikrotjänsten med de metoder som exponeras i Swagger-användargränssnittet och slutligen rensa allt med docker-compose down kommandot.

Direktåtkomstkommunikation till mikrotjänsten, i det här fallet via den externa porten 5101, är dock precis vad du vill undvika i ditt program. Och du kan undvika det genom att ange den ytterligare indirekta nivån för API Gateway (Ocelot, i det här fallet). På så sätt kommer klientappen inte direkt åt mikrotjänsten.

Implementera dina API Gateways med Ocelot

Ocelot är i princip en uppsättning mellanprogram som du kan använda i en viss ordning.

Ocelot är endast utformat för att fungera med ASP.NET Core. Den senaste versionen av paketet är 18.0 som riktar sig till .NET 6 och därför inte är lämplig för .NET Framework-program.

Du installerar Ocelot och dess beroenden i ditt ASP.NET Core-projekt med Ocelots NuGet-paket från Visual Studio.

Install-Package Ocelot

I eShopOnContainers är dess API Gateway-implementering ett enkelt ASP.NET Core WebHost-projekt, och Ocelots mellanprogram hanterar alla API Gateway-funktioner, som visas i följande bild:

Screenshot of Solution Explorer showing Ocelot API gateway project.

Bild 6-32. OcelotApiGw-basprojektet i eShopOnContainers

Det här ASP.NET Core WebHost-projektet har skapats med två enkla filer: Program.cs och Startup.cs.

Program.cs behöver bara skapa och konfigurera den typiska ASP.NET Core BuildWebHost.

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;
        }
    }
}

Den viktiga punkten här för Ocelot är den configuration.json fil som du måste ange för byggaren via AddJsonFile() -metoden. Det configuration.json är där du anger alla API Gateway ReRoutes, vilket innebär att de externa slutpunkterna med specifika portar och de korrelerade interna slutpunkterna vanligtvis använder olika portar.

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

Det finns två avsnitt i konfigurationen. En matris med ReRoutes och en GlobalConfiguration. ReRoutes är de objekt som talar om för Ocelot hur en överordnad begäran ska hanteras. Den globala konfigurationen tillåter åsidosättningar av ReRoute-specifika inställningar. Det är användbart om du inte vill hantera många reroute-specifika inställningar.

Här är ett förenklat exempel på ReRoute-konfigurationsfilen från en av API Gateways från eShopOnContainers.

{
  "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"
    }
  }

Huvudfunktionerna i en Ocelot API Gateway är att ta inkommande HTTP-begäranden och vidarebefordra dem till en underordnad tjänst, för närvarande som en annan HTTP-begäran. Ocelot's beskriver routningen av en begäran till en annan som en ReRoute.

Vi ska till exempel fokusera på en av ReRoutes i configuration.json ovan, konfigurationen för basketmikrotjänsten.

{
      "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": []
      }
}

DownstreamPathTemplate, Scheme och DownstreamHostAndPorts gör den interna mikrotjänst-URL:en som begäran vidarebefordras till.

Porten är den interna port som används av tjänsten. När du använder containrar anges porten i dess dockerfile.

Host är ett tjänstnamn som är beroende av den lösning för tjänstnamn som du använder. När du använder docker-compose tillhandahålls tjänstnamnen av Docker-värden, som använder tjänstnamnen som anges i docker-compose-filerna. Om du använder en orkestrerare som Kubernetes eller Service Fabric bör det namnet matchas av dns- eller namnmatchningen som tillhandahålls av varje orkestrator.

DownstreamHostAndPorts är en matris som innehåller värden och porten för alla underordnade tjänster som du vill vidarebefordra begäranden till. Vanligtvis innehåller den här konfigurationen bara en post, men ibland kanske du vill lastbalansera begäranden till dina underordnade tjänster och Med Ocelot kan du lägga till fler än en post och sedan välja en lastbalanserare. Men om du använder Azure och någon orkestrerare är det förmodligen en bättre idé att belastningsutjämning med molnet och orkestreringsinfrastrukturen.

UpstreamPathTemplate är den URL som Ocelot använder för att identifiera vilken DownstreamPathTemplate som ska användas för en viss begäran från klienten. Slutligen används UpstreamHttpMethod så att Ocelot kan skilja mellan olika begäranden (GET, POST, PUT) med samma URL.

Nu kan du ha en enda Ocelot API Gateway (ASP.NET Core WebHost) med hjälp av en eller flera sammanfogade configuration.json filer eller så kan du även lagra konfigurationen i ett Konsul KV-arkiv.

Men om du verkligen vill ha autonoma mikrotjänster kan det vara bättre att dela upp den monolitiska API-gatewayen i flera API Gateways och/eller BFF (serverdelen för klientdelen) som introduceras i avsnitten arkitektur och design. Därför ska vi se hur du implementerar den metoden med Docker-containrar.

Använda en enskild Docker-containeravbildning för att köra flera olika API Gateway/BFF-containertyper

I eShopOnContainers använder vi en enda Docker-containeravbildning med Ocelot API Gateway, men sedan skapar vi olika tjänster/containrar för varje typ av API-Gateway/BFF genom att tillhandahålla en annan configuration.json fil med hjälp av en docker-volym för att få åtkomst till en annan datormapp för varje tjänst.

Diagram of a single Ocelot gateway Docker image for all API gateways.

Bild 6-33. Återanvända en enskild Ocelot Docker-avbildning över flera API Gateway-typer

I eShopOnContainers skapas "Generic Ocelot API Gateway Docker Image" med projektet "OcelotApiGw" och avbildningsnamnet "eshop/ocelotapigw" som anges i filen docker-compose.yml. När du sedan distribuerar till Docker kommer det att finnas fyra API-Gateway-containrar som skapats från samma Docker-avbildning, som du ser i följande extrahering från docker-compose.yml-filen.

  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

Som du kan se i följande docker-compose.override.yml fil är den enda skillnaden mellan dessa API Gateway-containrar Ocelot-konfigurationsfilen, som är olika för varje tjänstcontainer och som anges vid körning via en Docker-volym.

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

På grund av den tidigare koden, och som visas i Visual Studio Explorer nedan, är den enda fil som behövs för att definiera varje specifik affärs-/BFF API Gateway bara en configuration.json fil, eftersom de fyra API Gateways baseras på samma Docker-avbildning.

Screenshot showing all API gateways with configuration.json files.

Bild 6-34. Den enda fil som behövs för att definiera varje API Gateway/BFF med Ocelot är en konfigurationsfil

Genom att dela upp API Gateway i flera API Gateways kan olika utvecklingsteam som fokuserar på olika delmängder av mikrotjänster hantera sina egna API Gateways med hjälp av oberoende Ocelot-konfigurationsfiler. Dessutom kan de återanvända samma Ocelot Docker-avbildning.

Om du nu kör eShopOnContainers med API Gateways (ingår som standard i VS när du öppnar eShopOnContainers-ServicesAndWebApps.sln lösning eller om du kör "docker-compose up") utförs följande exempelvägar.

När du till exempel besöker den överordnade URL:en http://host.docker.internal:5202/api/v1/c/catalog/items/2/ som hanteras av api-gatewayen webshoppingapigw får du samma resultat från den interna nedströms-URL:en http://catalog-api/api/v1/2 i Docker-värden som i följande webbläsare.

Screenshot of a browser showing a response going through API gateway.

Bild 6-35. Åtkomst till en mikrotjänst via en URL som tillhandahålls av API Gateway

Om du vill ha direkt åtkomst till Docker-containern i katalog (endast i utvecklingsmiljön) utan att skicka via API Gateway, eftersom "catalog-api" är en DNS-matchning som är intern för Docker-värden (tjänstidentifiering som hanteras av docker-compose-tjänstnamn) är det enda sättet att komma åt containern direkt via den externa porten som publicerats i docker-compose.override.yml, som endast tillhandahålls för utvecklingstester, till exempel http://host.docker.internal:5101/api/v1/Catalog/items/1 i följande webbläsare.

Screenshot of a browser showing a direct response to the Catalog.api.

Bild 6-36. Direktåtkomst till en mikrotjänst i testsyfte

Men programmet är konfigurerat så att det kommer åt alla mikrotjänster via API Gateways, inte via direktporten "genvägar".

Gateway-sammansättningsmönstret i eShopOnContainers

Som tidigare beskrivits är ett flexibelt sätt att implementera aggregering av begäranden med anpassade tjänster, efter kod. Du kan också implementera aggregering av begäranden med funktionen Förfrågningsaggregering i Ocelot, men den kanske inte är så flexibel som du behöver. Därför är det valda sättet att implementera aggregering i eShopOnContainers med en explicit ASP.NET Core Web API-tjänst för varje aggregator.

Enligt den metoden utökas API Gateway-kompositionsdiagrammet i verkligheten lite mer när du överväger de aggregatortjänster som inte visas i det förenklade globala arkitekturdiagram som visades tidigare.

I följande diagram kan du också se hur aggregatortjänsterna fungerar med sina relaterade API Gateways.

Diagram of eShopOnContainers architecture showing aggregator services.

Bild 6-37. eShopOnContainers-arkitektur med aggregatortjänster

Om du zoomar in ytterligare på affärsområdet "Shopping" i följande bild kan du se att chattigheten mellan klientapparna och mikrotjänsterna minskar när du använder aggregatortjänsterna i API Gateways.

Diagram showing eShopOnContainers architecture zoom in.

Bild 6-38. Zooma in visionen för Aggregator-tjänsterna

Du kan se hur det kan bli komplext när diagrammet visar de möjliga begäranden som kommer från API Gateways. Å andra sidan kan du se hur pilarna i blått förenklar kommunikationen ur ett klientappsperspektiv när du använder aggregatormönstret. Det här mönstret bidrar inte bara till att minska chattigheten och svarstiden i kommunikationen, det förbättrar även användarupplevelsen avsevärt för fjärrappar (mobil- och SPA-appar).

När det gäller affärsområdet "Marknadsföring" och mikrotjänster är det ett enkelt användningsfall så det fanns inget behov av att använda aggregatorer, men det kan också vara möjligt om det behövs.

Autentisering och auktorisering i Ocelot API Gateways

I en Ocelot API Gateway kan du sitta i autentiseringstjänsten, till exempel en ASP.NET Core Web API-tjänst med hjälp av IdentityServer som tillhandahåller autentiseringstoken, antingen ute eller inuti API Gateway.

Eftersom eShopOnContainers använder flera API Gateways med gränser baserade på BFF och affärsområden lämnas identitets-/autentiseringstjänsten utanför API Gateways, vilket är markerat i gult i följande diagram.

Diagram showing Identity microservice beneath the API gateway.

Bild 6-39. Identitetstjänstens position i eShopOnContainers

Ocelot har dock även stöd för att sitta Identity/Auth-mikrotjänsten inom API Gateway-gränsen, som i det här andra diagrammet.

Diagram showing authentication in an Ocelot API Gateway.

Bild 6-40. Autentisering i Ocelot

Som det föregående diagrammet visar, när identitetsmikrotjänsten finns under API-gatewayen (AG): 1) AG begär en autentiseringstoken från identitetsmikrotjänst, 2) Identitetsmikrotjänsten returnerar token till tillgänglighetsgruppen, 3–4) AG-begäranden från mikrotjänster med hjälp av autentiseringstoken. Eftersom eShopOnContainers-programmet har delat upp API Gateway i flera BFF -program (serverdelen för klientdelen) och affärsområdena API Gateways, skulle ett annat alternativ ha varit att skapa ytterligare en API Gateway för övergripande problem. Det valet skulle vara rättvist i en mer komplex mikrotjänstbaserad arkitektur med flera övergripande problem för mikrotjänster. Eftersom det bara finns ett övergripande problem i eShopOnContainers bestämdes det att bara hantera säkerhetstjänsten utanför API Gateway-sfären, för enkelhetens skull.

I vilket fall som helst, om appen skyddas på API Gateway-nivå, besöks autentiseringsmodulen för Ocelot API Gateway först när du försöker använda någon säker mikrotjänst. Det omdirigerar HTTP-begäran för att besöka identiteten eller autentiseringsmikrotjänsten för att hämta åtkomsttoken så att du kan besöka de skyddade tjänsterna med access_token.

Det sätt som du skyddar med autentisering av alla tjänster på API Gateway-nivå är genom att ange AuthenticationProviderKey i dess relaterade inställningar på configuration.json.

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

När Ocelot körs tittar den på ReRoutes AuthenticationOptions.AuthenticationProviderKey och kontrollerar att det finns en autentiseringsprovider registrerad med den angivna nyckeln. Om det inte finns det startar inte Ocelot. Om så är fallet använder ReRoute providern när den körs.

Eftersom Ocelot WebHost har konfigurerats med authenticationProviderKey = "IdentityApiKey"kräver det autentisering när tjänsten har några begäranden utan någon autentiseringstoken.

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" }
                    };
                });
            //...
        }
    }
}

Sedan måste du också ange auktorisering med attributet [Auktorisera] för alla resurser som ska användas som mikrotjänster, till exempel i följande basket-mikrotjänstkontrollant.

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

ValidAudiences som "korg" korreleras med målgruppen som definieras i varje mikrotjänst med AddJwtBearer() i Klassen ConfigureServices() i startklassen, till exempel i koden nedan.

// 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";
});

Om du försöker komma åt någon skyddad mikrotjänst, till exempel Basket-mikrotjänsten med en ReRoute-URL baserat på API Gateway som http://host.docker.internal:5202/api/v1/b/basket/1, får du en 401 Obehörig om du inte anger en giltig token. Om en ReRoute-URL å andra sidan autentiseras anropar Ocelot det underordnade schema som är associerat med den (den interna mikrotjänst-URL:en).

Auktorisering på Ocelots ReRoutes-nivå. Ocelot stöder anspråksbaserad auktorisering som utvärderas efter autentiseringen. Du anger auktoriseringen på vägnivå genom att lägga till följande rader i ReRoute-konfigurationen.

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

I det exemplet när mellanprogrammet för auktorisering anropas, kommer Ocelot att ta reda på om användaren har anspråkstypen "UserType" i token och om värdet för anspråket är "anställd". Om det inte är det kommer användaren inte att auktoriseras och svaret är 403 förbjudet.

Använda Kubernetes Ingress plus Ocelot API Gateways

När du använder Kubernetes (till exempel i ett Azure Kubernetes Service-kluster) förenar du vanligtvis alla HTTP-begäranden via Kubernetes-ingressnivån baserat på Nginx.

Om du inte använder någon ingressmetod i Kubernetes har dina tjänster och poddar IP-adresser som endast kan dirigeras av klusternätverket.

Men om du använder en ingressmetod har du en mellannivå mellan Internet och dina tjänster (inklusive dina API Gateways) som fungerar som en omvänd proxy.

Som en definition är en ingress en samling regler som tillåter inkommande anslutningar att nå klustertjänsterna. En ingress har konfigurerats för att tillhandahålla tjänster externt åtkomliga URL:er, lastbalanseringstrafik, SSL-avslutning med mera. Användare begär ingress genom att POSTing ingress-resursen till API-servern.

I eShopOnContainers, när du utvecklar lokalt och bara använder din utvecklingsdator som Docker-värd, använder du inte någon ingress utan bara flera API Gateways.

Men när du riktar in dig på en "produktionsmiljö" baserad på Kubernetes använder eShopOnContainers en ingress framför API-gatewayerna. På så sätt anropar klienterna fortfarande samma bas-URL, men begäranden dirigeras till flera API Gateways eller BFF.

API Gateways är klientdelar eller fasader som bara visar tjänsterna, men inte de webbprogram som vanligtvis ligger utanför deras omfång. Dessutom kan API Gateways dölja vissa interna mikrotjänster.

Ingressen omdirigerar dock bara HTTP-begäranden men försöker inte dölja någon mikrotjänst eller webbapp.

Att ha en inkommande Nginx-nivå i Kubernetes framför webbprogrammen plus flera Ocelot API Gateways/BFF är den idealiska arkitekturen, som du ser i följande diagram.

A diagram showing how an ingress tier fits into the AKS environment.

Bild 6-41. Ingressnivån i eShopOnContainers när den distribueras till Kubernetes

En Kubernetes-ingress fungerar som en omvänd proxy för all trafik till appen, inklusive webbprogrammen, som ligger utanför Api Gateway-omfånget. När du distribuerar eShopOnContainers till Kubernetes exponeras bara några få tjänster eller slutpunkter via ingress, i princip följande lista över postfix på URL:erna:

  • / för klientens SPA-webbapp
  • /webmvc för klientens MVC-webbapp
  • /webstatus för klientwebbappen som visar status/hälsokontroller
  • /webshoppingapigw för webb-BFF och affärsprocesser för shopping
  • /webmarketingapigw för webb-BFF och marknadsföringsprocesser
  • /mobileshoppingapigw för mobila BFF- och shoppingaffärsprocesser
  • /mobilemarketingapigw för mobila BFF- och marknadsföringsprocesser

När du distribuerar till Kubernetes använder varje Ocelot API Gateway en annan "configuration.json"-fil för varje podd som kör API Gateways. Dessa "configuration.json"-filer tillhandahålls genom montering (ursprungligen med skriptet deploy.ps1) en volym som skapats baserat på en Kubernetes-konfigurationskarta med namnet "ocelot". Varje container monterar sin relaterade konfigurationsfil i containerns mapp med namnet /app/configuration.

I källkodsfilerna för eShopOnContainers finns de ursprungliga "configuration.json"-filerna i k8s/ocelot/ mappen. Det finns en fil för varje BFF/APIGateway.

Ytterligare övergripande funktioner i en Ocelot API Gateway

Det finns andra viktiga funktioner att undersöka och använda, när du använder en Ocelot API Gateway, som beskrivs i följande länkar.