Bagikan melalui


Menerapkan Gateway API dengan Ocelot

Tip

Konten ini adalah kutipan dari eBook, .NET Microservices Architecture for Containerized .NET Applications, tersedia di .NET Docs atau sebagai PDF yang dapat diunduh gratis dan dapat dibaca secara offline.

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

Penting

Aplikasi layanan mikro referensi eShopOnContainers saat ini menggunakan fitur yang disediakan oleh Envoy untuk mengimplementasikan API Gateway alih-alih Ocelot yang dirujuk sebelumnya. Kami membuat pilihan desain ini karena dukungan bawaan Envoy untuk protokol WebSocket, yang diperlukan oleh komunikasi antar-layanan gRPC baru yang diterapkan di eShopOnContainers. Namun, kami telah mempertahankan bagian ini dalam panduan sehingga Anda dapat menganggap Ocelot sebagai API Gateway sederhana, berkemampuan, dan ringan yang cocok untuk skenario tingkat produksi. Selain itu, versi Ocelot terbaru berisi perubahan yang melanggar pada skema json-nya. Pertimbangkan untuk menggunakan Ocelot < v16.0.0, atau gunakan Rute kunci alih-alih ReRoutes.

Merancang dan merancang GATEWAY API Anda

Diagram arsitektur berikut menunjukkan bagaimana API Gateway diimplementasikan dengan Ocelot di eShopOnContainers.

Diagram showing the eShopOnContainers architecture.

Gambar 6-28. Arsitektur eShopOnContainers dengan API Gateway

Diagram itu menunjukkan bagaimana seluruh aplikasi disebarkan ke dalam satu host Docker atau PC pengembangan dengan "Docker untuk Windows" atau "Docker untuk Mac". Namun, penyebaran ke orkestrator apa pun akan serupa, tetapi kontainer apa pun dalam diagram dapat diskalakan di orkestrator.

Selain itu, aset infrastruktur seperti database, cache, dan broker pesan harus dibongkar dari orkestrator dan disebarkan ke dalam sistem dengan ketersediaan tinggi untuk infrastruktur, seperti Azure SQL Database, Azure Cosmos DB, Azure Redis, Azure Service Bus, atau solusi pengklusteran HA lokal.

Seperti yang dapat Anda perhatikan dalam diagram, memiliki beberapa GATEWAY API memungkinkan beberapa tim pengembangan untuk menjadi otonom (dalam hal ini fitur Pemasaran vs. fitur Belanja) saat mengembangkan dan menyebarkan layanan mikro mereka ditambah GATEWAY API terkait mereka sendiri.

Jika Anda memiliki satu GATEWAY API monolitik yang berarti satu titik yang akan diperbarui oleh beberapa tim pengembangan, yang dapat menggabungkan semua layanan mikro dengan satu bagian aplikasi.

Jauh lebih jauh dalam desain, terkadang API Gateway beruban halus juga dapat dibatasi pada satu layanan mikro bisnis tergantung pada arsitektur yang dipilih. Memiliki batasAN API Gateway yang ditentukan oleh bisnis atau domain akan membantu Anda mendapatkan desain yang lebih baik.

Misalnya, granularitas halus di tingkat API Gateway dapat sangat berguna untuk aplikasi UI komposit yang lebih canggih yang didasarkan pada layanan mikro, karena konsep API Gateway terperinci mirip dengan layanan komposisi UI.

Kami mempelajari lebih detail di bagian sebelumnya Membuat UI komposit berdasarkan layanan mikro.

Sebagai pengambilan kunci, untuk banyak aplikasi berukuran sedang dan besar, menggunakan produk API Gateway yang dibuat khusus biasanya merupakan pendekatan yang baik, tetapi bukan sebagai agregator monolitik tunggal atau API Gateway kustom pusat yang unik kecuali api Gateway memungkinkan beberapa area konfigurasi independen untuk beberapa tim pengembangan yang menciptakan layanan mikro otonom.

Sampel layanan mikro/kontainer untuk dirutekan ulang melalui GATEWAY API

Sebagai contoh, eShopOnContainers memiliki sekitar enam jenis layanan mikro internal yang harus diterbitkan melalui API Gateway, seperti yang ditunjukkan pada gambar berikut.

Screenshot of the Services folder showing its subfolders.

Gambar 6-29. Folder layanan mikro dalam solusi eShopOnContainers di Visual Studio

Tentang layanan Identitas, dalam desain dibiarkan keluar dari perutean API Gateway karena ini adalah satu-satunya kekhawatiran lintas pemotongan dalam sistem, meskipun dengan Ocelot juga dimungkinkan untuk menyertakannya sebagai bagian dari daftar perutean ulang.

Semua layanan tersebut saat ini diimplementasikan sebagai ASP.NET layanan Core Web API, seperti yang dapat Anda katakan dari kode. Mari kita fokus pada salah satu layanan mikro seperti kode layanan mikro Katalog.

Screenshot of Solution Explorer showing Catalog.API project contents.

Gambar 6-30. Sampel layanan mikro API Web (Layanan mikro katalog)

Anda dapat melihat bahwa layanan mikro Katalog adalah proyek ASP.NET Core Web API yang khas dengan beberapa pengontrol dan metode seperti dalam kode berikut.

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

Permintaan HTTP akan akhirnya menjalankan kode C# semacam itu yang mengakses database layanan mikro dan tindakan tambahan yang diperlukan.

Mengenai URL layanan mikro, ketika kontainer disebarkan di PC pengembangan lokal Anda (host Docker lokal), setiap kontainer layanan mikro selalu memiliki port internal (biasanya port 80) yang ditentukan dalam dockerfile-nya, seperti dalam dockerfile berikut:

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

Port 80 yang ditampilkan dalam kode bersifat internal dalam host Docker, sehingga tidak dapat dijangkau oleh aplikasi klien.

Aplikasi klien hanya dapat mengakses port eksternal (jika ada) yang diterbitkan saat menyebarkan dengan docker-compose.

Port eksternal tersebut tidak boleh diterbitkan saat menyebarkan ke lingkungan produksi. Untuk alasan khusus ini, mengapa Anda ingin menggunakan API Gateway, untuk menghindari komunikasi langsung antara aplikasi klien dan layanan mikro.

Namun, saat mengembangkan, Anda ingin mengakses layanan mikro/kontainer secara langsung dan menjalankannya melalui Swagger. Itulah sebabnya di eShopOnContainers, port eksternal masih ditentukan bahkan ketika tidak akan digunakan oleh API Gateway atau aplikasi klien.

Berikut adalah contoh docker-compose.override.yml file untuk layanan mikro Katalog:

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

Anda dapat melihat bagaimana dalam konfigurasi docker-compose.override.yml port internal untuk kontainer Katalog adalah port 80, tetapi port untuk akses eksternal adalah 5101. Tetapi port ini tidak boleh digunakan oleh aplikasi saat menggunakan API Gateway, hanya untuk men-debug, menjalankan, dan menguji hanya layanan mikro Katalog.

Biasanya, Anda tidak akan menyebarkan dengan docker-compose ke lingkungan produksi karena lingkungan penyebaran produksi yang tepat untuk layanan mikro adalah orkestrator seperti Kubernetes atau Service Fabric. Saat menyebarkan ke lingkungan tersebut, Anda menggunakan file konfigurasi yang berbeda saat Anda tidak akan menerbitkan langsung port eksternal apa pun untuk layanan mikro tetapi, Anda akan selalu menggunakan proksi terbalik dari API Gateway.

Jalankan layanan mikro katalog di host Docker lokal Anda. Jalankan solusi eShopOnContainers lengkap dari Visual Studio (menjalankan semua layanan dalam file docker-compose), atau mulai layanan mikro Katalog dengan perintah docker-compose berikut di CMD atau PowerShell yang diposisikan di folder tempat docker-compose.yml dan docker-compose.override.yml ditempatkan.

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

Perintah ini hanya menjalankan kontainer layanan catalog-api ditambah dependensi yang ditentukan dalam docker-compose.yml. Dalam hal ini, kontainer SQL Server dan kontainer RabbitMQ.

Kemudian, Anda dapat langsung mengakses layanan mikro Katalog dan melihat metodenya melalui antarmuka pengguna Swagger yang mengakses langsung melalui port "eksternal", dalam hal ini http://host.docker.internal:5101/swagger:

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

Gambar 6-31. Menguji layanan mikro Katalog dengan antarmuka pengguna Swagger-nya

Pada titik ini, Anda dapat mengatur titik henti dalam kode C# di Visual Studio, menguji layanan mikro dengan metode yang terekspos di antarmuka pengguna Swagger, dan akhirnya membersihkan semuanya dengan docker-compose down perintah.

Namun, komunikasi akses langsung ke layanan mikro, dalam hal ini melalui port eksternal 5101, tepatnya yang ingin Anda hindari di aplikasi Anda. Dan Anda dapat menghindarinya dengan mengatur tingkat tidak langsung tambahan API Gateway (Ocelot, dalam hal ini). Dengan begitu, aplikasi klien tidak akan langsung mengakses layanan mikro.

Menerapkan GATEWAY API Anda dengan Ocelot

Ocelot pada dasarnya adalah sekumpulan middleware yang dapat Anda terapkan dalam urutan tertentu.

Ocelot dirancang untuk bekerja dengan ASP.NET Core saja. Versi terbaru paket adalah 18.0 yang menargetkan .NET 6 dan karenanya tidak cocok untuk aplikasi .NET Framework.

Anda menginstal Ocelot dan dependensinya di proyek ASP.NET Core Anda dengan paket NuGet Ocelot, dari Visual Studio.

Install-Package Ocelot

Di eShopOnContainers, implementasi API Gateway-nya adalah proyek ASP.NET Core WebHost sederhana, dan middleware Ocelot menangani semua fitur API Gateway, seperti yang ditunjukkan pada gambar berikut:

Screenshot of Solution Explorer showing Ocelot API gateway project.

Gambar 6-32. Proyek dasar OcelotApiGw di eShopOnContainers

Proyek ASP.NET Core WebHost ini dibangun dengan dua file sederhana: Program.cs dan Startup.cs.

Program.cs hanya perlu membuat dan mengonfigurasi ASP.NET Core BuildWebHost yang khas.

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

Poin penting di sini untuk Ocelot adalah configuration.json file yang harus Anda berikan kepada penyusun melalui AddJsonFile() metode. Di configuration.json situlah Anda menentukan semua API Gateway ReRoutes, yang berarti titik akhir eksternal dengan port tertentu dan titik akhir internal yang berkorelasi, biasanya menggunakan port yang berbeda.

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

Ada dua bagian untuk konfigurasi. Array ReRoutes dan GlobalConfiguration. ReRoutes adalah objek yang memberi tahu Ocelot cara memperlakukan permintaan hulu. Konfigurasi Global memungkinkan penimpaan pengaturan spesifik ReRoute. Ini berguna jika Anda tidak ingin mengelola banyak pengaturan khusus ReRoute.

Berikut adalah contoh file konfigurasi ReRoute yang disederhanakan dari salah satu GATEWAY API dari 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"
    }
  }

Fungsionalitas utama Ocelot API Gateway adalah mengambil permintaan HTTP masuk dan meneruskannya ke layanan hilir, saat ini sebagai permintaan HTTP lain. Ocelot menggambarkan perutean satu permintaan ke permintaan lain sebagai ReRoute.

Misalnya, mari kita fokus pada salah satu ReRoutes di configuration.json dari atas, konfigurasi untuk layanan mikro Ke basket.

{
      "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, dan DownstreamHostAndPorts membuat URL layanan mikro internal tempat permintaan ini akan diteruskan.

Port adalah port internal yang digunakan oleh layanan. Saat menggunakan kontainer, port yang ditentukan pada dockerfile-nya.

Host adalah nama layanan yang bergantung pada resolusi nama layanan yang Anda gunakan. Saat menggunakan docker-compose, nama layanan disediakan oleh Docker Host, yang menggunakan nama layanan yang disediakan dalam file docker-compose. Jika menggunakan orkestrator seperti Kubernetes atau Service Fabric, nama tersebut harus diselesaikan dengan DNS atau resolusi nama yang disediakan oleh setiap orkestrator.

DownstreamHostAndPorts adalah array yang berisi host dan port layanan hilir apa pun yang ingin Anda teruskan permintaannya. Biasanya konfigurasi ini hanya akan berisi satu entri tetapi kadang-kadang Anda mungkin ingin memuat permintaan keseimbangan ke layanan hilir Anda dan Ocelot memungkinkan Anda menambahkan lebih dari satu entri dan kemudian memilih load balancer. Tetapi jika menggunakan Azure dan orkestrator apa pun, mungkin ide yang lebih baik untuk memuat keseimbangan dengan infrastruktur cloud dan orkestrator.

UpstreamPathTemplate adalah URL yang akan digunakan Ocelot untuk mengidentifikasi DownstreamPathTemplate mana yang akan digunakan untuk permintaan tertentu dari klien. Terakhir, UpstreamHttpMethod digunakan sehingga Ocelot dapat membedakan antara permintaan yang berbeda (GET, POST, PUT) ke URL yang sama.

Pada titik ini, Anda dapat memiliki satu Gateway API Ocelot (ASP.NET Core WebHost) menggunakan satu atau beberapa file configuration.json gabungan atau Anda juga dapat menyimpan konfigurasi di penyimpanan Consul KV.

Tetapi seperti yang diperkenalkan di bagian arsitektur dan desain, jika Anda benar-benar ingin memiliki layanan mikro otonom, mungkin lebih baik untuk membagi API Gateway monolitik tunggal itu menjadi beberapa API Gateway dan/atau BFF (Backend for Frontend). Untuk tujuan itu, mari kita lihat cara menerapkan pendekatan tersebut dengan kontainer Docker.

Menggunakan satu gambar kontainer Docker untuk menjalankan beberapa jenis kontainer API Gateway/BFF yang berbeda

Di eShopOnContainers, kami menggunakan satu gambar kontainer Docker dengan Gateway API Ocelot tetapi kemudian, pada waktu proses, kami membuat layanan/kontainer yang berbeda untuk setiap jenis API-Gateway/BFF dengan menyediakan file configuration.json yang berbeda, menggunakan volume docker untuk mengakses folder PC yang berbeda untuk setiap layanan.

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

Gambar 6-33. Menggunakan kembali satu gambar Ocelot Docker di beberapa jenis API Gateway

Dalam eShopOnContainers, "Generic Ocelot API Gateway Docker Image" dibuat dengan proyek bernama 'OcelotApiGw' dan nama gambar "eshop/ocelotapigw" yang ditentukan dalam file docker-compose.yml. Kemudian, saat menyebarkan ke Docker, akan ada empat kontainer API-Gateway yang dibuat dari gambar Docker yang sama, seperti yang ditunjukkan dalam ekstrak berikut dari file 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

Selain itu, seperti yang Anda lihat dalam file docker-compose.override.yml berikut, satu-satunya perbedaan antara kontainer API Gateway tersebut adalah file konfigurasi Ocelot, yang berbeda untuk setiap kontainer layanan dan ditentukan pada durasi melalui volume 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

Karena kode sebelumnya, dan seperti yang ditunjukkan pada Visual Studio Explorer di bawah ini, satu-satunya file yang diperlukan untuk menentukan setiap BISNIS/BFF API Gateway tertentu hanyalah file configuration.json, karena empat API Gateway didasarkan pada gambar Docker yang sama.

Screenshot showing all API gateways with configuration.json files.

Gambar 6-34. Satu-satunya file yang diperlukan untuk menentukan setiap API Gateway/BFF dengan Ocelot adalah file konfigurasi

Dengan membagi API Gateway menjadi beberapa GATEWAY API, tim pengembangan yang berbeda yang berfokus pada subset layanan mikro yang berbeda dapat mengelola GATEWAY API mereka sendiri dengan menggunakan file konfigurasi Ocelot independen. Plus, pada saat yang sama mereka dapat menggunakan kembali gambar Ocelot Docker yang sama.

Sekarang, jika Anda menjalankan eShopOnContainers dengan API Gateway (disertakan secara default di VS saat membuka solusi eShopOnContainers-ServicesAndWebApps.sln atau jika menjalankan "docker-compose up"), rute sampel berikut akan dilakukan.

Misalnya, saat mengunjungi URL http://host.docker.internal:5202/api/v1/c/catalog/items/2/ upstream yang dilayani oleh webshoppingapigw API Gateway, Anda mendapatkan hasil yang sama dari URL http://catalog-api/api/v1/2 Hilir internal dalam host Docker, seperti di browser berikut.

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

Gambar 6-35. Mengakses layanan mikro melalui URL yang disediakan oleh API Gateway

Karena alasan pengujian atau penelusuran kesalahan, jika Anda ingin langsung mengakses kontainer Catalog Docker (hanya di lingkungan pengembangan) tanpa melewati API Gateway, karena 'catalog-api' adalah resolusi DNS internal untuk host Docker (penemuan layanan yang ditangani oleh nama layanan docker-compose), satu-satunya cara untuk mengakses kontainer secara langsung adalah melalui port eksternal yang diterbitkan di docker-compose.override.yml, yang disediakan hanya untuk pengujian pengembangan, seperti http://host.docker.internal:5101/api/v1/Catalog/items/1 di browser berikut.

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

Gambar 6-36. Akses langsung ke layanan mikro untuk tujuan pengujian

Tetapi aplikasi dikonfigurasi sehingga mengakses semua layanan mikro melalui GATEWAY API, bukan melalui port langsung "pintasan".

Pola agregasi Gateway di eShopOnContainers

Seperti yang diperkenalkan sebelumnya, cara fleksibel untuk menerapkan agregasi permintaan adalah dengan layanan kustom, berdasarkan kode. Anda juga dapat menerapkan agregasi permintaan dengan fitur Agregasi Permintaan di Ocelot, tetapi mungkin tidak fleksibel seperti yang Anda butuhkan. Oleh karena itu, cara yang dipilih untuk menerapkan agregasi di eShopOnContainers adalah dengan layanan API Web Inti ASP.NET eksplisit untuk setiap agregator.

Menurut pendekatan itu, diagram komposisi API Gateway pada kenyataannya sedikit lebih diperluas ketika mempertimbangkan layanan agregator yang tidak ditampilkan dalam diagram arsitektur global yang disederhanakan yang ditunjukkan sebelumnya.

Dalam diagram berikut, Anda juga dapat melihat cara kerja layanan agregator dengan API Gateway terkait.

Diagram of eShopOnContainers architecture showing aggregator services.

Gambar 6-37. Arsitektur eShopOnContainers dengan layanan agregator

Memperbesar lebih lanjut, pada area bisnis "Belanja" dalam gambar berikut, Anda dapat melihat bahwa obrolan antara aplikasi klien dan layanan mikro berkurang saat menggunakan layanan agregator di GATEWAY API.

Diagram showing eShopOnContainers architecture zoom in.

Gambar 6-38. Memperbesar visi layanan Agregator

Anda dapat melihat bagaimana ketika diagram menunjukkan kemungkinan permintaan yang berasal dari GATEWAY API, dia bisa menjadi kompleks. Di sisi lain, ketika Anda menggunakan pola agregator, Anda dapat melihat bagaimana panah berwarna biru akan menyederhanakan komunikasi dari perspektif aplikasi klien. Pola ini tidak hanya membantu mengurangi obrolan dan latensi dalam komunikasi, tetapi juga meningkatkan pengalaman pengguna secara signifikan untuk aplikasi jarak jauh (aplikasi seluler dan SPA).

Dalam kasus area bisnis "Pemasaran" dan layanan mikro, itu adalah kasus penggunaan sederhana sehingga tidak perlu menggunakan agregator, tetapi mungkin juga, jika diperlukan.

Autentikasi dan otorisasi di Ocelot API Gateways

Di Gateway API Ocelot, Anda dapat duduk di layanan autentikasi, seperti layanan ASP.NET Core Web API menggunakan IdentityServer yang menyediakan token autentikasi, baik keluar atau di dalam API Gateway.

Karena eShopOnContainers menggunakan beberapa GATEWAY API dengan batasan berdasarkan BFF dan area bisnis, layanan Identitas/Auth ditinggalkan dari GATEWAY API, seperti yang disorot dengan warna kuning dalam diagram berikut.

Diagram showing Identity microservice beneath the API gateway.

Gambar 6-39. Posisi layanan Identitas di eShopOnContainers

Namun, Ocelot juga mendukung duduknya layanan mikro Identitas/Autentikasi dalam batas API Gateway, seperti dalam diagram lainnya ini.

Diagram showing authentication in an Ocelot API Gateway.

Gambar 6-40. Autentikasi di Ocelot

Seperti yang ditunjukkan diagram sebelumnya, ketika layanan mikro Identitas berada di bawah gateway API (AG): 1) AG meminta token autentikasi dari layanan mikro identitas, 2) Layanan mikro identitas mengembalikan token ke AG, 3-4) permintaan AG dari layanan mikro menggunakan token auth. Karena aplikasi eShopOnContainers telah membagi API Gateway menjadi beberapa BFF (Backend untuk Frontend) dan area bisnis API Gateway, opsi lain adalah membuat API Gateway tambahan untuk masalah lintas pemotongan. Pilihan itu akan adil dalam arsitektur berbasis layanan mikro yang lebih kompleks dengan beberapa kekhawatiran lintas pemotongan layanan mikro. Karena hanya ada satu kekhawatiran lintas pemotongan di eShopOnContainers, diputuskan untuk hanya menangani layanan keamanan dari realm API Gateway, demi kesederhanaan.

Bagaimanapun, jika aplikasi diamankan di tingkat API Gateway, modul autentikasi Ocelot API Gateway dikunjungi pada awalnya saat mencoba menggunakan layanan mikro yang aman. Itu mengalihkan permintaan HTTP untuk mengunjungi Identitas atau layanan mikro autentikasi untuk mendapatkan token akses sehingga Anda dapat mengunjungi layanan yang dilindungi dengan access_token.

Cara Anda mengamankan dengan autentikasi layanan apa pun di tingkat API Gateway adalah dengan mengatur AuthenticationProviderKey dalam pengaturan terkait di configuration.json.

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

Ketika Ocelot berjalan, Ocelot akan melihat ReRoutes AuthenticationOptions.AuthenticationProviderKey dan memeriksa bahwa ada Penyedia Autentikasi yang terdaftar dengan kunci yang diberikan. Jika tidak ada, maka Ocelot tidak akan memulai. Jika ada, maka ReRoute akan menggunakan penyedia tersebut saat dijalankan.

Karena Ocelot WebHost dikonfigurasi dengan authenticationProviderKey = "IdentityApiKey", yang akan memerlukan autentikasi setiap kali layanan tersebut memiliki permintaan tanpa token autentikasi apa pun.

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

Kemudian, Anda juga perlu mengatur otorisasi dengan atribut [Otorisasi] pada sumber daya apa pun untuk diakses seperti layanan mikro, seperti di pengontrol layanan mikro Ke basket berikut.

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

ValidAudiences seperti "keranjang" berkorelasi dengan audiens yang ditentukan dalam setiap layanan mikro dengan AddJwtBearer() di ConfigureServices() kelas Startup, seperti dalam kode di bawah ini.

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

Jika Anda mencoba mengakses layanan mikro aman, seperti layanan mikro Ke basket dengan URL ReRoute berdasarkan API Gateway seperti http://host.docker.internal:5202/api/v1/b/basket/1, maka Anda akan mendapatkan 401 Tidak Sah kecuali Anda memberikan token yang valid. Di sisi lain, jika URL ReRoute diautentikasi, Ocelot akan memanggil skema hilir apa pun yang terkait dengannya (URL layanan mikro internal).

Otorisasi di tingkat ReRoutes Ocelot. Ocelot mendukung otorisasi berbasis klaim yang dievaluasi setelah autentikasi. Anda mengatur otorisasi pada tingkat rute dengan menambahkan baris berikut ke konfigurasi ReRoute.

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

Dalam contoh itu, ketika middleware otorisasi dipanggil, Ocelot akan menemukan apakah pengguna memiliki jenis klaim 'UserType' dalam token dan jika nilai klaim tersebut adalah 'karyawan'. Jika tidak, maka pengguna tidak akan diotorisasi dan responsnya akan dilarang 403.

Menggunakan Kubernetes Ingress ditambah Gateway API Ocelot

Saat menggunakan Kubernetes (seperti dalam kluster Azure Kubernetes Service), Anda biasanya menyatukan semua permintaan HTTP melalui tingkat Kubernetes Ingress berdasarkan Nginx.

Di Kubernetes, jika Anda tidak menggunakan pendekatan ingress apa pun, maka layanan dan pod Anda hanya memiliki IP yang dapat dirutekan oleh jaringan kluster.

Tetapi jika Anda menggunakan pendekatan ingress, Anda akan memiliki tingkat menengah antara Internet dan layanan Anda (termasuk GATEWAY API Anda), bertindak sebagai proksi terbalik.

Sebagai definisi, Ingress adalah kumpulan aturan yang memungkinkan koneksi masuk mencapai layanan kluster. ingress dikonfigurasi untuk menyediakan layanan URL yang dapat dijangkau secara eksternal, lalu lintas keseimbangan beban, penghentian SSL, dan banyak lagi. Pengguna meminta masuk dengan MEMPOSTING sumber daya Ingress ke server API.

Di eShopOnContainers, saat mengembangkan secara lokal dan hanya menggunakan komputer pengembangan Anda sebagai host Docker, Anda tidak menggunakan ingress apa pun tetapi hanya beberapa API Gateway.

Namun, saat menargetkan lingkungan "produksi" berdasarkan Kubernetes, eShopOnContainers menggunakan ingress di depan gateway API. Dengan begitu, klien masih memanggil URL dasar yang sama tetapi permintaan dirutekan ke beberapa GATEWAY API atau BFF.

API Gateway adalah ujung depan atau fasad yang hanya memunculkan layanan tetapi bukan aplikasi web yang biasanya berada di luar cakupannya. Selain itu, API Gateway mungkin menyembunyikan layanan mikro internal tertentu.

Namun, ingress hanya mengalihkan permintaan HTTP tetapi tidak mencoba menyembunyikan layanan mikro atau aplikasi web apa pun.

Memiliki tingkat ingress Nginx di Kubernetes di depan aplikasi web ditambah beberapa Ocelot API Gateways/BFF adalah arsitektur yang ideal, seperti yang ditunjukkan pada diagram berikut.

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

Gambar 6-41. Tingkat ingress di eShopOnContainers saat disebarkan ke Kubernetes

Ingress Kubernetes bertindak sebagai proksi terbalik untuk semua lalu lintas ke aplikasi, termasuk aplikasi web, yang berada di luar cakupan gateway Api. Ketika Anda menyebarkan eShopOnContainers ke Kubernetes, itu hanya mengekspos beberapa layanan atau titik akhir melalui masuknya, pada dasarnya daftar postfix berikut pada URL:

  • / untuk aplikasi web SPA klien
  • /webmvc untuk aplikasi web MVC klien
  • /webstatus untuk aplikasi web klien yang menunjukkan status/pemeriksaan kesehatan
  • /webshoppingapigw untuk BFF web dan proses bisnis belanja
  • /webmarketingapigw untuk BFF web dan proses bisnis pemasaran
  • /mobileshoppingapigw untuk BFF web dan proses bisnis belanja
  • /mobilemarketingapigw untuk BFF web dan proses bisnis pemasaran

Saat menyebarkan ke Kubernetes, setiap Gateway API Ocelot menggunakan file "configuration.json" yang berbeda untuk setiap pod yang menjalankan API Gateway. File "configuration.json" tersebut disediakan dengan memasang (awalnya dengan skrip deploy.ps1) volume yang dibuat berdasarkan peta konfigurasi Kubernetesbernama 'ocelot'. Setiap kontainer memasang file konfigurasi terkait di folder kontainer bernama /app/configuration.

Dalam file kode sumber eShopOnContainers, file "configuration.json" asli dapat ditemukan di k8s/ocelot/ dalam folder. Ada satu file untuk setiap BFF/APIGateway.

Fitur lintas pemotongan silang tambahan di Gateway API Ocelot

Ada fitur penting lainnya untuk diteliti dan digunakan, saat menggunakan Ocelot API Gateway, yang dijelaskan dalam tautan berikut.