.NET Core API Gateway (asp.net core 3.1 + Ocelot)
Merhaba arkadaşlar, bügünkü yazımda son günlerin trend topic konusu microservice’lerin olmazsa olmaz patternlerinden api gateway ve api gateway patternini .Net ekosistemi içinde uygulamayı kolaylaştıran Ocelot’dan bahsedeceğim.
Gartner microservice için ne demiş;
A microservice is a service-oriented application component that is tightly scoped, strongly encapsulated, loosely coupled, independently deployable and independently scalable.
Açıklayacak olursak; çerçevesi tam olarak belirlenmiş(bakınız bounded context), olabildiğince kapsüllenmiş, diğer servislere olan bağlılığı mümkün olduğunca koparılmış, bağımsız olarak deploy(herhangi bir anda yapılan geliştirmenin yayına alınabilmesi) ve scale(ihtiyaç adında uygulamanın instance’nın bağımsız şekilde çoğaltılabilmesi yanında azaltılabilmesidir) olabilen uygulama modülleri diyebiliriz.
Api Gateway nedir?
Diyelimki bir microservice dönüşümü içindesiniz veya yeni projenizde microservice mimari yapısını uygulamaya karar verdiniz. Bu proje örneğimiz herkesin az çok fikir sahibi olmasından dolayı E-Ticaret olsun. Hadi gelin sadece ürün detayı ile ilgili ihtiyaç olunan servislerden bahsedelim.
Sayfayı oluşturalım. www.example.com/products/1 dedik. Catalog servisinden ürünü aldık. Price servisinden ürünle ilgili fiyat ve kampanya fiyatlarını aldık. Ürünle ilgili görselleri cdn servisimizden aldık, User servisinden kullanıcı bilgilerini aldık,ürün yorumları ve bu yorumlar işlenerek çıkan sonuçları details(isim aklıma gelmedi) servisimden aldık, ürünle ilişkili veya kullanıcın ilgili çekecek ek ürünler için data servislerimizin birini call ettik. Bir bakışta ürün ile ilgili sayafa için 6–7 servis sayabildik. Bu servislerinden kendine has adresleri var. Yüzlerce servisimiz olduğunu varsayalım. Hepsini ayrı bir url ve authorization, rate-limit vs olduğunuda düşünürsek işiniz içinden çıkılmaz bir hal alıyor.
İşte bu noktada Api Gateway Pattern devreye giriyor. Servislerimize tek bir giriş noktası oluşturup tüm servisler için ortak işlemlerin tek bir yerden yapılmasına olanak sağlıyor.
Api Gateway patternin bize sağladığı bazı işlevsellikler;
Authentication-Authorization
Reques-Response Logging
Response Cache
CorrelationId for Logging
Circiut Breaker
Retry
Rate Limit
Response Cache
IP White Or Black list
Ocelot’a gelelim
Ocelot, .Net ekosistemi üzerinde çalışan bir api gateway’dir. Ocelot, Http ile konuşabilen herhangi bir app ile iletişim kurabilmektedir.
Kısaca nasıl çalıştığını anlatacak olursak; Ocelot, gelen requesti yapılan konfigurasyonlara göre manipüle ederek. hedef route’a(ocelot içinde downstream olarak geçmekte) yeni bir request yapıp dönen result’ı client’a iletir.
Ocelot yeteneklerini aşağıdaki gibi sıralıyor.
- Routing
- Request Aggregation
- Service Discovery with Consul & Eureka
- Service Fabric
- Kubernetes
- WebSockets
- Authentication
- Authorisation
- Rate Limiting
- Caching
- Retry policies
- Load Balancing
- Logging / Tracing / Correlation
- Headers / Method / Query String / Claims Transformation
- Custom Middleware / Delegating Handlers
- Configuration / Administration REST API
- Platform / Cloud Agnostic
Peki bir örnekle peliştirelim o zaman.
Örneğimizde, odak kaybolmaması adına business rules olmayan foo ve bar adında 2 servisimiz olacak. Foo servisini go, Bar servisini ise .net core projesi ile geliştireceğim. Son olarak api gateway(ocelot) karşılığı olarak bir .net core projemiz daha olacak.
Not: Sizde örneklerde sürekli olarak neden foo ve bar kullanıldığını merak ediyorsanız, bunun için 3092 nolu rfc’ye bakabilirsiniz.
Not: .Net core ve Go uygulama geliştirme ile ilgili gerekli ortamların, geliştirme ortamınızda yüklü olduğunu varsayıyorum. Geliştirmeleri windows ortamında, Visual Studio Code ile geliştiriyorum.
Kodlamaya başlayabiliriz…
Öncelikle Api-Gateway-With-Ocelot adında bir klasör oluşturuyorum. Foo(Go) için, Foo adında bir klasör daha oluşturup foo.go adında bir dosya ekliyorum.
Bir console penceresi açıp go dizine gelioruz. code . komutu ile go projemizi visual studio code ile açıyoruz.
foo.go içeri aşağıdaki gibidir.
Oldukça basit bir go servisi.Httpserver ayağa kaldırıp 5001 nolu portu dinliyoruz. Örneğimiz için foo adında bir servisimiz bulunmakta.
console penceresinde foo dizinininde go run foo.go diyoruz. Aşığıdaki şekilde bir uyarı alabilrsiniz, Allow acces deyip devam edebilirsiniz.
Artık servisimizi çağırabiliriz. Browserdan http://localhost:5001 adresini call ediyoruz. Sonuç aşağıdaki gibidir.
Şimdi sıra geldi Bar servisimize. Öncelikle ana dizinimize(Api-Gateway-With-Ocelot) geri dönüyoruz. Daha sonra aşağdaki komutu çalıştırak “Bar” projemizi oluşturuyoruz.
“cd Bar” komutu ile “Bar” projemizin dizinine giriyoruz. “code .” komutu ile projemizi Visual Studio Code ile açıyoruz. Projeye “Bar” adında bir controller ekliyoruz.
BarController içeriği aşağıdaki gibidir.
“Bar” servsimizin 5002 nolu porttan çalışması için program.cs içeriğini aşağıdaki gibi değiştiriyoruz.
“dotnet run” komutu ile projemizi ayağa kaldırıyoruz. Browserdan http://localhost:5001 adresini call ediyoruz. Sonuç aşağıdaki gibidir.
Şimdi sıra geldi konumuz olan Api Gateway servisimize. Tekrardan ana dizinimize(Api-Gateway-With-Ocelot) geri dönüyoruz. Daha sonra aşağıdaki komutu çalıştırarak “ApiGateway” projemizi oluşturuyoruz.
“cd Bar” komutu ile “Bar” projemizin dizinine giriyoruz.”dotnet add package ocelot” komutu ile ocelot paketini projemize ekliyoruz.“code .” komutu ile de projemizi Visual Studio Code ile açıyoruz.
Ana dizine ocelot route konfigürasyonu için ocelot.json adında bir json file ekliyoruz. Foo ve Bar servislerimiz için gerekli tanımlamaları yapıyoruz.
Yapılan tanımları atlamayalım.
UpstreamPathTemplate:ApiGateway servisimize gelecek requestin route’ı belirlenmektedir.
UpstreamHttpMethod: ApiGateway request’in http werb’i(Http method) tanmlanmaktadır.
DownstreamPathTemplate: Gelen request’e karşılık eşleştirilecek servisin route bilgisi tanımlanmaktadır.
DownstreamHostAndPorts: Eşleştirilen route’un host ve port bilgisi tanımlanmaktadır.
DownstreamScheme: Eşleştirilen route için tanımlanan DownstreamHostAndPorts bilgisi için protokol tanımlanmaktadır.(http, https ..)
GlobalConfiguration.BaseUrl ile de api gateway’imizin url bilgisi tanımlanmaktadır.
Ocelot için gerekli servis ve middleware tanımlamaları için program.cs içerisindeki değişikliklerimiz ile birlikte son hali aşağıdaki gibidir.
Artık projelerimizi ayağa kaldırıp api gateway’imizi kullanabiliriz. Api Gateway projemizi de ayağa kaldırdıktan sonra http://localhost:5000/bar ve http://localhost:5000/foo servislerini call edelim. Sonuç aşağıdaki gibi olacaktır.
Gördüğünüz gibi api gateway patterni ocelot vasıtasıyla uygulayarak tek bir endpoint üzerinden servis erişimlerimizi sağlayabildik.
Ocelot, route işlemi yapmakla birlikte projeye birçok fonsiyonellik getirdiğinden bahsetmiştik. Hadi bunlardan bir tanesini daha test edelim.
Ocelot Rate Limited
Ocelot rate limited özelliği sayesinde gelen requestler için belirli süre için request limitleri belirleyip, aşıldığı takdirde belirlenen süre için ilgili client’tan gelen requesti yok sayabiliyoruz.
Foo servisi için, dakikada en fazla 10 request yapılacak şekilde konfigurasyonu yapalım.
RateLimitOption için tanımlanan özelliklere bakacak olursak; ClientWhitelist ile istediğimiz ip’leri bu kuralın dışında bırakabiliyoruz. EnableRateLimiting ile rate limiting’i aktif ediyoruz. 1 dakika içerisinde(Period(istenildiği takdirde 1s,1m,1h şeklinde period belirlenebilir)) , 10 request yapılırsa(Limit), client’ı 1 dk boyunca(PeriodTimeSpan saniye cinsinden) bloklayacağımızı belirttik.
ApiGateway projemizi tekrar ayağa kaldırıp, üst üste 10 request yaptıktan sonra aşağıdaki gibi bir uyarı ile karşılacaksınız.
Sonuç
Bu makelemizde, api gateway ve .Net ekosistemi için implementasyonu olan Ocelot’dan bahsettik. Adı her ne kadar daha çok microservice’lerle birlikte anılsa da, dışarıya açtığınız endpointler için ortak bir path uyarlamak istediğinizde de rahatlıkla kullanabilirsiniz.
Projenin kodlarında github adresimden ulaşabilirsiniz.
Umarım keyif aldığınız, bilgilendirici bir yazı olmuştur. Bir sonraki makalede görüşmek üzere, sağlıcakla kalın.
Kaynaklar