共用方式為


使用 Ocelot 實作 API 閘道

小提示

此內容是適用於容器化 .NET 應用程式的電子書.NET 微服務架構摘錄,可在 .NET Docs 或免費下載的 PDF 中取得,可脫機讀取。

.NET 微服務架構的容器化 .NET 應用程式電子書封面縮圖。

這很重要

參考微服務應用程式 eShopOnContainers 目前使用 Envoy 所提供的功能來實作 API 閘道,而不是先前參考的 Ocelot。 由於 Envoy 對 WebSocket 通訊協定的內建支援,因此我們在 eShopOnContainers 中實作的新 gRPC 服務間通訊需要此設計選擇。 不過,我們已在指南中保留本節,因此您可以將 Ocelot 視為適用於生產等級案例的簡單、有能力和輕量型的 API 閘道。 此外,最新的 Ocelot 版本包含其 json 架構的重大變更。 請考慮使用 Ocelot < v16.0.0,或使用密鑰 Route,而不是 ReRoutes。

建構和設計 API 閘道

下列架構圖顯示如何在 eShopOnContainers 中使用 Ocelot 實作 API 閘道。

顯示 eShopOnContainers 架構的圖表。

圖 6-28。 使用 API 閘道的 eShopOnContainers 架構

此圖顯示如何將整個應用程式部署到具有「Docker for Windows」或「Docker for Mac」的單一 Docker 主機或開發電腦。 不過,部署到任何協調器會很類似,但圖表中的任何容器都可以在協調器中相應放大。

此外,基礎結構資產,例如資料庫、快取和訊息代理程式,應該從協調器卸除,並部署到基礎結構的高可用系統,例如 Azure SQL Database、Azure Cosmos DB、Azure Redis、Azure 服務總線或任何內部部署 HA 叢集解決方案。

您也可以在圖表中注意到,擁有數個 API 閘道可讓多個開發小組在開發及部署微服務以及自己的相關 API 閘道時進行自主性(在此案例中為行銷功能與購物功能)。

如果您有單一整合型 API 閘道,表示數個開發小組要更新的單一點,這可能會讓所有微服務與應用程式的單一部分結合。

進一步設計,有時候細部 API 閘道也可以受限於單一商務微服務,視所選擇的架構而定。 讓 API 閘道的界限由商務或網域決定,將可協助您獲得更好的設計。

例如,API 閘道層中的細微度對於以微服務為基礎的更進階複合 UI 應用程式特別有用,因為精細 API 閘道的概念類似於 UI 組合服務。

在上一節中,我們會深入探討 根據微服務建立複合 UI 的詳細數據

對於許多中型和大型應用程式而言,使用自定義建置的 API 閘道產品通常是一個很好的方法,但不是作為單一整合型匯總工具或唯一的中央自定義 API 閘道,除非該 API 閘道允許數個開發小組建立自主微服務的多個獨立設定區域。

透過 API 閘道重新路由的微服務/容器範例

例如,eShopOnContainers 有大約六種內部微服務類型,必須透過 API 閘道發佈,如下圖所示。

Services 資料夾的螢幕快照,其中顯示其子資料夾。

圖 6-29。 Visual Studio 中 eShopOnContainers 解決方案中的微服務資料夾

關於身分識別服務,在設計中,它被排除在 API 閘道路由中,因為它是系統中唯一的跨領域考慮,雖然使用 Ocelot 時,也可以將其納入重新路由清單。

所有這些服務目前都會實作為 ASP.NET Core Web API 服務,如您可以從程式代碼中得知。 讓我們專注於其中一個微服務,例如目錄微服務程序代碼。

[方案總管] 的螢幕快照,其中顯示 Catalog.API 項目內容。

圖 6-30。 範例 Web API 微服務 (目錄微服務)

您可以看到目錄微服務是典型的 ASP.NET Core Web API 專案,其中包含數個控制器和方法,如下列程式代碼所示。

[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 要求最終會執行那種 C# 程式代碼來存取微服務資料庫,以及任何其他必要動作。

關於微服務 URL,當容器部署在本機開發計算機(本機 Docker 主機)時,每個微服務的容器一律在其 dockerfile 中指定的內部埠(通常是埠 80),如下列 dockerfile 所示:

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

程式代碼中顯示的埠 80 位於 Docker 主機內部,因此無法由用戶端應用程式連線。

用戶端應用程式只能存取使用 部署 docker-compose時發佈的外部埠(如果有的話)。

部署至生產環境時,不應該發佈這些外部埠。 基於這個特定原因,為何要使用 API 閘道,以避免用戶端應用程式與微服務之間的直接通訊。

不過,在開發時,您想要直接存取微服務/容器,並透過 Swagger 執行。 這就是為什麼在 eShopOnContainers 中,即使 API 閘道或用戶端應用程式不會使用外部埠,仍會指定外部埠。

以下是目錄微服務檔案的 docker-compose.override.yml 範例:

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

您可以在docker-compose.override.yml設定目錄容器的內部埠為埠 80,但外部存取的埠為 5101。 但是,使用 API 閘道時,應用程式不應該使用此埠,而只能偵錯、執行及測試目錄微服務。

一般而言,您不會使用 docker-compose 部署到生產環境,因為微服務的正確生產部署環境是 Kubernetes 或 Service Fabric 等協調器。 部署至這些環境時,您會使用不同的組態檔,而不會直接發佈微服務的任何外部埠,但一律會從 API 閘道使用反向 Proxy。

在本機 Docker 主機中執行目錄微服務。 從 Visual Studio 執行完整的 eShopOnContainers 方案(它會在 docker-compose 檔案中執行所有服務),或在 CMD 或位於 和 docker-compose.yml 所在的資料夾中docker-compose.override.yml,使用下列 docker-compose 命令啟動 Catalog 微服務。

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

此命令只會執行 catalog-api 服務容器以及docker-compose.yml中指定的相依性。 在此情況下,SQL Server 容器和 RabbitMQ 容器。

然後,您可以直接存取目錄微服務,並透過 Swagger UI 直接透過該「外部」埠存取,查看其方法,在此案例中為 http://host.docker.internal:5101/swagger

顯示 Catalog.API REST API 的 Swagger UI 螢幕快照。

圖 6-31。 使用其 Swagger UI 測試目錄微服務

此時,您可以在 Visual Studio 中設定 C# 程式代碼中的斷點、使用 Swagger UI 中公開的方法測試微服務,最後使用 docker-compose down 命令清除所有專案。

不過,透過外部埠 5101 直接存取微服務的通訊正是您想要在應用程式中避免的。 您可以藉由設定 API 閘道的額外間接層級來避免這種情況(在此案例中為 Ocelot)。 如此一來,用戶端應用程式就不會直接存取微服務。

使用 Ocelot 實作 API 閘道

Ocelot 基本上是一組中間件,您可以依特定順序套用。

Ocelot 的設計目的是只與 ASP.NET Core 搭配使用。 最新版本的套件是 18.0,以 .NET 6 為目標,因此不適用於 .NET Framework 應用程式。

您可以從 Visual Studio 使用 Ocelot 的 NuGet 套件,在 ASP.NET Core 專案中安裝 Ocelot 及其相依性。

Install-Package Ocelot

在 eShopOnContainers 中,其 API 閘道實作是簡單的 ASP.NET Core WebHost 專案,而 Ocelot 的中間件會處理所有 API 閘道功能,如下圖所示:

顯示 Ocelot API 閘道專案的 [方案總管] 螢幕快照。

圖 6-32。 eShopOnContainers 中的 OcelotApiGw 基底專案

此 ASP.NET Core WebHost 專案是以兩個簡單的檔案建置: Program.csStartup.cs

Program.cs只需要建立及設定一般 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;
        }
    }
}

Ocelot configuration.json 的重點是您必須透過 AddJsonFile() 方法提供給產生器的檔案。 這就是 configuration.json 您指定所有 API 閘道 ReRoutes 的地方,這表示具有特定埠的外部連接點和相互關聯的內部端點,通常使用不同的埠。

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

組態有兩個區段。 ReRoutes 和 GlobalConfiguration 的陣列。 ReRoutes 是指示 Ocelot 如何處理上游要求的物件。 全域設定允許覆寫 ReRoute 特定設定。 如果您不想管理許多 ReRoute 特定設定,這會很有用。

以下是 eShopOnContainers 其中一個 API 閘道的 ReRoute 設定檔 簡化範例。

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

Ocelot API 閘道的主要功能是取得連入 HTTP 要求,並將其轉送至下游服務,目前為另一個 HTTP 要求。 Ocelot 的 將一個要求的路由描述為 ReRoute。

例如,讓我們將焦點放在上述 configuration.json 的其中一個 ReRoutes,即購物籃微服務的設定。

{
      "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 和 DownstreamHostAndPorts 會發出此要求將轉送至的內部微服務 URL。

埠是服務所使用的內部埠。 使用容器時,其 dockerfile 中指定的埠。

Host是一種服務名稱,視您使用的服務名稱解析而定。 使用 docker-compose 時,服務名稱是由 Docker 主機提供,而 Docker 主機則使用 docker-compose 檔案中所提供的服務名稱。 如果使用 Kubernetes 或 Service Fabric 之類的協調器,該名稱應該由每個協調器提供的 DNS 或名稱解析來解析。

DownstreamHostAndPorts 是一個陣列,其中包含您想要轉送要求的任何下游服務的主機和埠。 此設定通常只會包含一個專案,但有時您可能想要將要求負載平衡至下游服務,而 Ocelot 可讓您新增多個專案,然後選取負載平衡器。 但是,如果使用 Azure 和任何協調器,則可能是與雲端和協調器基礎結構進行負載平衡的較佳概念。

UpstreamPathTemplate 是 Ocelot 將用來識別用戶端指定要求所使用的 DownstreamPathTemplate URL。 最後,使用 UpstreamHttpMethod,讓 Ocelot 可以區分相同 URL 的不同要求(GET、POST、PUT)。

此時,您可以使用一或 多個合併 configuration.json 檔案 ,來擁有單一 Ocelot API 閘道(ASP.NET Core WebHost),也可以將設定儲存 在 Consul KV 存放區中。

但是,如架構和設計小節所介紹,如果您真的想要擁有自主微服務,最好將單一整合型 API 閘道分割成多個 API 閘道和/或 BFF(前端的後端)。 為此,讓我們瞭解如何使用 Docker 容器實作該方法。

使用單一 Docker 容器映像來執行多個不同的 API 閘道/BFF 容器類型

在 eShopOnContainers 中,我們使用單一 Docker 容器映射搭配 Ocelot API 閘道,但在運行時間,我們會藉由提供不同的 configuration.json 檔案,為每個 API-Gateway/BFF 類型建立不同的服務/容器,使用 Docker 磁碟區來存取每個服務的不同 PC 資料夾。

所有 API 閘道的單一 Ocelot 閘道 Docker 映射圖表。

圖 6-33。 跨多個 API 閘道類型重複使用單一 Ocelot Docker 映像

在 eShopOnContainers 中,會使用名為 'OcelotApiGw' 的專案和docker-compose.yml檔案中指定的映射名稱 “eshop/ocelotapigw” 來建立「一般 Ocelot API 網關 Docker 映射」。 然後,部署至 Docker 時,將會有四個從該相同 Docker 映像建立的 API-Gateway 容器,如下列從 docker-compose.yml 檔案擷取所示。

  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

此外,如下列docker-compose.override.yml檔案所示,這些 API 閘道容器之間的唯一差異在於 Ocelot 組態檔,每個服務容器都不同,而且它會在運行時間透過 Docker 磁碟區指定。

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

由於先前的程式代碼,如下面的 Visual Studio 檔案總管所示,定義每個特定商務/BFF API 閘道的唯一檔案只是一個 configuration.json 檔案,因為四個 API 閘道是以相同的 Docker 映像為基礎。

顯示具有 configuration.json 檔案之所有 API 閘道的螢幕快照。

圖 6-34。 使用 Ocelot 定義每個 API 閘道 /BFF 所需的唯一檔案是組態檔

藉由將 API 閘道分割成多個 API 閘道,專注於不同微服務子集的不同開發小組可以使用獨立的 Ocelot 組態檔來管理自己的 API 閘道。 此外,他們也可以重複使用相同的 Ocelot Docker 映像。

現在,如果您使用 API 閘道執行 eShopOnContainers(在開啟eShopOnContainers-ServicesAndWebApps.sln解決方案時預設包含在 VS 中,或執行 「docker-compose up」,則會執行下列範例路由。

例如,造訪 Webshoppingapigw API 閘道所服務的上游 URL http://host.docker.internal:5202/api/v1/c/catalog/items/2/ 時,您會從 Docker 主機內的內部下游 URL http://catalog-api/api/v1/2 取得相同的結果,如下列瀏覽器所示。

瀏覽器的螢幕快照,其中顯示透過 API 閘道的回應。

圖 6-35。 透過 API 閘道提供的 URL 存取微服務

由於測試或偵錯的原因,如果您想要直接存取目錄 Docker 容器(僅在開發環境中),而不需要通過 API 閘道,因為 'catalog-api' 是 Docker 主機內部的 DNS 解析(docker-compose 服務名稱所處理的服務探索),直接存取容器的唯一方式是透過docker-compose.override.yml中發佈的外部埠, 僅適用於開發測試,例如 http://host.docker.internal:5101/api/v1/Catalog/items/1 在下列瀏覽器中。

瀏覽器的螢幕快照,其中顯示對 Catalog.api 的直接回應。

圖 6-36。 直接存取微服務以供測試之用

但應用程式已設定,因此它會透過 API 閘道存取所有微服務,而不是透過直接埠「快捷方式」。

eShopOnContainers 中的閘道匯總模式

如先前所介紹,依程式代碼實作要求匯總的彈性方式是使用自定義服務。 在 eShopOnContainers 中實作匯總的選取方式是針對每個匯總工具明確 ASP.NET Core Web API 服務。

根據這種方法,API 閘道組合圖在考慮先前所顯示簡化的全域架構圖表中未顯示的匯總工具服務時,實際上會更延伸一點。

在下圖中,您也可以查看匯總工具服務如何使用其相關的 API 閘道。

顯示匯總工具服務的 eShopOnContainers 架構圖表。

圖 6-37。 具有匯總工具服務的 eShopOnContainers 架構

在下圖中的「購物」商務區域進一步放大,您可以看到用戶端應用程式與微服務之間的閒聊會在 API 閘道中使用匯總工具服務時減少。

顯示 eShopOnContainers 架構放大的圖表。

圖 6-38。 放大匯總工具服務的視覺

您可以注意到當圖表顯示來自 API 閘道的可能要求時,其可能會變得很複雜。 另一方面,當您使用匯總工具模式時,您可以看到藍色箭號如何簡化用戶端應用程式觀點的通訊。 這種模式不僅有助於減少通訊中的閒聊和延遲,還能大幅改善遠端應用程式(行動裝置和 SPA 應用程式)的用戶體驗。

在「行銷」業務領域和微服務的情況下,這是一個簡單的使用案例,因此不需要使用匯總工具,但如有需要,也可能是可能的。

Ocelot API 閘道中的驗證和授權

在 Ocelot API 閘道中,您可以坐上驗證服務,例如使用 IdentityServer 提供驗證令牌的 IdentityServer 來提供驗證令牌的 ASP.NET Core Web API 服務。

由於 eShopOnContainers 使用多個 API 閘道,其界限是以 BFF 和商務區域為基礎,因此身分識別/驗證服務會排除在 API 閘道外,如下圖所示,以黃色醒目提示。

此圖顯示 API 閘道下方的身分識別微服務。

圖 6-39。 eShopOnContainers 中身分識別服務的位置

不過,Ocelot 也支援將身分識別/驗證微服務放在 API 閘道界限內,如此其他圖表所示。

顯示 Ocelot API 閘道中驗證的圖表。

圖 6-40。 Ocelot 中的驗證

如上圖所示,當身分識別微服務位於 API 閘道 (AG): 1) AG 要求身分識別微服務的驗證令牌時,2) 身分識別微服務會使用驗證令牌將令牌傳回 AG,3-4) 來自微服務的 AG 要求。 因為 eShopOnContainers 應用程式已將 API 閘道分割成多個 BFF(前端的後端)和商務區域 API 閘道,因此另一個選項是建立額外的 API 閘道,以進行跨領域考慮。 這種選擇在更複雜的微服務架構中,具有多個跨領域關注的微服務相當公平。 由於 eShopOnContainers 中只有一個跨領域考慮,因此為了簡單起見,它決定只處理 API 閘道領域的安全性服務。

在任何情況下,如果應用程式在 API 閘道層級受到保護,則嘗試使用任何安全的微服務時,會先流覽 Ocelot API 閘道的驗證模組。 這會將 HTTP 要求重新導向至造訪身分識別或驗證微服務,以取得存取令牌,讓您可以使用 access_token來流覽受保護的服務。

使用 API 閘道層級的任何服務進行驗證的方式,是在 configuration.json的相關設定中設定 AuthenticationProviderKey。

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

當 Ocelot 執行時,它會查看 ReRoutes AuthenticationOptions.AuthenticationProviderKey,並檢查是否有向指定密鑰註冊的驗證提供者。 如果沒有,Ocelot 將不會啟動。 如果有,則 ReRoute 會在執行該提供者時使用該提供者。

由於 Ocelot WebHost 已設定為 authenticationProviderKey = "IdentityApiKey",因此每當該服務有任何要求且沒有任何驗證令牌時,都需要驗證。

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

然後,您也需要使用任何資源上的 [Authorize] 屬性來設定授權,才能像微服務一樣存取,例如在下列購物籃微服務控制器中。

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

“basket” 之類的 ValidAudiences 會與在 Startup 類別的 ConfigureServices() 的每個微服務 AddJwtBearer() 中定義的物件相互關聯,例如在下列程式代碼中。

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

如果您嘗試存取任何受保護的微服務,例如以 API 閘道 http://host.docker.internal:5202/api/v1/b/basket/1為基礎的 ReRoute URL 的購物籃微服務,除非您提供有效的令牌,否則您將會收到 401 未經授權。 另一方面,如果已驗證 ReRoute URL,Ocelot 會叫用與其相關聯的下游配置(內部微服務 URL)。

Ocelot ReRoutes 層的授權。 Ocelot 支援驗證之後評估的宣告型授權。 您可以將下列幾行新增至 ReRoute 組態,以在路由層級設定授權。

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

在該範例中,呼叫授權中間件時,Ocelot 會發現使用者在令牌中是否有宣告類型 『UserType』,以及該宣告的值是否為 『employee』。 如果不是,則使用者將不會獲得授權,且回應將禁止 403。

使用 Kubernetes 輸入加上 Ocelot API 閘道

使用 Kubernetes 時(如同在 Azure Kubernetes Service 叢集中),您通常會根據 Nginx 透過 Kubernetes 輸入層統一所有 HTTP 要求。

在 Kubernetes 中,如果您未使用任何輸入方法,則服務和 Pod 只會讓叢集網路可路由傳送 IP。

但是,如果您使用輸入方法,則因特網與服務之間會有中介層(包括 API 閘道),做為反向 Proxy。

作為定義,輸入是一組規則,可讓輸入連線到達叢集服務。 輸入已設定為提供服務外部可連線的 URL、負載平衡流量、SSL 終止等等。 用戶藉由將輸入資源 POS 處理至 API 伺服器來要求輸入。

在 eShopOnContainers 中,在本機開發時,只要使用您的開發電腦作為 Docker 主機,您就不會使用任何輸入,而只會使用多個 API 閘道。

不過,當以 Kubernetes 為基礎的「生產」環境為目標時,eShopOnContainers 會在 API 閘道前面使用輸入。 如此一來,用戶端仍會呼叫相同的基底 URL,但要求會路由傳送至多個 API 網關或 BFF。

API 閘道是前端或外觀,只會呈現服務,但不會呈現通常不在其範圍的 Web 應用程式。 此外,API 閘道可能會隱藏特定內部微服務。

不過,輸入只是重新導向 HTTP 要求,但不嘗試隱藏任何微服務或 Web 應用程式。

在 Web 應用程式前面具有 Kubernetes 中的輸入 Nginx 層,加上數個 Ocelot API 閘道/BFF 是理想的架構,如下圖所示。

顯示輸入層如何融入 AKS 環境的圖表。

圖 6-41。 部署到 Kubernetes 時,eShopOnContainers 中的輸入層

Kubernetes 輸入可作為應用程式的所有流量的反向 Proxy,包括來自 Api 閘道範圍的 Web 應用程式。 當您將 eShopOnContainers 部署到 Kubernetes 時,它只會透過 輸入公開幾個服務或端點,基本上是 URL 上的下列後置修正清單:

  • / 適用於用戶端 SPA Web 應用程式
  • /webmvc 適用於用戶端MVC Web 應用程式
  • /webstatus 適用於顯示狀態/健康情況檢查的用戶端應用程式
  • /webshoppingapigw 適用於 Web BFF 和購物商務程式
  • /webmarketingapigw 適用於 Web BFF 和行銷商務程式
  • /mobileshoppingapigw 適用於行動 BFF 和購物商務程式
  • /mobilemarketingapigw 適用於行動 BFF 和行銷商務程式

部署至 Kubernetes 時,每個 Ocelot API 閘道都會針對執行 API 閘道的每個 Pod 使用不同的「configuration.json」檔案。 這些「configuration.json」檔案是藉由掛接##deploy.ps1 腳本所提供,這是根據名為 'ocelot' 的 Kubernetes 組態對應 所建立的磁碟區。 每個容器會在名為 /app/configuration的容器資料夾中掛接其相關的組態檔。

在 eShopOnContainers 的原始程式碼檔案中,您可以在資料夾中找到 k8s/ocelot/ 原始的 「configuration.json」 檔案。 每個 BFF/APIGateway 都有一個檔案。

Ocelot API 閘道中的其他跨領域功能

使用 Ocelot API 閘道時,還有其他重要的功能可供研究及使用,如下列連結所述。