ASP.NET Ocelot ile Api Gateway ve Consul ile Service Discovery

Örnek projeyi github üzerinden indirmek veya görüntülemek için https://github.com/ayzdru/AspNetApiGatewayWithOcelotAndServiceDiscoveryWithConsul adresine gidebilirsiniz.

API Gateway Nedir?

API Gateway, gelen tüm requestleri alır, ardından bunları gerekli api servislerine yönlendirir. Bu şekilde tek bir yerden bütün api servislerimizi kullanabiliriz. 

Ocelot Nedir?

Ocelot bir API Gateway kütüphanesidir. Microservisler veya servis odaklı mimarilerde gelen requestleri istenen api servislerine yönlendirmeye ve geriye response olarak döndürmeye yarar. 

Service Discovery Nedir?

Hizmet Keşfi, servislerin birbirleriyle iletişim kurabilmesini, healt check ile sadece ayakta olan servislerin kullanılabilmesini, load balancing ile servislerin dinamik olarak dağıtılmasını sağlar.

 

Consul Nedir?

Consul, ilk olarak 2014 yılında DNS tabanlı hizmet keşfi için yayınlanan bir yazılımdır ve dağıtılmış Anahtar / değer depolama, segmentasyon ve yapılandırma sağlar. Kayıtlı hizmetler ve düğümler bir DNS arayüzü veya bir HTTP arayüzü kullanılarak sorgulanabilir.

1. Adım (Consul Kurulumu)

Buradaki linkten Consul'u indiriyoruz.

Daha sonra konsol (cmd)'yi açıyoruz.

Ben consul uygulamasını masaüstüne indirdim. Siz indirdiğiniz yere göre klasör yolunu girersiniz.

cd desktop
consul agent -dev

komutlarını çalıştırıyoruz.

Varsayılan olarak http://localhost:8500/ adresine giriyoruz. Sonuç olarak consul ui ekranına girebilmeniz lazım.

2. Adım (Api Servislerini Consul ile Konuşturma)

Order.API ve Product.API adlı 2 adet basit api projeleri oluşturuyoruz.

Örnek OrderController.cs

[ApiController]
    [Route("/api/[controller]")]
    public class OrderController : ControllerBase
    {
        private static readonly string[] ProductNames = new[]
        {
            "Araba", "Motorsiklet", "Bisiklet", "Çanta", "Ayakkabı", "Telefon", "Saat", "Kulaklık", "Televizyon", "Detarjan"
        };

        private readonly ILogger<OrderController> _logger;

        public OrderController(ILogger<OrderController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable<Order> Get()
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index =>  new Order
            {
                OrderedDate = DateTime.Now.AddDays(index),
                TotalAmount = rng.Next(10, 500),
                AppUrl = HttpContext.Request.Host.ToString(),
                ProductName = ProductNames[rng.Next(ProductNames.Length)]
            })
            .ToArray();
        }
    }

 

Install-Package Consul -Version 1.6.1.1

ile projemize nuget üzerinden Consul paketini yüklüyoruz.

ConsulExtensions.cs dosyasını oluşturuyoruz.

public static class ConsulExtensions
    {
        public static IServiceCollection AddConsulConfig(this IServiceCollection services, IConfiguration configuration)
        {
            services.AddSingleton<IConsulClient, ConsulClient>(p => new ConsulClient(consulConfig =>
            {
                var address = configuration.GetValue<string>("Consul:Host");
                consulConfig.Address = new Uri(address);
            }));
            return services;
        }

        public static IApplicationBuilder UseConsul(this IApplicationBuilder app)
        {
            var consulClient = app.ApplicationServices.GetRequiredService<IConsulClient>();
            var logger = app.ApplicationServices.GetRequiredService<ILoggerFactory>().CreateLogger("AppExtensions");
            var lifetime = app.ApplicationServices.GetRequiredService<IApplicationLifetime>();

            if (!(app.Properties["server.Features"] is FeatureCollection features)) return app;

            var addresses = features.Get<IServerAddressesFeature>();
            var address = addresses.Addresses.First();

            Console.WriteLine($"address={address}");

            var uri = new Uri(address);
            var registration = new AgentServiceRegistration()
            {
                ID = $"Order-{uri.Port}",
                // servie name  
                Name = "order",
                Address = $"{uri.Host}",
                Port = uri.Port
            };

            logger.LogInformation("Registering with Consul");
            consulClient.Agent.ServiceDeregister(registration.ID).ConfigureAwait(true);
            consulClient.Agent.ServiceRegister(registration).ConfigureAwait(true);

            lifetime.ApplicationStopping.Register(() =>
            {
                logger.LogInformation("Unregistering from Consul");
                consulClient.Agent.ServiceDeregister(registration.ID).ConfigureAwait(true);
            });

            return app;
        }
    }

Startup.cs dosyamızı düzenliyoruz

 public void ConfigureServices(IServiceCollection services)
        {
...
            services.AddConsulConfig(Configuration);     

...
        }      
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {

...
            app.UseConsul();          
... 
        }

Konsol (cmd) dotnet komutu üzerinden Api projelerimizi farklı adreslerden ayağa kaldırıyoruz.

cd C:\Projects\AspNetApiGatewayWithOcelotAndServiceDiscoveryWithConsul\source\Order.API\bin\Debug\netcoreapp3.1

dotnet Order.API.dll --urls=https://localhost:5001

dotnet Order.API.dll --urls=https://localhost:5002

cd C:\Projects\AspNetApiGatewayWithOcelotAndServiceDiscoveryWithConsul\source\Product.API\bin\Debug\netcoreapp3.1

dotnet Product.API.dll --urls=https://localhost:6001

dotnet Product.API.dll --urls=https://localhost:6002

Sonuç:

3. Adım (Ocelot ile Api Gateway projesini oluşturma ve Consul ile konuşturma)

Install-Package Ocelot.Provider.Consul -Version 16.0.1

ile projemize nuget üzerinden Ocelot ve Consul paketini yüklüyoruz.

ocelot.json dosyamızı oluşturuyoruz.

{
  "Routes": [
    {
      "UseServiceDiscovery": true,
      "DownstreamPathTemplate": "/api/order",
      "DownstreamScheme": "https",
      "UpstreamPathTemplate": "/order",
      "UpstreamHttpMethod": [ "Get" ],
      "ServiceName": "order",
      "LoadBalancerOptions": {
        "Type": "LeastConnection"
      }
    }
  ],
  "GlobalConfiguration": {
    "RequestIdKey": "OcRequestId",
    "ServiceDiscoveryProvider": {
      "Host": "localhost",
      "Port": 8500,
      "Type": "PollConsul",
      "PollingInterval": 100
    }
  }
}

Program.cs dosyasını düzenliyoruz.

 public class Program
    {
        public static void Main(string[] args)
        {
            new WebHostBuilder()
                .UseKestrel()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .ConfigureAppConfiguration((context, config) =>
                {
                    config
                        .SetBasePath(context.HostingEnvironment.ContentRootPath)
                        .AddJsonFile("appsettings.json", true, true)
                        .AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json",
                            true, true)
                        .AddJsonFile("ocelot.json")
                        .AddEnvironmentVariables();
                })
                .ConfigureServices(s => {
                    s.AddOcelot().AddConsul();
                })
                .ConfigureLogging((hostingContext, logging) =>
                {
                    logging.AddConsole();
                })
                .UseIISIntegration()
                .Configure(app =>
                {
                    app.UseOcelot().Wait();
                })
                .Build()
                .Run();
        }
    }

Api Gateway projemizi çalıştırıyoruz ve

Artık Servislerimizi dinamik ve load balancing özelliği ile ayağa kaldırabiliriz.

 

Örnek projeyi github üzerinden indirmek veya görüntülemek için https://github.com/ayzdru/AspNetApiGatewayWithOcelotAndServiceDiscoveryWithConsul adresine gidebilirsiniz.

Umarım yararlı olmuştur.

Mutlu kodlamalar..

Yorumlar kapalı