Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

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

8 Cevaplar

  1. zeynep dedi ki:

    ben çalıştıramadım istek ulasadı diger kısımlara bana örnek projeyi githubtan paylasma sansınız varmı

  2. mustafa dedi ki:

    Hocam merhaba,

    Bu konu üzerinde çalışırken sunucu ortamında hata ile karşılaşıyorum. Localde her şey çalışırken subdomainlerle oluşturduğum microservicelerimi sunucuya atınca hata alıyorum. Örneğin http://auth.domain.com adresine postmandan post çağrısı atınca kendi başına çalışıyor ancak gateway https://api.domain.com/api/login üzerinden çağrı atınca 500 alıyorum. Herhangi bir detayda göremiyorum. Burada hatayı yakalamamın bir yolu var mıdır? Ocelotun yüklü olduğu gatewayimin SSL sertifikalı olması, diğer microservicelerin SSL’siz olmasının bununla alakası var mıdır?

    Teşekkürler.

    • Gençay dedi ki:

      Merhaba,

      Probleminize dair bende araştırmalarımı yapıyorum. Eğer çözüme kavuşursanız burada bizimle paylaşmanızı istirham ederim.
      Kolay gelsin.

  3. Önder ALKAN dedi ki:

    Hocam merhaba. Bu olayın reverse proxy olayından ne farkı var? Ocelot paketinin yaptığı işlemi proxy acaılığı ile de yapabiliyoruz aslında.

    • faydalı bir adam dedi ki:

      merhaba. burdaki konu sadece isteğin yönlendirilmesi değil. yazılım mimarisineki avantajları. bir önceki makaleyi incelemenizi öneririm.

  1. 05 Ekim 2020

    […] .NET Core Microservices – Ocelot API Gateway başlıklı makalemizde bir Gateway kütüphanesi olan Ocelot’un; microservice’ler […]

  2. 21 Aralık 2021

    […] Yararlandığım Kaynaklar: https://www.gencayyildiz.com/blog/ […]

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir