Implementar Gateways de API com o OcelotImplement API Gateways with Ocelot

Os aplicativos de microsserviço de referência eShopOnContainers usam o Ocelot, um Gateway de API simples e leve que pode ser implantado em qualquer lugar, juntamente com microsserviços/contêineres, como nos ambientes a seguir usados pelo eShopOnContainers.The reference microservice application eShopOnContainers is using Ocelot, a simple and lightweight API Gateway that you can deploy anywhere along with your microservices/containers, such as in any of the following environments used by eShopOnContainers.

  • Host do docker, no computador de desenvolvimento local, localmente ou na nuvem.Docker host, in your local dev PC, on-premises or in the cloud.
  • Cluster do Kubernetes, localmente ou em nuvem gerenciada, como o AKS (Serviço de Kubernetes do Azure).Kubernetes cluster, on-premises or in managed cloud such as Azure Kubernetes Service (AKS).
  • Cluster do Service Fabric, localmente ou na nuvem.Service Fabric cluster, on-premises or in the cloud.
  • Malha do Service Fabric, como PaaS/sem servidor no Azure.Service Fabric mesh, as PaaS/Serverless in Azure.

Arquitetar e projetar seus Gateways de APIArchitect and design your API Gateways

O diagrama de arquitetura a seguir mostra como os Gateways de API são implementados com o Ocelot no eShopOnContainers.The following architecture diagram shows how API Gateways are implemented with Ocelot in eShopOnContainers.

Diagrama mostrando a arquitetura eShopOnContainers.

Figura 6-28.Figure 6-28. Arquitetura do eShopOnContainers com Gateways de APIeShopOnContainers architecture with API Gateways

Esse diagrama mostra como todo o aplicativo é implantado em um único host do Docker ou computador de desenvolvimento com o "Docker for Windows" ou o "Docker for Mac".That diagram shows how the whole application is deployed into a single Docker host or development PC with “Docker for Windows” or “Docker for Mac”. No entanto, implantar em qualquer orquestrador seria muito semelhante, mas qualquer contêiner no diagrama poderia ser expandido no orquestrador.However, deploying into any orchestrator would be pretty similar but any container in the diagram could be scaled-out in the orchestrator.

Além disso, os ativos de infraestrutura, como bancos de dados, cache e agentes de mensagens devem ser descarregados do orquestrador e implantados em sistemas altamente disponíveis para a infraestrutura, como o Banco de Dados SQL do Azure, o Azure Cosmos DB, o Redis do Azure, o Barramento de Serviço do Azure ou qualquer solução de cluster de HA local.In addition, the infrastructure assets such as databases, cache, and message brokers should be offloaded from the orchestrator and deployed into high available systems for infrastructure, like Azure SQL Database, Azure Cosmos DB, Azure Redis, Azure Service Bus, or any HA clustering solution on-premises.

Como você também pode observar no diagrama, ter vários gateways de API permite que várias equipes de desenvolvimento sejam autônomas (neste caso, recursos de marketing versus recursos de compra) ao desenvolver e implantar seus microserviços, além de seus próprios gateways de API relacionados.As you can also notice in the diagram, having several API Gateways allows multiple development teams to be autonomous (in this case Marketing features vs. Shopping features) when developing and deploying their microservices plus their own related API Gateways.

Se você tivesse um único Gateway de API monolítico, isso significaria um único ponto a ser atualizado por várias equipes de desenvolvimento, o que poderia vincular todos os microsserviços com uma única parte do aplicativo.If you had a single monolithic API Gateway that would mean a single point to be updated by several development teams, which could couple all the microservices with a single part of the application.

Avançado bastante no design, às vezes, um Gateway de API refinado também pode ser limitado a um único microsserviço de negócios, dependendo da arquitetura escolhida.Going much further in the design, sometimes a fine-grained API Gateway can also be limited to a single business microservice depending on the chosen architecture. Ter os limites de API do Gateway determinados pela empresa ou domínio ajudará a obter um melhor design.Having the API Gateway’s boundaries dictated by the business or domain will help you to get a better design.

Por exemplo, a granularidade refinada na camada do Gateway de API pode ser útil principalmente para aplicativos de interface do usuário compostos, mais avançados e baseados em microsserviços, porque o conceito de Gateway de API refinado é semelhante ao de serviço de composição de interface do usuário.For instance, fine granularity in the API Gateway tier can be especially useful for more advanced composite UI applications that are based on microservices, because the concept of a fine-grained API Gateway is similar to a UI composition service.

Apresentamos mais detalhes na seção anterior Criando uma interface do usuário composta baseada em microsserviços.We delve into more details in the previous section Creating composite UI based on microservices.

Como principal vantagem para muitos aplicativos de médio e grande porte, o uso de um produto de Gateway de API personalizado costuma ser uma boa abordagem, mas não como um único agregador monolítico ou um Gateway de API personalizado central exclusivo, a menos que esse Gateway de API permita várias áreas de configuração independentes para as diversas equipes de desenvolvimento que criam microsserviços autônomos.As key takeaway, for many medium- and large-size applications, using a custom-built API Gateway product is usually a good approach, but not as a single monolithic aggregator or unique central custom API Gateway unless that API Gateway allows multiple independent configuration areas for the several development teams creating autonomous microservices.

Microsserviços/contêineres de exemplo a serem reencaminhados por meio dos Gateways de APISample microservices/containers to re-route through the API Gateways

Por exemplo, o eShopOnContainers tem cerca de seis tipos de microsserviços internos que precisam ser publicados por meio dos Gateways de API, conforme mostrado na imagem a seguir.As an example, eShopOnContainers has around six internal microservice-types that have to be published through the API Gateways, as shown in the following image.

Captura de tela da pasta serviços mostrando suas subpastas.

Figura 6-29.Figure 6-29. Pastas do microsserviço na solução eShopOnContainers no Visual StudioMicroservice folders in eShopOnContainers solution in Visual Studio

Sobre o serviço de Identidade, no design, ele fica fora do roteamento do Gateway de API porque é o único interesse paralelo no sistema, embora com o Ocelot também seja possível incluí-lo como parte das listas de reencaminhamento.About the Identity service, in the design it's left out of the API Gateway routing because it's the only cross-cutting concern in the system, although with Ocelot it's also possible to include it as part of the rerouting lists.

Todos esses serviços são implementados atualmente como serviços de API Web do ASP.NET Core, como você pode observar no código.All those services are currently implemented as ASP.NET Core Web API services, as you can tell from the code. Vamos nos concentrar em um dos microsserviços, como o código do microsserviço Catálogo.Let’s focus on one of the microservices like the Catalog microservice code.

Captura de tela de Gerenciador de Soluções mostrando o conteúdo do projeto Catalog. API.

Figura 6-30.Figure 6-30. Microsserviço de API Web de exemplo (microsserviço Catálogo)Sample Web API microservice (Catalog microservice)

Você pode ver que o microsserviço Catálogo é um projeto de API Web ASP.NET Core típico com vários controladores e métodos como no código a seguir.You can see that the Catalog microservice is a typical ASP.NET Core Web API project with several controllers and methods like in the following code.

[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 solicitação HTTP acabará executando esse tipo de código C# acessando o banco de dados de microsserviço e qualquer ação adicional necessária.The HTTP request will end up running that kind of C# code accessing the microservice database and any additional required action.

Em relação à URL do microsserviço, quando os contêineres são implantados no computador de desenvolvimento local (host do Docker local), cada contêiner do microsserviço tem sempre uma porta interna (geralmente, a porta 80) especificada em seu Dockerfile, como no seguinte Dockerfile:Regarding the microservice URL, when the containers are deployed in your local development PC (local Docker host), each microservice’s container has always an internal port (usually port 80) specified in its dockerfile, as in the following dockerfile:

FROM microsoft/aspnetcore:2.0.5 AS base
WORKDIR /app
EXPOSE 80

A porta 80 mostrada no código é interna no host do Docker e, portanto, não pode ser acessada por aplicativos cliente.The port 80 shown in the code is internal within the Docker host, so it can't be reached by client apps.

Os aplicativos cliente poderão acessar apenas as portas externas (se houver) publicadas durante a implantação com docker-compose.Client apps can access only the external ports (if any) published when deploying with docker-compose.

Essas portas externas não devem ser publicadas durante a implantação em um ambiente de produção.Those external ports shouldn't be published when deploying to a production environment. Esse é exatamente o motivo para usar o Gateway de API, ou seja, para evitar a comunicação direta entre os aplicativos clientes e os microsserviços.This is precisely why you want to use the API Gateway, to avoid the direct communication between the client apps and the microservices.

No entanto, durante o desenvolvimento, é necessário acessar o microsserviço/contêiner diretamente e executá-lo por meio do Swagger.However, when developing, you want to access the microservice/container directly and run it through Swagger. É por isso que no eShopOnContainers as portas externas são especificadas mesmo quando elas não precisam ser usadas pelo Gateway de API ou por aplicativos clientes.That’s why in eShopOnContainers, the external ports are still specified even when they won’t be used by the API Gateway or the client apps.

Aqui está um exemplo do arquivo docker-compose.override.yml para o microsserviço de catálogo:Here’s an example of the docker-compose.override.yml file for the Catalog microservice:

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

Você pode ver como na configuração do docker-compose.override.yml a porta interna do contêiner de catálogo é a porta 80, mas a porta para acesso externo é a 5101.You can see how in the docker-compose.override.yml configuration the internal port for the Catalog container is port 80, but the port for external access is 5101. Mas essa porta não deve ser usada pelo aplicativo quando um Gateway de API é usado, apenas para depurar, executar e testar somente o microsserviço Catálogo.But this port shouldn’t be used by the application when using an API Gateway, only to debug, run and test just the Catalog microservice.

Normalmente, não se implanta com o docker-compose em um ambiente de produção porque o ambiente de implantação de produção certo para microsserviços é um orquestrador como o Kubernetes ou o Service Fabric.Normally, you won’t be deploying with docker-compose into a production environment because the right production deployment environment for microservices is an orchestrator like Kubernetes or Service Fabric. Ao implantar nesses ambientes, use arquivos de configuração diferentes nos quais você não publica diretamente nenhuma porta externa para os microsserviços, mas sempre usa o proxy reverso do Gateway de API.When deploying to those environments you use different configuration files where you won’t publish directly any external port for the microservices but, you'll always use the reverse proxy from the API Gateway.

Execute o microsserviço de catálogo no host do Docker local seja executando a solução eShopOnContainers completa por meio do Visual Studio (ela executará todos os serviços nos arquivos docker-compose) ou apenas iniciando o microsserviço de catálogo com o seguinte comando docker-compose no CMD ou no PowerShell, localizado na pasta onde o docker-compose.yml e o docker-compose.override.yml estão localizados.Run the catalog microservice in your local Docker host either by running the full eShopOnContainers solution from Visual Studio (it’ll run all the services in the docker-compose files) or just starting the Catalog microservice with the following docker-compose command in CMD or PowerShell positioned at the folder where the docker-compose.yml and docker-compose.override.yml are placed.

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

Esse comando executa apenas o contêiner de serviço catalog.api e as dependências especificadas no docker-compose.yml.This command only runs the catalog.api service container plus dependencies that are specified in the docker-compose.yml. Nesse caso, o contêiner do SQL Server e o contêiner do RabbitMQ.In this case, the SQL Server container and RabbitMQ container.

Em seguida, você pode acessar diretamente o microsserviço de Catálogo e ver seus métodos por meio da interface do usuário do Swagger, acessando-o diretamente por essa porta “externa”, nesse caso, http://localhost:5101/swagger:Then, you can directly access the Catalog microservice and see its methods through the Swagger UI accessing directly through that “external” port, in this case http://localhost:5101/swagger:

Captura de tela da interface do usuário do Swagger mostrando a API REST do Catalog. API.

Figura 6-31.Figure 6-31. Testando o microsserviço Catálogo com sua interface do usuário do SwaggerTesting the Catalog microservice with its Swagger UI

Neste ponto, você pode definir um ponto de interrupção no código C# no Visual Studio, testar o microsserviço com os métodos expostos na interface do usuário do Swagger e, por fim, limpar tudo com o comando docker-compose down.At this point, you could set a breakpoint in C# code in Visual Studio, test the microservice with the methods exposed in Swagger UI, and finally clean-up everything with the docker-compose down command.

No entanto, a comunicação de acesso direto com o microsserviço, nesse caso, pela porta 5101 externa, é exatamente o que você deseja evitar em seu aplicativo.However, direct-access communication to the microservice, in this case through the external port 5101, is precisely what you want to avoid in your application. E você pode evitar isso definindo o nível adicional de indireção do Gateway de API (o Ocelot, neste caso).And you can avoid that by setting the additional level of indirection of the API Gateway (Ocelot, in this case). Dessa forma, o aplicativo cliente não acessará o microsserviço diretamente.That way, the client app won’t directly access the microservice.

Implementando Gateways de API com o OcelotImplementing your API Gateways with Ocelot

O Ocelot é basicamente um conjunto de middleware que você pode aplicar em uma ordem específica.Ocelot is basically a set of middlewares that you can apply in a specific order.

O Ocelot foi projetado para funcionar apenas com o ASP.NET Core.Ocelot is designed to work with ASP.NET Core only. Ele é direcionado ao netstandard2.0, portanto, pode ser usado em qualquer local com suporte para o .NET Standard 2.0, incluindo o runtime do .NET Core 2.0 e o runtime do .NET Framework 4.6.1 e superiores.It targets netstandard2.0 so it can be used anywhere .NET Standard 2.0 is supported, including .NET Core 2.0 runtime and .NET Framework 4.6.1 runtime and up.

Instale o Ocelot e suas dependências no projeto ASP.NET Core com o pacote NuGet do Ocelot, por meio do Visual Studio.You install Ocelot and its dependencies in your ASP.NET Core project with Ocelot's NuGet package, from Visual Studio.

Install-Package Ocelot

No eShopOnContainers, a implementação do Gateway de API é um projeto simples de WebHost do ASP.NET Core, além disso, o middleware do Ocelot lida com todos os recursos do Gateway de API, conforme é mostrado na imagem a seguir:In eShopOnContainers, its API Gateway implementation is a simple ASP.NET Core WebHost project, and Ocelot’s middlewares handle all the API Gateway features, as shown in the following image:

Captura de tela de Gerenciador de Soluções mostrando o projeto de gateway de API do Ocelot.

Figura 6-32.Figure 6-32. Projeto base OcelotApiGw no eShopOnContainersThe OcelotApiGw base project in eShopOnContainers

Basicamente, este projeto WebHost do ASP.NET Core é criado com dois arquivos simples: Program.cs e Startup.cs.This ASP.NET Core WebHost project is basically built with two simple files: Program.cs and Startup.cs.

O Program.cs precisa apenas criar e configurar o BuildWebHost típico do ASP.NET Core.The Program.cs just needs to create and configure the typical 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;
        }
    }
}

O ponto importante para Ocelot é o arquivo configuration.json que você precisa fornecer para o construtor pelo método AddJsonFile().The important point here for Ocelot is the configuration.json file that you must provide to the builder through the AddJsonFile() method. Esse configuration.json é onde você especifica todos os reencaminhamentos do Gateway de API, o que significa os pontos de extremidade externos com portas específicas e os pontos de extremidade internos correlacionados, geralmente usando portas diferentes.That configuration.json is where you specify all the API Gateway ReRoutes, meaning the external endpoints with specific ports and the correlated internal endpoints, usually using different ports.

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

Há duas seções para a configuração.There are two sections to the configuration. Uma matriz de reencaminhamento e um GlobalConfiguration.An array of Re-Routes and a GlobalConfiguration. Os reencaminhamentos são os objetos que dizem ao Ocelot como tratar uma solicitação de upstream.The Re-Routes are the objects that tell Ocelot how to treat an upstream request. A configuração Global permite substituições das configurações específicas de reencaminhamento.The Global configuration allows overrides of Re-Route specific settings. Ela é útil quando não se deseja gerenciar muita configurações específicas de reencaminhamento.It’s useful if you don’t want to manage lots of Re-Route specific settings.

Veja a seguir um exemplo simplificado do arquivo de configuração de Reencaminhamento de um dos Gateways de API do eShopOnContainers.Here’s a simplified example of ReRoute configuration file from one of the API Gateways from 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"
    }
  }

A funcionalidade principal de um Gateway de API Ocelot é obter solicitações HTTP de entrada e encaminhá-las para um serviço downstream, simultaneamente à outra solicitação HTTP.The main functionality of an Ocelot API Gateway is to take incoming HTTP requests and forward them on to a downstream service, currently as another HTTP request. O Ocelot descreve o encaminhamento de uma solicitação para outra como um reencaminhamento.Ocelot’s describes the routing of one request to another as a Re-Route.

Por exemplo, vamos nos concentrar em um dos reencaminhamentos no configuration.json mencionado acima, a configuração do microsserviço Cesta.For instance, let’s focus on one of the Re-Routes in the configuration.json from above, the configuration for the Basket microservice.

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

O DownstreamPathTemplate, o esquema e o DownstreamHostAndPorts compõem a URL interna do microsserviço ao qual essa solicitação será encaminhada.The DownstreamPathTemplate, Scheme, and DownstreamHostAndPorts make the internal microservice URL that this request will be forwarded to.

A porta é a porta interna usada pelo serviço.The port is the internal port used by the service. Ao usar contêineres, é a porta especificada no dockerfile.When using containers, the port specified at its dockerfile.

O Host é um nome de serviço que depende da resolução de nomes de serviço que você está usando.The Host is a service name that depends on the service name resolution you are using. Quando o docker-compose é usado, os serviços de nomes são fornecidos pelo Host do Docker, que está usando os nomes de serviço fornecidos nos arquivos docker-compose.When using docker-compose, the services names are provided by the Docker Host, which is using the service names provided in the docker-compose files. Quando é usado um orquestrador, como o Kubernetes ou o Service Fabric, esse nome deve ser resolvido pelo DNS ou pela resolução de nomes fornecida por cada orquestrador.If using an orchestrator like Kubernetes or Service Fabric, that name should be resolved by the DNS or name resolution provided by each orchestrator.

DownstreamHostAndPorts é uma matriz que contém o host e a porta de todos os serviços downstream para os quais você deseja encaminhar solicitações.DownstreamHostAndPorts is an array that contains the host and port of any downstream services that you wish to forward requests to. Normalmente, ela conterá apenas uma entrada, mas, às vezes, convém balancear a carga de solicitações para os serviços downstream e, para isso, o Ocelot permite que você adicione mais de uma entrada e, em seguida, selecione um balanceador de carga.Usually this will just contain one entry but sometimes you might want to load balance requests to your downstream services and Ocelot lets you add more than one entry and then select a load balancer. Mas se você estiver usando o Azure e algum orquestrador, provavelmente, será melhor balancear a carga com a infraestrutura de nuvem e do orquestrador.But if using Azure and any orchestrator it is probably a better idea to load balance with the cloud and orchestrator infrastructure.

O UpstreamPathTemplate é a URL que o Ocelot usará para identificar qual DownstreamPathTemplate será usado para uma determinada solicitação do cliente.The UpstreamPathTemplate is the URL that Ocelot will use to identify which DownstreamPathTemplate to use for a given request from the client. Por fim, o UpstreamHttpMethod é usado para que Ocelot possa distinguir entre diferentes solicitações (GET, POST, PUT) para a mesma URL.Finally, the UpstreamHttpMethod is used so Ocelot can distinguish between different requests (GET, POST, PUT) to the same URL.

Neste ponto, você poderia usar um único Gateway de API do Ocelot (WebHost do ASP.NET Core), com um ou vários arquivos configuration.json mesclados, ou armazenar a configuração em um repositório KV Consul.At this point, you could have a single Ocelot API Gateway (ASP.NET Core WebHost) using one or multiple merged configuration.json files or you can also store the configuration in a Consul KV store.

Mas, conforme apresentado nas seções de arquitetura e design, se você realmente deseja usar microsserviços autônomos, talvez seja melhor dividir esse único Gateway de API monolítico em vários Gateways de API e/ou BFFs (back-end para front-end).But as introduced in the architecture and design sections, if you really want to have autonomous microservices, it might be better to split that single monolithic API Gateway into multiple API Gateways and/or BFF (Backend for Frontend). Para isso, vamos ver como implementar essa abordagem com contêineres do Docker.For that purpose, let’s see how to implement that approach with Docker containers.

Usando uma única imagem de contêiner do Docker para executar o vários Gateway de API diferentes ou tipos de BFF contêineresUsing a single Docker container image to run multiple different API Gateway / BFF container types

No eShopOnContainers, estamos usando uma única imagem de contêiner do Docker com o Gateway de API do Ocelot, mas, em seguida, em tempo de execução, criamos serviços/contêineres diferentes para cada tipo de Gateway de API/BFF fornecendo um arquivo configuration.json diferente, usando um volume do Docker para acessar uma pasta de computador diferente para cada serviço.In eShopOnContainers we’re using a single Docker container image with the Ocelot API Gateway but then, at run time, we create different services/containers for each type of API-Gateway/BFF by providing a different configuration.json file, using a docker volume to access a different PC folder for each service.

Diagrama de uma única imagem do Docker de gateway Ocelot para todos os gateways de API.

Figura 6-33.Figure 6-33. Reutilizando uma única imagem do Docker do Ocelot em vários tipos de Gateway de APIRe-using a single Ocelot Docker image across multiple API Gateway types

No eShopOnContainers, a "imagem genérica do Docker do Gateway de API" é criada com o projeto chamado 'OcelotApiGw' e a imagem de nome "eshop/ocelotapigw" que é especificada no arquivo docker-compose.yml.In eShopOnContainers, the “Generic Ocelot API Gateway Docker Image” is created with the project named 'OcelotApiGw' and the image name “eshop/ocelotapigw” that is specified in the docker-compose.yml file. Em seguida, ao implantar no Docker, haverá quatro contêineres de Gateway de API criados com essa mesma imagem do Docker, conforme é mostrado na seguinte extração do arquivo docker-compose.yml.Then, when deploying to Docker, there will be four API-Gateway containers created from that same Docker image, as shown in the following extract from the docker-compose.yml file.

  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

Além disso, como você pode ver no arquivo docker-compose.override.yml a seguir, a única diferença entre esses contêineres de Gateway de API é o arquivo de configuração do Ocelot, que é diferente para cada contêiner de serviço e é especificado em runtime por meio de um volume do Docker.Additionally, as you can see in the following docker-compose.override.yml file, the only difference between those API Gateway containers is the Ocelot configuration file, which is different for each service container and it's specified at runtime through a Docker volume.

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

Devido ao código anterior e, como é mostrado no Gerenciador do Visual Studio abaixo, o único arquivo necessário para definir cada Gateway de API de negócios/BFF é apenas um arquivo configuration.json, porque os quatro Gateways de API são baseados na mesma imagem do Docker.Because of that previous code, and as shown in the Visual Studio Explorer below, the only file needed to define each specific business/BFF API Gateway is just a configuration.json file, because the four API Gateways are based on the same Docker image.

Captura de tela mostrando todos os gateways de API com arquivos. JSON de configuração.

Figura 6-34.Figure 6-34. O único arquivo necessário para definir cada Gateway de API/BFF com o Ocelot é um arquivo de configuraçãoThe only file needed to define each API Gateway / BFF with Ocelot is a configuration file

Dividindo o Gateway de API em vários Gateways de API, diferentes equipes de desenvolvimento concentrando-se em diferentes subconjuntos de microsserviços podem gerenciar seus próprios Gateways de API usando arquivos de configuração do Ocelot independentes.By splitting the API Gateway into multiple API Gateways, different development teams focusing on different subsets of microservices can manage their own API Gateways by using independent Ocelot configuration files. Além disso, ao mesmo tempo, elas podem reutilizar a mesma imagem do Docker do Ocelot.Plus, at the same time they can reuse the same Ocelot Docker image.

Agora, se você executar o eShopOnContainers com os Gateways de API (incluídos por padrão no VS quando uma solução eShopOnContainers-ServicesAndWebApps.sln é aberta ou quando o "docker-compose up" é executado), as rotas de exemplo a seguir serão executadas.Now, if you run eShopOnContainers with the API Gateways (included by default in VS when opening eShopOnContainers-ServicesAndWebApps.sln solution or if running “docker-compose up”), the following sample routes will be performed.

Por exemplo, ao visitar a URL upstream http://localhost:5202/api/v1/c/catalog/items/2/ atendida pelo Gateway de API webshoppingapigw, você obterá o mesmo resultado da URL Downstream interna http://catalog.api/api/v1/2 dentro do host do Docker, como no navegador a seguir.For instance, when visiting the upstream URL http://localhost:5202/api/v1/c/catalog/items/2/ served by the webshoppingapigw API Gateway, you get the same result from the internal Downstream URL http://catalog.api/api/v1/2 within the Docker host, as in the following browser.

Captura de tela de um navegador mostrando uma resposta que passa pelo gateway de API.

Figura 6-35.Figure 6-35. Acessando um microsserviço por meio de uma URL fornecida pelo Gateway de APIAccessing a microservice through a URL provided by the API Gateway

Por motivos de teste ou depuração, se você quiser acessar diretamente o contêiner do Docker do Catálogo (somente no ambiente de desenvolvimento) sem passar pelo Gateway de API, como 'catalog.api' é uma resolução de DNS interna do host do Docker (descoberta de serviço manipulada pelos nomes de serviço do docker-compose), a única maneira de acessar diretamente o contêiner será por meio da porta externa publicada em docker-compose.override.yml, que é fornecida apenas para testes de desenvolvimento, como http://localhost:5101/api/v1/Catalog/items/1 no navegador a seguir.Because of testing or debugging reasons, if you wanted to directly access to the Catalog Docker container (only at the development environment) without passing through the API Gateway, since 'catalog.api' is a DNS resolution internal to the Docker host (service discovery handled by docker-compose service names), the only way to directly access the container is through the external port published in the docker-compose.override.yml, which is provided only for development tests, such as http://localhost:5101/api/v1/Catalog/items/1 in the following browser.

Captura de tela de um navegador que mostra uma resposta direta para o Catalog. API.

Figura 6-36.Figure 6-36. Acesso direto a um microsserviço para fins de testeDirect access to a microservice for testing purposes

Mas o aplicativo está configurado para acessar todos os microsserviços por meio dos Gateways de API, não pela porta direta "atalhos".But the application is configured so it accesses all the microservices through the API Gateways, not though the direct port “shortcuts”.

O padrão de agregação do Gateway em eShopOnContainersThe Gateway aggregation pattern in eShopOnContainers

Conforme apresentado anteriormente, uma maneira flexível de implementar a agregação de solicitações é com os serviços personalizados, por código.As introduced previously, a flexible way to implement requests aggregation is with custom services, by code. Você também pode implementar a agregação de solicitação com a funcionalidade de Agregação de Solicitação no Ocelot, mas talvez essa opção não seja flexível o suficiente.You could also implement request aggregation with the Request Aggregation feature in Ocelot, but it might not be as flexible as you need. Portanto, a maneira selecionada de implementar a agregação em eShopOnContainers é com um serviços da API Web ASP.NET Core explícitos para cada agregador.Therefore, the selected way to implement aggregation in eShopOnContainers is with an explicit ASP.NET Core Web API services for each aggregator.

De acordo com essa abordagem, o diagrama de composição do Gateway de API é, na realidade, um pouco mais amplo ao considerar os serviços de agregador que não são mostrados no diagrama de arquitetura global simplificado mostrado anteriormente.According to that approach, the API Gateway composition diagram is in reality a bit more extended when considering the aggregator services that are not shown in the simplified global architecture diagram shown previously.

No diagrama a seguir, você também poderá ver como os serviços do agregador funcionam com seus Gateways de API relacionados.In the following diagram, you can also see how the aggregator services work with their related API Gateways.

Diagrama da arquitetura eShopOnContainers que mostra os serviços do agregador.

Figura 6-37.Figure 6-37. Arquitetura de eShopOnContainers com serviços do agregadoreShopOnContainers architecture with aggregator services

Ampliando ainda mais, na área de negócios “Compras” na imagem a seguir, você pode ver que o número de chamadas entre os aplicativos cliente e os microsserviços é reduzido ao usar os serviços de agregador nos Gateways de API.Zooming in further, on the “Shopping” business area in the following image, you can see that chattiness between the client apps and the microservices is reduced when using the aggregator services in the API Gateways.

Diagrama mostrando o zoom da arquitetura eShopOnContainers.

Figura 6-38.Figure 6-38. Visão ampliada do agregador de serviçosZoom in vision of the Aggregator services

Você pode observar como a complexidade aumenta quando o diagrama mostra as possíveis solicitações provenientes dos Gateways de API.You can notice how when the diagram shows the possible requests coming from the API Gateways it can get pretty complex. Apesar disso, veja como as setas em azul seriam simplificadas, da perspectiva dos aplicativos clientes, ao usar o padrão de agregador reduzindo o excesso de comunicação e a latência na comunicação, por fim, melhorando significativamente a experiência do usuário para os aplicativos remotos ( aplicativos móveis e SPA), principalmente.Although you can see how the arrows in blue would be simplified, from a client apps perspective, when using the aggregator pattern by reducing chattiness and latency in the communication, ultimately significantly improving the user experience for the remote apps (mobile and SPA apps), especially.

A área de negócios e de microsserviços de "Marketing" é um caso de uso muito simples, portanto, não há necessidade de usar agregadores, mas, se fosse necessário, também seria possível.In the case of the “Marketing” business area and microservices, it is a very simple use case so there was no need to use aggregators, but it could also be possible, if needed.

Autenticação e autorização em Gateways de API do OcelotAuthentication and authorization in Ocelot API Gateways

Em um Gateway de API do Ocelot, você pode usar o serviço de autenticação, como um serviço de API Web ASP.NET Core, usando IdentityServer e fornecendo o token de autenticação dentro ou fora do Gateway de API.In an Ocelot API Gateway you can sit the authentication service, such as an ASP.NET Core Web API service using IdentityServer providing the auth token, either out or inside the API Gateway.

Como o eShopOnContainers está usando vários Gateways de API com limites baseados em BFF e em áreas de negócios, o serviço de identidade/autenticação é deixado de fora dos Gateways de API, conforme está realçado em amarelo no diagrama a seguir.Since eShopOnContainers is using multiple API Gateways with boundaries based on BFF and business areas, the Identity/Auth service is left out of the API Gateways, as highlighted in yellow in the following diagram.

Diagrama mostrando o microserviço de identidade sob o gateway de API.

Figura 6-39.Figure 6-39. A posição do serviço de identidade em eShopOnContainersPosition of the Identity service in eShopOnContainers

No entanto, o Ocelot também dá suporte ao uso do microsserviço de Identidade/Autenticação dentro do limite do Gateway de API, como neste outro diagrama.However, Ocelot also supports sitting the Identity/Auth microservice within the API Gateway boundary, as in this other diagram.

Diagrama mostrando a autenticação em um gateway de API do Ocelot.

Figura 6-40.Figure 6-40. Autenticação no OcelotAuthentication in Ocelot

Como mostra o diagrama anterior, quando o microserviço de identidade está abaixo do gateway de API (AG): 1) o AG solicita um token de autenticação do microserviço de identidade, 2) o microserviço de identidade retorna token para AG, 3-4) solicitações AG de microserviços usando o token de autenticação.As the previous diagram shows, when the Identity microservice is beneath the API gateway (AG): 1) AG requests an auth token from identity microservice, 2) The identity microservice returns token to AG, 3-4) AG requests from microservices using the auth token. Como o aplicativo eShopOnContainers dividiu o Gateway de API em vários Gateways de API de BFF (back-end para front-end) e de áreas de negócios, outra opção seria criar um Gateway de API adicional para interesses paralelos.Because eShopOnContainers application has split the API Gateway into multiple BFF (Backend for Frontend) and business areas API Gateways, another option would had been to create an additional API Gateway for cross-cutting concerns. Essa opção seria razoável em uma arquitetura de microsserviço bem mais complexa com vários microsserviços de interesses paralelos.That choice would be fair in a more complex microservice based architecture with multiple cross-cutting concerns microservices. Como há apenas um interesse paralelo no eShopOnContainers, foi decidido apenas lidar com o serviço de segurança fora do realm do Gateway de API, para simplificar.Since there's only one cross-cutting concern in eShopOnContainers, it was decided to just handle the security service out of the API Gateway realm, for simplicity’s sake.

Em qualquer caso, se o aplicativo estiver protegido no nível do Gateway de API, o módulo de autenticação do Gateway de API do Ocelot será acessado primeiro quando houver uma tentativa de usar qualquer microsserviço protegido.In any case, if the app is secured at the API Gateway level, the authentication module of the Ocelot API Gateway is visited at first when trying to use any secured microservice. Isso redireciona a solicitação HTTP para acessar o microsserviço de identidade ou de autenticação para obter o token de acesso que permitirá acessar os serviços protegidos com o access_token.That re-directs the HTTP request to visit the Identity or auth microservice to get the access token so you can visit the protected services with the access_token.

É a maneira de proteger com autenticação qualquer serviço no nível do Gateway de API é definir o AuthenticationProviderKey em suas configurações relacionadas no configuration.json.The way you secure with authentication any service at the API Gateway level is by setting the AuthenticationProviderKey in its related settings at the configuration.json.

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

Quando o Ocelot for executado, ele examinará os reencaminhamentos AuthenticationOptions.AuthenticationProviderKey e verificará se há um provedor de autenticação registrado com a chave especificada.When Ocelot runs, it will look at the Re-Routes AuthenticationOptions.AuthenticationProviderKey and check that there is an Authentication Provider registered with the given key. Se não houver, o Ocelot não será iniciado.If there isn't, then Ocelot will not start up. Se houver, o reencaminhamento usará esse provedor quando for executado.If there is, then the ReRoute will use that provider when it executes.

Como o WebHost do Ocelot é configurado com o authenticationProviderKey = "IdentityApiKey", ele exigirá a autenticação sempre que esse serviço tiver alguma solicitação sem nenhum token de autenticação.Because the Ocelot WebHost is configured with the authenticationProviderKey = "IdentityApiKey", that will require authentication whenever that service has any requests without any auth token.

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

Em seguida, você também precisará definir a autorização com o atributo [Authorize] nos recursos a serem acessados, como os microsserviços, como no seguinte controlador do microsserviço Cesta.Then, you also need to set authorization with the [Authorize] attribute on any resource to be accessed like the microservices, such as in the following Basket microservice controller.

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

Os ValidAudiences como "cesta" são correlacionados à audiência definida em cada microsserviço com AddJwtBearer() no ConfigureServices() da classe de inicialização, como no código a seguir.The ValidAudiences such as “basket” are correlated with the audience defined in each microservice with AddJwtBearer() at the ConfigureServices() of the Startup class, such as in the code below.

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

Se você tentar acessar qualquer microsserviço protegido, como o microsserviço de Cesta, com uma URL de Reencaminhamento baseada no Gateway de API como http://localhost:5202/api/v1/b/basket/1, ocorrerá um erro 401 Não Autorizado, a menos que você forneça um token válido.If you try to access any secured microservice, like the Basket microservice with a Re-Route URL based on the API Gateway like http://localhost:5202/api/v1/b/basket/1, then you’ll get a 401 Unauthorized unless you provide a valid token. Por outro lado, se uma URL de reencaminhamento for autenticada, o Ocelot invocará qualquer esquema downstream associado a ela (a URL interna do microsserviço).On the other hand, if a Re-Route URL is authenticated, Ocelot will invoke whatever downstream scheme is associated with it (the internal microservice URL).

Autorização na camada de Reencaminhamento do Ocelot.Authorization at Ocelot’s ReRoutes tier. O Ocelot dá suporte a autorização baseada em declarações avaliada após a autenticação.Ocelot supports claims-based authorization evaluated after the authentication. Defina a autorização em um nível de rota adicionando as linhas a seguir à configuração de Reencaminhamento.You set the authorization at a route level by adding the following lines to the ReRoute configuration.

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

Nesse exemplo, quando o middleware de autorização for chamado, o Ocelot descobrirá se o usuário tem o tipo de declaração 'UserType' no token e se o valor dessa declaração é 'employee'.In that example, when the authorization middleware is called, Ocelot will find if the user has the claim type 'UserType' in the token and if the value of that claim is 'employee'. Se não for, o usuário não será autorizado e a resposta será 403 Proibido.If it isn’t, then the user will not be authorized and the response will be 403 forbidden.

Usando a entrada do Kubernetes e os Gateways de API do OcelotUsing Kubernetes Ingress plus Ocelot API Gateways

Ao usar o Kubernetes (como em um cluster do Serviço de Kubernetes do Azure), você geralmente unifica todas as solicitações HTTP por meio da camada de Entrada do Kubernetes com base no Nginx.When using Kubernetes (like in an Azure Kubernetes Service cluster), you usually unify all the HTTP requests through the Kubernetes Ingress tier based on Nginx.

No Kubernetes, se você não usar qualquer abordagem de entrada, os seus serviços e pods terão IPs que poderão ser encaminhados apenas pela rede de cluster.In Kubernetes, if you don’t use any ingress approach, then your services and pods have IPs only routable by the cluster network.

Mas se você usar uma abordagem de entrada, haverá uma camada intermediária entre a Internet e seus serviços (incluindo seus Gateways de API), atuando como um proxy reverso.But if you use an ingress approach, you'll have a middle tier between the Internet and your services (including your API Gateways), acting as a reverse proxy.

Como uma definição, uma entrada é uma coleção de regras que permitem que conexões de entrada acessem os serviços de cluster.As a definition, an Ingress is a collection of rules that allow inbound connections to reach the cluster services. Uma entrada é geralmente configurada para fornecer aos serviços URLs acessadas externamente, balancear a carga do tráfego, terminação SSL e muito mais.An ingress is usually configured to provide services externally reachable URLs, load balance traffic, SSL termination and more. Os usuários solicitam a entrada postando o recurso de entrada no servidor de API.Users request ingress by POSTing the Ingress resource to the API server.

Em eShopOnContainers, ao desenvolver localmente e usar apenas o computador de desenvolvimento como o host do Docker, você não está usando nenhuma entrada, mas apenas vários Gateways de API.In eShopOnContainers, when developing locally and using just your development machine as the Docker host, you are not using any ingress but only the multiple API Gateways.

No entanto, ao direcionar a um ambiente de "produção" baseado no Kubernetes, o eShopOnContainers está usando uma entrada na frente dos gateways de API.However, when targeting a “production” environment based on Kubernetes, eShopOnContainers is using an ingress in front of the API gateways. Dessa forma, os clientes ainda chamam a mesma URL base, mas as solicitações são encaminhadas para vários Gateways de API ou BFFs.That way, the clients still call the same base URL but the requests are routed to multiple API Gateways or BFF.

Observe que os Gateways de API são front-ends ou fachadas que mostram somente os serviços, mas não os aplicativos Web que normalmente estão fora de seu escopo.Note that API Gateways are front-ends or façades surfacing only the services but not the web applications that are usually out of their scope. Além disso, os Gateways de API podem ocultar determinados microsserviços internos.In addition, the API Gateways might hide certain internal microservices.

A entrada, no entanto, está apenas redirecionando solicitações HTTP, mas não está tentando ocultar nenhum microsserviço ou aplicativo Web.The ingress, however, is just redirecting HTTP requests but not trying to hide any microservice or web app.

A arquitetura ideal é uma camada Nginx de entrada no Kubernetes na frente dos aplicativos Web além de vários Gateways de API/BFF do Ocelot, conforme é mostrado no diagrama a seguir.Having an ingress Nginx tier in Kubernetes in front of the web applications plus the several Ocelot API Gateways / BFF is the ideal architecture, as shown in the following diagram.

Um diagrama que mostra como uma camada de entrada se encaixa no ambiente AKS.

Figura 6-41.Figure 6-41. A camada de entrada em eShopOnContainers, quando implantada no KubernetesThe ingress tier in eShopOnContainers when deployed into Kubernetes

Uma Entrada do Kubernetes funciona como um proxy reverso para todo o tráfego para o aplicativo, incluindo os aplicativos Web, que geralmente estão fora do escopo do gateway de API.A Kubernetes Ingress acts as a reverse proxy for all traffic to the app, including the web applications, that are usually out of the Api gateway scope. Quando você implanta o eShopOnContainers no Kubernetes, ele expõe apenas alguns serviços ou pontos de extremidade via entrada, ou seja, basicamente, a seguinte lista de pós-fixados nas URLs:When you deploy eShopOnContainers into Kubernetes, it exposes just a few services or endpoints via ingress, basically the following list of postfixes on the URLs:

  • / para o aplicativo Web cliente SPA/ for the client SPA web application
  • /webmvc para o aplicativo Web cliente MVC/webmvc for the client MVC web application
  • /webstatus para o aplicativo Web cliente mostrando o status e as verificações de integridade/webstatus for the client web app showing the status/healthchecks
  • /webshoppingapigw para os processos de negócios Web BFF e de compras/webshoppingapigw for the web BFF and shopping business processes
  • /webmarketingapigw para os processos de negócios Web BFF e de marketing/webmarketingapigw for the web BFF and marketing business processes
  • /mobileshoppingapigw para os processos de negócios móveis BFF e de compras/mobileshoppingapigw for the mobile BFF and shopping business processes
  • /mobilemarketingapigw para os processos de negócios móveis BFF e de marketing/mobilemarketingapigw for the mobile BFF and marketing business processes

Ao implantar no Kubernetes, cada Gateway de API do Ocelot está usando um arquivo “configuration.json” diferente para cada pod que executa os Gateways de API.When deploying to Kubernetes, each Ocelot API Gateway is using a different “configuration.json” file for each pod running the API Gateways. Esses arquivos de "configuration.json" são fornecidos pela montagem (originalmente com o script deploy.ps1) de um volume criado com base em um mapa de configuração do Kubernetes chamado 'ocelot'.Those “configuration.json” files are provided by mounting (originally with the deploy.ps1 script) a volume created based on a Kubernetes config map named ‘ocelot’. Cada contêiner monta seu arquivo de configuração relacionado na pasta do contêiner chamada /app/configuration.Each container mounts its related configuration file in the container’s folder named /app/configuration.

Nos arquivos de código-fonte do eShopOnContainers, os arquivos “configuration.json” originais podem ser encontrados na pasta k8s/ocelot/.In the source code files of eShopOnContainers, the original “configuration.json” files can be found within the k8s/ocelot/ folder. Há um arquivo para cada BFF/APIGateway.There’s one file for each BFF/APIGateway.

Recursos de interesses paralelos adicionais em um Gateway de API do OcelotAdditional cross-cutting features in an Ocelot API Gateway

Há outros recursos importantes que podem ser pesquisados e usados ao usar um Gateway de API do Ocelot, descritos nos links a seguir.There are other important features to research and use, when using an Ocelot API Gateway, described in the following links.