Önceki içeriklerimizde AWS Lambda teknolojisinden ve lambda function kavramından detaylıca bahsetmiştik. Bu içeriğimizde, Asp.NET Core Web API mimarisi üzerinden geliştirilmiş bir API’ı lambda function’ı olarak AWS Lambda’da serverless olarak nasıl deploy edebileceğimizi inceliyor olacağız. O halde buyrun başlayalım…
Hatırlarsanız eğer .NET İle Amazon API Gateway – AWS Lambda & DynamoDB Entegrasyonu başlıklı makalemde bir lambda function’ı tasarladıktan sonra deploy edip, ardından oluşturduğumuz bir Amazon API Gateway aracılığıyla bir endpoint’e bağlayarak ayağa kaldırmıştık. Esasında bu yaptığımız çalışma özünde serverless olan REST API çalışmasının ta kendisidir, öyle değil mi?
Ancak lambda function süreçlerinde kurguladığımız REST API’lar da gelen request’leri APIGatewayHttpApiV2ProxyRequest
türünden karşılamak ve tüm query string, route parameters ve body değerlerini bu tür üzerinden elde etmek gibi bir zorunluluğun olması oldukça bağlayıcı bir unsurdur. Halbuki Asp.NET Core API mimarisinde direkt olarak controller sınıflarını kullanarak operasyonları yürütebilir ve ekstradan bir referansla ilgilenmeksizin sadece işleve odaklanabiliriz.
Peki hoca, bizler hangi durumlarda AWS Lambda servisinde lambda function yerine Asp.NET Core API uygulaması host edelim? diye sorarsanız eğer bu soruya kritik arz etmeyen ve pek yoğun kullanılmayacak ve rağbet görmeyecek API’lar söz konusu olduğu durumlarda diye cevap verebilirim. Bunun nedeni AWS Lambda servisinde bir function’a yapılan request neticesinde bu function’ın başlatılabilmesi için öncelikli olarak belleğe yüklenmesi gerekliliğidir. Bu belleğe yüklenme fiiliyatı ister istemez zaman alacaktır ve bu zaman Cold Start(Soğuk Başlatma) olarak nitelendirilmektedir.
Cold Start, bir AWS Lambda function’ın ilk kez başlatılması yahut ilk başlatılmanın dışında uzun bir süre çalıştırılmaması durumunda söz konusu olan süreçtir. Bu terim ilgili function’a gelen çağrıya verilecek cevaptan önce, gerekli ön yüklemeleri yürüten ve function’ın kullanılabilirliğini sıcak/hazır bir duruma getirmek için ihtiyaç duyulan ek süreyi ifade etmektedir. AWS Lambda servisi, sıcak bir durumda olan function’a gelen çağrılara karşın hızlı bir refleks göstermektedir ve bundan dolayı genellikle yapılan bir request’e dönecek yanıt, bir öncekine nazaran daha hızlı olabilmektedir. Ancak function bir müddet tetiklenmemişse yahut ilk defa tetiklenecekse Cold Start süreci söz konusu olacaktır. Cold Start durumu performansı doğrudan etkileyebilmektedir ve ortadan kaldırmak için kesin bir yolu da bulunmamaktadır!
İşte function’lar da ki bu Cold Start durumu, söz konusu Asp.NET Core API uygulaması ise zamansal açıdan daha da uzun olabilme ihtimaline sahiptir. Hele hele ilgili uygulama karmaşık ve büyük ölçekli bir hacme sahipse AWS Lambda servisinde deploy edilmesi hiçte iyi fikir olmayabilir. Bu tarz uygulamaları dockerize etmek veya AWS App Runner, ECS, EC2 gibi sistemler üzerinden çalıştırmak daha iyi bir yaklaşım olabilir. Keza büyük ölçekli bir projenin AWS Lambda servisinde deploy edilmeye çalışılması, AWS Lambda’nın varlık sebebini ihlal eden bir durumdur diye de düşünebiliriz. Çünkü uygulamanın kullanım durumu ve amacına bağlı olarak tercih edeceğimiz bu serviste keyfi olarak karmaşık bir altyapıyı kurgulamaya çalışmak maliyet grafiği açısından oldukça olumsuz etkiye sahip bir seçim olacaktır.
Ayrıca ilgili API’da adil sürenin üzerinde(5 dk.) işlem yapan endpoint’ler söz konusuysa yine AWS Lambda bu tarz uygulamalar için önerilen yaklaşım olmayacaktır.
Tüm bunların dışında basit düzeyde CRUD işlevlerini yerine getiren ve DynamoDB, Cloudwatch, Kinesis ve S3 gibi AWS servislerinden temel düzeyde istifade eden, en fazla orta şeker tadında bir API söz konusuysa bu yaklaşım sizlere optimize edilmiş bir süreç sağlayacaktır.
Şimdi gelin burada bahse konu olan teorik bilgilere nazaran, pratiksel olarak AWS Lambda ile Asp.NET Core Web API uygulamasını host etmeyi ele alarak tecrübe etmeye çalışalım.
Örnek Çalışma
- Adım 1 (Projenin Oluşturulması ve Temel Yapılandırmanın Sağlanması)
Her şeyden önce bir Asp.NET Core Web API uygulaması oluşturunuz ve içerisine aşağıdaki controller sınıfını ekleyiniz.01020304050607080910111213141516using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace AWS.Lambda.AspNETCore.WebAPI.Deploy.Example.Controllers
{
[Route(
"api/[controller]"
)]
[ApiController]
public
class
ValuesController : ControllerBase
{
[HttpGet]
public
async
Task<IActionResult> Get()
{
return
Ok(DateTime.UtcNow);
}
}
}
- Adım 2 (AWS Lambda Kütüphanesinin Kurulumu ve Servis Yapılandırması)
Bu API uygulamasını AWS Lambda servisinde host edebilmek için uygulamaya Amazon.Lambda.AspNetCoreServer.Hosting kütüphanesini eklemeniz gerekmektedir. Bunun için Package Manager Console üzerinden şu talimatın verilmesi yeterlidir :NuGet\Install-Package Amazon.Lambda.AspNetCoreServer.Hosting -Version 1.5.1
Asp.NET Core API uygulamasının AWS Lambda’ya dönüştürülmesi için ihtiyaç duyulacak tek kütüphane bundan ibarettir. Yükleme işleminin ardından uygulamanın konfigürasyonlarında aşağıdaki gibi
AddAWSLambdaHosting
servisini yapılandırmanız gerekmektedir.1234567.
.
.
builder.Services.AddAWSLambdaHosting(LambdaEventSource.HttpApi);
.
.
.
Esasında uygulama açısından, AWS Lambda altyapısına deploy edilebilmesi için yapılması gerekenler bundan ibarettir.
- Adım 3 (Uygulamayı AWS Lambda Servisine Deploy Etme)
Bu işlem için AWS CLI’dan istifade ediyor olacağız. Şimdi ilk olarak proje dizinini powershell yahut cmd üzerinden açınız ve aşağıdaki talimatı vererek süreci başlatınız.dotnet lambda deploy-function
Burada görselde olduğu gibi sırasıyla ‘Runtime’, ‘Function Name’, ‘IAM Role’, ‘Memory Size’, ‘Timeout’ ve ‘Handler’ bilgileri istenecektir. Bu soru dizelerine karşılık görseldeki gibi cevap vermeniz yeterli olacaktır.
Bu noktada tek vurgulamak istediğim nokta runtime olarak .NET 6’nın bildirilmesidir. Evet, bu yazının klavyeye alındığı tarih sürecinde her ne kadar .NET’in 7 sürümü mevcut olsa da AWS Lambda servisinde mevcut olan en son runtime’ın .NET 6 olduğunu görüyoruz. Lambda Runtime sürümleri hakkında daha fazla bilgi için buradaki içeriğe göz atabilirsiniz.
Bu adımdaki talimatların doğru bir şekilde çalışabilmesi için
aws configure
komutu eşliğinde yetkili ve aktif bir Access Key’e sahip IAM kullanıcısının tanımlı olduğundan emin olunuz.İşler beklenildiği gibi giderse eğer AWS Lambda servisinden ilgili fonksiyonun oluşturulduğunu görebileceksiniz.
- Adım 4 (Lambda Function’a Url Oluşturma)
Şimdi deploy edilmiş olan bu API’a bir function url’i alınması gerekmektedir. Bunun için Amazon API Gateway’den istifade edebilir yahut farklı bir yöntem olarak daha da basitleştirilmiş olan ‘Function URL’i kullanabilirsiniz.Burada “Create function URL’ butonuna tıklayınız ve açılan pencerede ‘NONE’ sekmesini seçerek ‘Save’ butonuna tıklayınız.Bu işlem ilgili API’a karşılık aşağıdaki gibi bir endpoint oluşturacaktır. - Adım 5 (Test Etme)
Edinilen endpoint’i kopyalayarak tarayıcı üzerinden yukarıdaki gibi test ediniz. Testi gerçekleştirdiğinizde her şey yolundaysa eğer aşağıdaki gibi sonuç alabilirsiniz. - Adım 6 (Swagger’ı Aktifleştirmek – Environment Eklemek)
Deploy neticesinde edindiğimiz endpoint üzerinden görseldeki gibi Swagger’a erişim göstermeye çalıştığımızda bunun ilk etapta mümkün olmadığını görebiliyoruz.Bunun nedeni, Swagger’ın Development environment’ına uygun şekilde konfigüre edilmesidir. Haliyle bu durumda yapılması gereken ilgili lambda function’a bir environment eklemektir. Bunun için ‘Configuration’ sekmesi üzerinden ‘Environment variables’ kısmına geliniz ve aşağıdaki gibi ASPNETCORE_ENVIRONMENT anahtarına karşılık Development değerini ekleyiniz.Böylece Swagger’ı tekrar deneyebilir ve çalıştığını görebilirsiniz.
aws-lambda-tools-defaults.json Dosyasında Lambda Konfigürasyonlarını Depolama
Şimdi, bu yapmış olduğumuz işleri otomatikleştirerek deploy sürecini bir nebze daha kolaylaştırıyor olacağız. Misal olarak; bu geliştirdiğimiz API uygulamasında bir değişiklik olduğu taktirde AWS Lambda’ya yeniden deploy etmemiz gerekecektir. Bunun için baştan beri gösterdiğimiz yöntemleri manuel bir şekilde uygulamak; ‘Function Name’, ‘IAM Role’, ‘Memory Size’, ‘Timeout’ ve ‘Handler’ gibi değerleri tekrardan istenmesine sebebiyet verecektir ve bunları hatırlamak bir geliştirici için ciddi zulüm olabilir.
Evet, her ne kadar CLI bizlere süreci daha da kolaylaştırmak için yardımcı oluyorsa da bu değerleri proje içinde yapılandırma değerleri olarak depolamak hem daha mantıklı bir yaklaşım olacak hem de bu yöntem CLI kullanımı açısından da daha pratik olacaktır. İşte bunun için bir JSON dosyasından istifade ediyor olacağız. Şimdi gelin bunu nasıl yapacağımızı keşfedelim…
Şimdi bunun için ilk olarak oluşturduğumuz ve deploy ettiğimiz ‘AWSLambdaAspNETCoreWebAPIDeployExample’ isimli lambda function’ı silerek başlayalım. Tabi bu silme işlemini AWS Lambda servisinin arayüzü üzerinden gerçekleştirebilir yahut AWS CLI’ı da tercih edebilirsiniz. AWS Lambda servisinden bu işlemin nasıl yapılacağı aşikar, o halde bizler yeni bilgi olması hasebiyle AWS CLI üzerinden silme işleminin nasıl yapılabileceğine odaklanalım.
Öncelikle mevcudiyette olan tüm lambda function’ları görebilmek için aşağıdaki talimatı veriniz.
aws lambda list-functions
Devamında ise silinecek olan lambda function’ı aşağıdaki talimatla bildiriniz.
aws lambda delete-function --function-name AWSLambdaAspNETCoreWebAPIDeployExample
İlgili talimat eşliğinde hedef lambda function’ın silindiğinden emin olabilirsiniz. Artık oluşturacağımız lambda function’ın yapılandırma değerlerini tutacağımız
aws-lambda-tools-defaults.json dosyasına odaklanabiliriz. Bunun için Visual Studio üzerinden projenin root path’inde bahsi geçen isimde bir json dosyası oluşturunuz. Bu dosya adı AWS CLI’da lambda operasyonlarına özel varsayılan dosya adı olduğu için belirtilen isimde olmasına özen gösteriniz.
Ardından oluşturulan bu json dosyasının içerisini aşağıdaki gibi doldurunuz.
01 02 03 04 05 06 07 08 09 10 11 12 | { "profile" : "" , "region" : "" , "configuration" : "Release" , "function-runtime" : "dotnet6" , "function-memory-size" : 256, "function-timeout" : 30, "function-handler" : "AWS.Lambda.AspNETCore.WebAPI.Deploy.Example" , "function-name" : "AWSLambdaAspNETCoreWebAPIDeployExample" , "environment-variables" : "ASPNETCORE_ENVIRONMENT=Development;" , "function-url-enable" : true } |
Yukarıdaki çalışmaya göz atarsanız eğer deploy edilecek function’a karşılık tüm yapılandırma değerlerini burada sabitlemiş bulunmaktayız. Tabi ‘profile’ ve ‘region’ bilgileri hariç. Çünkü bu bilgiler AWS CLI için başta yapılandırılmış vaziyettedir. O yüzden gerek görülmemektedir. Ayrıca oluşturulacak bu function’da, yukarıdaki çalışmanın 4. adımında görmüş olduğumuz function url’i aktifleştirebilmek için ‘function-url-enable’ property’sine karşılık ‘true’ değerini veriyoruz.
Bu tarz kalıcı konfigürasyonel yaklaşım, ilk etapta yaptığımız örnek çalışmadaki yaklaşıma nazaran oldukça kullanışlı olsa gerek… Öyle değil mi? Haa, bu yaklaşımda sadece ekstradan rol ve politika seçimlerini AWS Console üzerinden yapmak gerekebilir. Bunun da kalıcı yapılandırılmamasının sebebi, yeni rol ve politikaların eklenmesi durumuna karşın esneklik sağlayabilmektir.
Velhasıl,
Şimdi yapılan bu çalışma neticesinde projenin ana dizinine odaklanmış bir powershell ya da cmd üzerinden aşağıdaki talimatı vererek ilgili function’ı deploy ediniz.
dotnet lambda deploy-function
Normalde bir önceki çalışmada bu talimatı verdiğimizde deploy edilecek lambda ile ilgili gerekli bilgileri tek tek girmemiz gerekirken, şimdi ise AWS CLI
aws-lambda-tools-defaults.json dosyasının varlığını görebildiğinden dolayı bu yapılandırma dosyasından otomatik olarak aldığını ve sadece kullanılacak rolün tarafımızca seçilmesi gerektiğini görmekteyiz.
Vee böylece başarıyla API uygulamasını lambda servisine deploy etmiş olduk. Artık bu son çalışmanın testini de sizlere bırakıyorum
İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…
Not : Örnek projeye aşağıdaki github adresinden erişebilirsiniz.
https://github.com/gncyyldz/AWS.Lambda.AspNETCore.WebAPI.Deploy.Example
Hiç Yorum Yapılmamış. İlk Yorumu Sen Yap