.NET Core Microservices – Ocelot API Gateway

Merhaba,

Bu içeriğimizde microservice yaklaşımını benimseyen bir uygulamada, client tarafından gelen istekleri ilgili servislere yönlendirme sorumluluğunu üstlenen API Gateway yapılanmalarından açık kaynak olan Ocelot kütüphanesiyle tanışacak ve nasıl kullanıldığını inceleyeceğiz.

Öncelikle API Gateway Nedir? sorusuna karşılık klavyeye almış olduğumuz Microservice Mimarisinde API Gateway Nedir? başlıklı makalemizi incelemenizi, ardından bu içeriği okumanızı tavsiye ederim.

Ocelot Nedir?

.NET Core Microservices - Ocelot API GatewayMicroservice yapılanmasını benimseyen uygulamalarda clientlardan gelen istekleri işlevsel açıdan uygun servislere yönlendirmekten sorumlu bir geçiş görevi gören API Gateway kütüphanesidir. Ocelot, clienttan gelen istek neticesinde oluşturulan HttpRequest nesnesini arkaplandaki servislere iletebilmek için HttpRequestMessage nesnesi oluşturmakta ve bu şekilde ulaştırmakla görevli middleware’dir. Ocelot, uygulamanın pipeline’ında ki son ara katmandır diyebiliriz ve bu yüzden bir sonraki middleware çağrılmamaktadır.

Ocelot’ın Kullanıldığı Deploy Tasarımları

Ocelot aşağıdaki gibi dağıtımlarda kullanılmaktadır.

Basit
Uygulamalarda
IdentityServer
Kullanıldığında
Çoklu Instance
Durumlarımda
.NET Core Microservices - Ocelot API Gateway .NET Core Microservices - Ocelot API Gateway .NET Core Microservices - Ocelot API Gateway
Birden fazla service’in kullanıldığı durumlarda client tarafından gelen istekleri ilgili servislere yönlendirmektedir. IdentityServer kullanılan bir uygulamada, Ocelot token talebi için gerekli yönlendirmeyi yapmakta ve alınan token ile birlikte yapılan istekleri başarıyla ilgili microservislere yönlendirmektedir. Load Balancer aracılığıyla birden fazla instance üzerinden istekleri karşılayabilmekte ve ilgili servislere dağıtabilmektedir.
Consul Kullanıldığında Service Fabric Kullanıldığında
.NET Core Microservices - Ocelot API Gateway .NET Core Microservices - Ocelot API Gateway

Peki Ocelot Nerelerde Kullanılmaktadır?

Ocelot aşağıdaki gibi birçok yeteneğe sahip olan bir kütüphanedir.

  • Routing
  • Request Aggregation
  • Service Discovery with Consul & Eureka
  • Service Fabric
  • Kubernetes
  • WebSockets
  • Authentication
  • Authorisation
  • Rate Limiting
  • Caching
  • Retry policies / QoS
  • Load Balancing
  • Logging / Tracing / Correlation
  • Headers / Method / Query String / Claims Transformation
  • Custom Middleware / Delegating Handlers
  • Configuration / Administration REST API
  • Platform / Cloud Agnostic

Ocelot Nasıl Kullanılır?

Ocelot kütüphanesinin kullanımını örneklendirebilmek için öncelikle basit seviyede bir microservice örneklendirmesinde bulunmamız gerekmektedir.

Örnek Senaryo Hazırlığı

Bunun için aşağıdaki gibi ‘ProductAPI’ ve ‘CostumerAPI’ olmak üzere iki proje oluşturalım.
dotnet new webapi --name productAPI
dotnet new webapi --name customerAPI

Şimdi bu projelere işlevsel özellik kazandırabilmek için sırasıyla ‘ProductController’ ve ‘CustomerController’ isimli controller sınıfları ekleyelim ve içeriklerini aşağıdaki gibi inşa edelim.

ProductAPI;

   [ApiController]
   [Route("api/[controller]")]
   public class ProductController : ControllerBase
   {
      public IActionResult Get()
      {
         return Ok(new List<string> { "Kalem", "Kitap", "Silgi", "Defter" });
      }
   }

CustomerAPI;

   [ApiController]
   [Route("api/[controller]")]
   public class CustomerController : ControllerBase
   {
      public IActionResult Get()
      {
         return Ok(new List<string> { "Hilmi Celayir", "Saniye Yıldız", "Nevin Yıldız", "Fatih Yılmaz" });
      }
   }

Ardından her iki projeye localde çalışılacağından dolayı uygun bir port tanımlayalım. Tabi bu işlem için ister ‘Program.cs’ dosyasını istersenizde ‘launchSettings.json’ dosyasındaki profilleri kullanabilirsiniz. Ben örneklendirme olarak ‘launchSettings.json’ dosyasını seçiyorum.

ProductAPI;

    "productAPI": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "weatherforecast",
      "applicationUrl": "https://localhost:5003;http://localhost:5002",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }

CustomerAPI;

    "customerAPI": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "weatherforecast",
      "applicationUrl": "https://localhost:5001;http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }

Evet… Artık microservicelerimiz hazır. Bundan sonra clientlardan gelecek olan istekleri tek elden karşılayabilecek ve isteğe uygun ilgili servise yönlendirecek olan api gateway projesini tasarlayalım.

Ocelot Entegrasyonu ve Konfigürasyonu

İlk olarak ‘GatewayAPI’ isimli projemizi oluşturalım.
dotnet new webapi --name getwayAPI

Bu projemizde localde çalışacağından dolayı portuna el atalım;

    "getwayAPI": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "weatherforecast",
      "applicationUrl": "https://localhost:5005;http://localhost:5004",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }

Ardından Ocelot kütüphanesini aşağıdaki kodu terminalde çalıştırarak ilgili projeye dahil edelim. (Nuget Ocelot)
dotnet add package Ocelot

Bu işlemden sonra uygulamanın herhangi bir dizininde(genellikle root tercih edilir) yapılandırmayı konfigüre edebilmek için ‘ocelot.json’ isminde bir dosya oluşturalım ve içeriğini aşağıdaki gibi temel ve en sade biçimde olacak şekilde inşa edelim. Bu kullanım Ocelot’a dair herhangi bir aktivite sergilemese de ilgili kütüphaneyi aktifleştirmek için yeterli olacaktır.

{
   "Routes": [],
   "GlobalConfiguration": {
       "BaseUrl": "https://localhost:5005"
   }
}

Burada ‘GlobalConfiguration’ içerisindeki ‘BaseUrl’ api gateway uygulaması için esas url’i bildirmektedir. Bu projenin Ocelot kütüphanesi aracılığıyla microservislere erişimi sağlayabilmesi için aşağıdaki gibi konfigürasyonda bulunulması gerekmektedir.

{
   "Routes": [
      {
         "DownstreamPathTemplate": "/api/customer",
         "DownstreamScheme": "https",
         "DownstreamHostAndPorts": [
             {
                 "Host": "localhost",
                 "Port": 5001
             }
         ],
         "UpstreamPathTemplate": "/api/gateway/customer",
         "UpstreamHttpMethod": [ "Get" ]
      },
      {
         "DownstreamPathTemplate": "/api/product",
         "DownstreamScheme": "https",
         "DownstreamHostAndPorts": [
             {
                 "Host": "localhost",
                 "Port": 5003
             }
         ],
         "UpstreamPathTemplate": "/api/gateway/product",
         "UpstreamHttpMethod": [ "Get" ]
      }
   ],
   "GlobalConfiguration": {
       "BaseUrl": "https://localhost:5005"
   }
}

Yukarıdaki konfigürasyonu izah etmemiz gerekirse eğer;

  • DownstreamPathTemplate
    Yönlendirme yapılacak microservice’in route’unu tutmaktadır.
  • DownstreamScheme
    İlgili microservice’e yapılacak isteğin hangi protokol üzerinden gerçekleştirileceğini bildirmektedir.
  • DownstreamHostAndPorts
    Microservice’in ‘Host’ ve ‘Port’ bilgilerini tutmaktadır.
  • UpstreamPathTemplate
    API Gateway üzerinden microservice’e yapılacak yönlendirmenin route’unu tutmaktadır.
  • UpstreamHttpMethod
    Hangi isteklerin yapılabileceği bildirilmektedir.

şeklinde tanımlama yapabiliriz.

Tabi içerisini bu şekilde konfigüre ettiğimiz ‘ocelot.json’ dosyasını ‘Program.cs’ dosyası üzerinden uygulamaya aşağıdaki gibi dahil etmemiz gerekmektedir.

   public class Program
   {
      public static void Main(string[] args)
      {
         CreateHostBuilder(args).Build().Run();
      }

      public static IHostBuilder CreateHostBuilder(string[] args) =>
          Host.CreateDefaultBuilder(args)
              .ConfigureAppConfiguration((hosting, config) =>
              {
                 config.AddJsonFile("ocelot.json", false, true);
              })
              .ConfigureWebHostDefaults(webBuilder =>
              {
                 webBuilder.UseStartup<Startup>();
              });
   }

Ayriyetten ‘Startup.cs’ dosyasında da programatik olarak servis entegrasyonunu ve middleware çağrısını gerçekleştirelim.

   public class Startup
   {
      public void ConfigureServices(IServiceCollection services)
      {
         .
         .
         .
         services.AddOcelot();
         .
         .
         .
      }
      async public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
      {
         .
         .
         .
         await app.UseOcelot();
         .
         .
         .
      }
   }

Test Edelim

Şu ana kadar yaptığımız çalışmayı test edersek eğer;
.NET Core Microservices - Ocelot API Gateway
şeklinde bir sonuçla karşılaşacağız.

Parametreli Yönlendirme

Microservice rotalarının parametre aldığı durumlarda ilgili parametre değeriyle birlikte yönlendirmeyi gerçekleştirebilmek için aşağıdaki gibi route tanımlanması gerekmektedir.

      {
         "DownstreamPathTemplate": "/api/product/{id}",
         "DownstreamScheme": "https",
         "DownstreamHostAndPorts": [
             {
                 "Host": "localhost",
                 "Port": 5003
             }
         ],
         "UpstreamPathTemplate": "/api/gateway/product/{id}",
         "UpstreamHttpMethod": [ "Get" ]
      }

Bu yapılanma üzerinden aşağıdaki gibi bir url üzerinden istek gönderildiği taktirde hedef servis tetiklenmektedir.
https://localhost:5005/api/gateway/product/1

Tüm İsteklerin Yakalanması

Aşağıdaki gibi bir tasarım, yapılan tüm isteklerin doğrudan proxy üzerinden yönlendirilmesini sağlayacaktır.

    {
        "DownstreamPathTemplate": "/{url}",
        "DownstreamScheme": "https",
        "DownstreamHostAndPorts": [
                {
                    "Host": "localhost",
                    "Port": 5003
                }
            ],
        "UpstreamPathTemplate": "/{url}",
        "UpstreamHttpMethod": [ "Get" ]
    }

Örneğin;
https://localhost:5005/api/product adresine yapılan isteği https://localhost:5003/api/product adresine yönlendirecektir.

Benzer mantıkla;

    {
        "DownstreamPathTemplate": "/{url}",
        "DownstreamScheme": "https",
        "DownstreamHostAndPorts": [
                {
                    "Host": "localhost",
                    "Port": 5003
                }
            ],
        "UpstreamPathTemplate": "/p/{url}",
        "UpstreamHttpMethod": [ "Get" ]
    },
    {
        "DownstreamPathTemplate": "/{url}",
        "DownstreamScheme": "https",
        "DownstreamHostAndPorts": [
                {
                    "Host": "localhost",
                    "Port": 5001
                }
            ],
        "UpstreamPathTemplate": "/c/{url}",
        "UpstreamHttpMethod": [ "Get" ]
    }

https://localhost:5005/p/api/product adresine yapılan isteği https://localhost:5003/api/product adresine, https://localhost:5005/c/api/customer adresine yapılan isteği https://localhost:5001/api/customer adresine yönlendirilecektir.

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Not : Örnek dosyayı indirmek için buraya tıklayınız.

Bunlar da hoşunuza gidebilir...

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

*