Bagikan melalui


Menerapkan API Gateway dengan Ocelot

Petunjuk / Saran

Konten ini adalah kutipan dari eBook, Arsitektur Layanan Mikro .NET untuk Aplikasi .NET Kontainer, tersedia di .NET Docs atau sebagai PDF gratis yang dapat diunduh yang dapat dibaca secara offline.

Arsitektur Layanan Mikro .NET untuk Aplikasi .NET Dalam Kontainer: gambar kecil sampul eBook.

Penting

Aplikasi layanan mikro referensi eShopOnContainers saat ini menggunakan fitur yang disediakan oleh Envoy untuk menerapkan 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 mempertimbangkan Ocelot sebagai API Gateway sederhana, mampu, dan ringan yang cocok untuk skenario tingkat produksi. Selain itu, versi Ocelot terbaru berisi perubahan besar pada skema JSON-nya. Pertimbangkan untuk menggunakan Ocelot < v16.0.0, atau gunakan key Routes alih-alih ReRoutes.

Merancang dan mendesain API Gateway Anda

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

Diagram memperlihatkan arsitektur eShopOnContainers.

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, penerapan ke dalam orkestrator mana pun akan mirip, tetapi kontainer mana pun dalam diagram dapat diskalakan dalam orkestrator.

Selain itu, aset infrastruktur seperti database, cache, dan broker pesan harus dikeluarkan dari orkestrator dan disebarkan ke dalam sistem yang memiliki 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 API Gateway monolitik yang berarti satu titik yang harus diperbarui oleh beberapa tim pengembangan, yang dapat menghubungkan semua layanan mikro dengan satu bagian dari aplikasi.

Jauh lebih jauh dalam desain, kadang-kadang API Gateway terperinci 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 detail selengkapnya di bagian Sebelumnya Membuat UI komposit berdasarkan layanan mikro.

Sebagai 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 API Gateway

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

Cuplikan layar folder Layanan memperlihatkan subfoldernya.

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

Tentang layanan Identitas, pada desain layanan ini tidak dimasukkan dalam perutean API Gateway karena ini adalah satu-satunya kekhawatiran lintas fungsional 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 tahu dari kode. Mari kita fokus pada salah satu layanan mikro seperti kode layanan mikro Katalog.

Cuplikan layar Penjelajah Solusi memperlihatkan konten proyek Catalog.API.

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 akhirnya akan 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 tersedia) yang diterbitkan saat mendeploy dengan docker-compose.

Port eksternal tersebut tidak boleh dibuat tersedia saat mengerahkan 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 di mana 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 http://host.docker.internal:5101/swaggerini:

Cuplikan layar antarmuka pengguna Swagger memperlihatkan 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 diekspos 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, itulah yang ingin Anda hindari dalam aplikasi Anda. Dan Anda dapat menghindarinya dengan mengatur tingkat tambahan tidak langsung API Gateway (Ocelot, dalam hal ini). Dengan begitu, aplikasi klien tidak akan langsung mengakses layanan mikro.

Menerapkan API Gateway 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:

Cuplikan layar Penjelajah Solusi memperlihatkan proyek gateway API Ocelot.

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 file configuration.json yang harus Anda berikan kepada pembangun melalui metode AddJsonFile(). Di situlah Anda menentukan semua pengalihan jalur API Gateway, yaitu titik akhir eksternal dengan port tertentu dan titik akhir internal yang terkait, biasanya menggunakan port berbeda.

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

Terdapat dua bagian konfigurasi. Sebuah array dari ReRoutes dan sebuah Konfigurasi Global. ReRoutes adalah objek yang memberi tahu Ocelot cara mengelola permintaan hulu. Konfigurasi Global memungkinkan penimpaan pengaturan spesifik ReRoute. Ini berguna jika Anda tidak ingin mengelola banyak pengaturan spesifik 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 pengalihan satu permintaan ke permintaan lain sebagai ReRoute.

Misalnya, mari kita fokus pada salah satu ReRoutes di configuration.json dari atas, yaitu pada konfigurasi untuk microservice 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 oleh 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 terkadang 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 melakukan penyeimbangan beban dengan infrastruktur orkestrator dan cloud.

UpstreamPathTemplate adalah URL yang akan digunakan Ocelot untuk mengidentifikasi DownstreamPathTemplate mana yang akan digunakan untuk permintaan tertentu dari klien. Akhirnya, 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 disebutkan dalam bagian arsitektur dan desain, jika Anda benar-benar ingin memiliki layanan mikro otonom, mungkin lebih baik untuk membagi API Gateway yang bersifat monolitik itu menjadi beberapa API Gateway dan/atau BFF (Backend untuk 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 Ocelot API Gateway 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 gambar Docker gateway Ocelot tunggal untuk semua gateway API.

Gambar 6-33. Menggunakan kembali satu image Docker Ocelot pada berbagai tipe API Gateway

Di eShopOnContainers, "Generic Ocelot API Gateway Docker Image" dibuat dari 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 pada 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 waktu proses 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 sebagaimana yang ditunjukkan di Visual Studio Explorer di bawah ini, satu-satunya file yang dibutuhkan untuk menentukan setiap bisnis spesifik/BFF API Gateway hanyalah file configuration.json, karena keempat API Gateway didasarkan pada image Docker yang sama.

Cuplikan layar memperlihatkan semua gateway API dengan file configuration.json.

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 API Gateway 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 Gateways (disertakan secara default dalam 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 downstream internal di host Docker, seperti yang terlihat di browser berikut.

Cuplikan layar browser yang memperlihatkan respons melalui gateway API.

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

Karena alasan pengujian atau debug, jika Anda ingin langsung mengakses kontainer Docker Katalog (hanya di lingkungan pengembangan) tanpa melewati gateway API, karena 'catalog-api' adalah resolusi DNS internal pada host Docker (penemuan layanan yang ditangani oleh nama layanan yang didukung oleh 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 seperti berikut.

Cuplikan layar browser memperlihatkan respons langsung ke Catalog.api.

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

Tetapi aplikasi dikonfigurasi sehingga mengakses semua layanan mikro melalui API Gateway, 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. Cara yang dipilih untuk menerapkan agregasi di eShopOnContainers adalah dengan layanan API Web Core 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 arsitektur eShopOnContainers memperlihatkan layanan agregator.

Gambar 6-37. Arsitektur eShopOnContainers dengan layanan agregator

Dengan memperbesar lebih lanjut, pada area bisnis "Belanja" dalam gambar berikut, Anda dapat melihat bahwa komunikasi intensif antara aplikasi klien dan layanan mikro berkurang saat menggunakan layanan agregator di API Gateway.

Diagram memperlihatkan arsitektur eShopOnContainers memperbesar tampilan.

Gambar 6-38. Memperbesar visi layanan Agregator

Anda dapat melihat bagaimana ketika diagram menunjukkan kemungkinan permintaan yang berasal dari API Gateway, itu bisa menjadi rumit. 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 juga bisa mungkin, jika diperlukan.

Autentikasi dan otorisasi di Ocelot API Gateways

Di Gateway API Ocelot, Anda dapat menempatkan layanan autentikasi, seperti layanan ASP.NET Core Web API menggunakan IdentityServer yang menyediakan token otentikasi, baik di luar maupun di dalam API Gateway.

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

Diagram memperlihatkan Layanan mikro identitas di bawah gateway API.

Gambar 6-39. Posisi layanan Identitas di eShopOnContainers

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

Diagram memperlihatkan autentikasi di Ocelot API Gateway.

Gambar 6-40. Autentikasi pada 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 autentikasi. Karena aplikasi eShopOnContainers telah memecah API Gateway menjadi beberapa BFF (Backend untuk Frontend) dan API Gateway area bisnis, opsi lainnya adalah membuat API Gateway tambahan untuk kebutuhan lintas fungsional. Pilihan itu akan adil dalam arsitektur berbasis layanan mikro yang lebih kompleks dengan beberapa layanan mikro yang menangani kekhawatiran lintas. Karena hanya ada satu aspek yang mempengaruhi banyak bagian di eShopOnContainers, diputuskan untuk mengelola layanan keamanan di luar lingkup API Gateway, untuk alasan kesederhanaan.

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

Cara mengamankan layanan apa pun dengan autentikasi di level API Gateway adalah 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, akan memeriksa ReRoutes AuthenticationOptions.AuthenticationProviderKey dan memastikan 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 [Authorize] pada sumber daya apa pun untuk diakses, seperti mikroservis, seperti contohnya pada pengontrol mikroservis Basket berikut.

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

ValidAudiences seperti "basket" berkorelasi dengan audiens yang ditentukan dalam setiap mikroservis dengan elemen 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 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 menjadi 403 Forbidden.

Menggunakan Kubernetes Ingress ditambah Gateway API Ocelot

Saat menggunakan Kubernetes (seperti di kluster Azure Kubernetes Service), Anda biasanya menyatukan semua permintaan HTTP melalui tingkat Ingress Kubernetes 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 lapisan tengah antara Internet dan layanan Anda (termasuk gerbang API), yang bertindak sebagai proksi terbalik.

Sebagai definisi, Ingress adalah kumpulan aturan yang memungkinkan koneksi masuk menjangkau layanan kluster. ingress dikonfigurasi untuk menyediakan layanan dengan URL yang dapat dijangkau secara eksternal, menyeimbangkan lalu lintas, pemutusan SSL, dan fitur lainnya. 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 Gateways adalah ujung depan atau antarmuka yang hanya menyediakan layanan tetapi bukan aplikasi web yang biasanya tidak termasuk dalam cakupan mereka. 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.

Diagram yang menunjukkan bagaimana tingkat ingress cocok dengan lingkungan AKS.

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 API gateway. Ketika Anda menyebarkan eShopOnContainers ke Kubernetes, itu hanya mengekspos beberapa layanan atau titik akhir melalui ingress, 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 seluler dan proses bisnis belanja
  • /mobilemarketingapigw untuk BFF seluler dan proses bisnis pemasaran

Saat menyebarkan ke Kubernetes, setiap Ocelot API Gateway menggunakan file "configuration.json" yang berbeda untuk setiap pod yang menjalankan API Gateway. File "configuration.json" disediakan dengan memasang (awalnya dengan skrip deploy.ps1) volume yang dibuat berdasarkan peta konfigurasi Kubernetes bernama '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 dalam folder k8s/ocelot/. Ada satu file untuk setiap BFF/APIGateway.

Fitur lintas fungsi tambahan di Ocelot API Gateway

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