https://www.buraksenyurt.com/Burak Selim Şenyurt - AWS2018-04-27T06:34:40+00:00Matematik Mühendisi Bir Bilgisayar Programcısının NotlarıBurak Selim SenyurtBlogEngine.Net Syndication Generatorhttps://www.buraksenyurt.com/opml.axdBurak Selim SenyurtMatematik Mühendisi Bir Bilgisayar Programcısının Notlarıtr-TRBurak Selim Şenyurt0.0000000.000000https://www.buraksenyurt.com/post/net-core-ile-amazon-dynamodb-yi-kullanmak.Net Core ile Amazon DynamoDB'yi Kullanmak2018-04-16T06:00:00+00:00bsenyurt<p><img style="float: right;" src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/dynamocore_halo.gif" alt="" />Merhaba Arkadaşlar,</p>
<p>Epey zamandır NoSQL veritabanı sistemlerini kurcalamıyordum. Ağırlıklı olarak .Net Framework tarafında nasıl kullanılabildiklerini incelediğimi hatırlıyorum. 2017nin son çeyreği ve 2018in tamamı için kendime koyduğum hedeflerden birisi ise .Net Core dünyasını daha yakından tanımaktı. Zaten Ubuntu üzerinde koşan West-World'ün kurulum amacı da buydu. Sonuç olarak Amazon'un DynamoDb'sini .Net Core tarafında nasıl kullanabileceğimi incelemeye karar verdim. Bir süredir AWS Console üzerinden bir şeyler araştırıyor ve Amazon Web Service ürünleri hakkında giriş niteliğinde bilgiler edinmeye çalışıyorum.</p>
<p>Amazon DynamoDb şemasız(schema-less) olarak kullanılabilen bir NoSQL veritabanı sistemi olarak karşımıza çıkıyor. Key-Value tipine göre çalışan<em>(ama Document Store'a da benzeyen)</em> bir model sunduğunu söyleyebiliriz. Belli koşullar gerçekleşinceye kadar tamamen ücretsiz kullanılabilen hızlı bir veri tabanı da aynı zamanda. Bununla birlikte veriyi hızlı SSD'ler üzerinde tuttuğuna dair bir bilgi de var. Bu açıdan bakıldığında veriyi bellekte konuşlandırmayı seçen Redis'ten ayrışıyor.</p>
<p>Elastic MapReduce ile entegre olabilen, otomatik olarak ölçeklenebilen, Backup sürecinde S3 hizmetlerini kullanan DynamoDb ile ilgili Bahadır Akın'un <a href="http://www.bahadirakin.com/aws-dynamodb-nedir/" target="_blank">şu adreste</a> oldukça güzel ve detaylı bir yazısı da bulunuyor. Okumanızı tavsiye ederim. Onunla ilgili çalışmalara <a href="https://aws.amazon.com/dynamodb/getting-started/" target="_blank">bu adresten</a> hızlıca başlayabiliriz.</p>
<h1>Amazon Console Üzerinden Basit Bir Giriş</h1>
<p>Amazon Console web arayüzü üzerinden DynamoDb ile ilgili pek çok işlem gerçekleştirilebilir. Bir kaç dakika içerisinde tablolar oluşturabilir, insert, update, delete gibi temel veri işlemlerini gerçekleştirebiliriz. Söz gelimi sevdiğimiz oyun karakterlerine ait sözleri tutan bir tablo tasarlayabiliriz. Bunun için Create Table bağlantısından hareket etmemiz ve sayfadaki ilgili alanları doldurmamız yeterli.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/dynamocore_1.gif" alt="" /></p>
<p>BEn bu deneme sonucunda aşağıdaki gibi bir ekranla karşılaştım. </p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/dynamocore_2.gif" alt="" /></p>
<p>Quote isminde, Primary Key<em>(Partition Key)</em> olarak Game adında string tipte alan içeren bir tablo oluştu. Partition Key alanı özellikle veritabanının ölçeklendirilmesi noktasında önem arz eden bir konu. İkinci olarak eklediğimiz Sort Key alanı hızlı bir arama işlemi için ele alınacak ancak kullanılması elbette zorunlu değil. Game ve Character alanları bir arada yeni bir hash tanımının oluşmasına da neden olmakta. Tablonun tasarımını daha da detaylandırmamız mümkün. Şunu da unutmamak gerekiyor ki; iyi bir tablo tasarımı için partition key, sort key, global secondary index ve local secondary index kavramlarını iyi derecede kavramak lazım.</p>
<p>Oldukça detaylı ayarların yapılabildiği bir arabirim burası. Pek çok sekmeye yabancı olduğumu itiraf edebilirim. Yeni yeni keşfetmeye çalışıyorum. İlk olarak tabloya nasıl veri ekleyeceğimizi göstermeye çalışayım. Bunun için Items sekmesinden Create Item düğmesine basmak yeterli.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/dynamocore_3.gif" alt="" /></p>
<p>Tree olarak adlandırılan ve ağaç görünümü sunan arabirim kullanılabileceği gibi, Text moduna geçilerek JSON Formatındaki içeriğin elle yazılması da sağlanabilir. </p>
<p>Tree modundaki görünüm;</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/dynamocore_4.gif" alt="" /></p>
<p>Bunun text modundaki görünümü ise aşağıdaki gibiydi.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/dynamocore_5.gif" alt="" /></p>
<p>Bunun üzerine bir kaç öğe daha ekledim ve aşağıdaki içeriğin oluşmasını sağladım. Benim size önerim ücretsiz olarak sunulan REST tabanlı Quote hizmetlerinden yararlanarak veri girişi yapmanız. Bu güzel bir vaka çalışması da olabilir. Örneğin her gün bağlanıp o günün özlü sözünü aldığınız REST servis içeriğini, DynamoDB üzerindeki tablonuza aktarabilirsiniz ;)</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/dynamocore_6.gif" alt="" /></p>
<p>Sonra bir filtreleme yapmaya çalıştım. Text alanı içerisinde "I" kelimesi geçenleri bulmayı denedim.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/dynamocore_7.gif" alt="" /></p>
<p>Ardından Halo 2 oyununda karakterin adı G harfi ile başlayanların sözlerini nasıl süzebileceğime bir baktım.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/dynamocore_8.gif" alt="" /></p>
<p>Tabii benim yaptığım sadece arabirimi tanımaya çalışmak. Tablo tasarımı aslına bakarsanız yanlış. Söz gelimi bir oyuna bir karakter için n sayıda söz ekleyemeyiz. Dolayısıyla tasarımı bir oyunun birbirinden farklı karakterlerine ait en iyi sözlerin tutulduğu bir depo gibi düşünebiliriz. Eğer aynı oyuna aynı karakterden bir söz daha girmeye çalışırsak şu uzun ifadeye benzer hata mesajı ile karşılaşmanız muhtemel.</p>
<p>"The conditional request failed (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID: KP8D9MU06E36D9AH50IF9AV99RVV4KQNSO5AEMVJF66Q9ASUAAJG)</p>
<p>Tablo oluşturma, içine veri atma, veriyi sorgulama gibi basit işlemlerin Amazon Console arabirimi ile nasıl yapılabileceğini gördük. Ancak amacımız başta da belirttiğimiz gibi bir .Net Core uygulaması üzerinden Amazon DynamoDb'yi kullanmak.</p>
<h1>.Net Core Tarafını Geliştiriyoruz</h1>
<p>En büyük yardımcımız <a href="https://www.nuget.org/packages/AWSSDK.DynamoDBv2/" target="_blank">şu adresten sunulan DynamoDbv2 isimli NuGet</a> paketimiz olacak. Tabii birde Amazon servisine erişirken kullanacağımız geçerli bir kimlik bilgimizin(Credential) olması lazım. Dolayısıyla <a href="https://console.aws.amazon.com/iam/home#/home" target="_blank">IAM adresine giderek</a> bu uygulama için bir kullanıcı oluşturabilirsiniz. Ben daha önceden oluşturduğum AdministratorAccess rolündeki westworld-buraksenyurt kullanıcısına ait Access Key ID ve Secret Access Key değerlerini kullanacağım. Bu değerler bildiğiniz üzere IAM üzerinden kullanıcı oluşturduğunuzda size verilmekte.</p>
<p>İşe bir Console projesi oluşturarak başlayabiliriz.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">dotnet new console -o HowToDynamoDb</pre>
<p>Bu işlemin ardından DynamoDb NuGet paketini projeye eklememiz gerekiyor.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">dotnet add package AWSSDK.DynamoDBv2 --version 3.3.5</pre>
<p>İlk olarak DynamoDb üzerindeki tablo listesini çekmeye çalışalım. Ben deneme olması için önce Amazon Console'dan 3 tablo oluşturdum ve Program dosyasına aşağıdaki kodları yazdım<em>(Visual Studio Code kullanıyorum)</em></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Amazon;
using Amazon.DynamoDBv2;
using Amazon.Runtime;
namespace HowToDynamoDb
{
class Program
{
static void Main(string[] args)
{
var utl=new DynamoDBUtility();
var tableNames = utl.GetTables();
foreach (var tableName in tableNames)
{
Console.WriteLine($"{tableName}");
}
}
}
class DynamoDBUtility
{
AmazonDynamoDBClient aws;
public DynamoDBUtility()
{
var myCredentials=new BasicAWSCredentials("Application Key ID","Secret Access Key");
aws=new AmazonDynamoDBClient(myCredentials,RegionEndpoint.USEast2);
}
public List<string> GetTables()
{
var response = aws.ListTablesAsync();
return response.Result.TableNames;
}
}
}</pre>
<p>Öncelikle geçerli bir Credential bilgisi oluşturmalıyız. Bunun için BasicAWSCredentials sınıfını kullanabiliriz<em>(Siz kendi oluşturduğunuz kullanıcıya ait Key bilgilerini girmelisiniz ki bu bilgiler konfigurasyondan da gelebilirler)</em> Sonrasında AmazonDynamoDBClient türünden bir örnek oluşturuyoruz. Ben US-East-2 bölgesini kullandığım için ikinci parametrede RegionEndpoint.USEast2 değerini verdim. GetTables isimli metodun yaptığı işlem oldukça basit. ListTablesAsync metodu ile elde edilen tablo adlarını geriye döndürüyor. Sonuçlar aşağıdaki ekran görüntüsüne benzer olmalı <em>(AmazonDynamoDBClient üzerindeki pek çok operasyon awaitable nitelikte. Dolayısıyla tamamen asenkron olarak kullanılabilirler de)</em></p>
<p><em><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/dynamocore_9.gif" alt="" /></em></p>
<p>Peki kod ile sıfırdan bir tabloyu nasıl oluşturabiliriz? Kodu aşağıdaki gibi değiştirelim.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Amazon;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;
namespace HowToDynamoDb
{
class Program
{
static void Main(string[] args)
{
var utl = new DynamoDBUtility();
utl.CreateTable("GameQuotes","QuoteID", ScalarAttributeType.N);
utl.CreateTable("Players","Nickname", ScalarAttributeType.S);
var tableNames = utl.GetTables();
foreach (var tableName in tableNames)
{
Console.WriteLine($"{tableName}");
}
}
}
class DynamoDBUtility
{
AmazonDynamoDBClient aws;
public DynamoDBUtility()
{
var myCredentials=new BasicAWSCredentials("Application Key ID","Secret Access Key");
aws = new AmazonDynamoDBClient(myCredentials, RegionEndpoint.USEast2);
}
public List<string> GetTables()
{
var response = aws.ListTablesAsync();
return response.Result.TableNames;
}
public void CreateTable(string tableName,string partionKeyName,ScalarAttributeType partitionKeyType)
{
var tableResponse = GetTables();
if (!tableResponse.Contains(tableName))
{
var response = aws.CreateTableAsync(new CreateTableRequest
{
TableName = tableName,
KeySchema = new List<KeySchemaElement>
{
new KeySchemaElement
{
AttributeName = partionKeyName,
KeyType = KeyType.HASH
}
},
AttributeDefinitions = new List<AttributeDefinition>
{
new AttributeDefinition {
AttributeName = partionKeyName,
AttributeType=partitionKeyType
}
},
ProvisionedThroughput = new ProvisionedThroughput
{
ReadCapacityUnits = 3,
WriteCapacityUnits = 3
},
});
Console.WriteLine($"HTTP Response : {response.Result.HttpStatusCode}");
}
else
{
Console.WriteLine($"{tableName} isimli tablo zaten var");
}
}
}
}</pre>
<p>CreateTable isimli operayon DynamoDB üzerinde bir tablo oluşturmak için kullanılıyor. Üç parametresi var. Tablo ve Partition Key adları ile, Partition Key'in veri türünü alıyor. ScalarAttributeType üzerinden N(number), S(string) ve B(Binary) şeklinde anahtar türünün ne olacağını belirtebiliriz. Tablo oluşturma işlemini asenkron olarak kullanılabilen<em>(ki burada senkron bir işleyiş var)</em> CreateTableAsync fonksiyonu gerçekleştirmekte. Tabii tabloyu oluşturmadan önce var olup olmadığını da kontrol ediyoruz. Ben GameQuotes ve Players isimli iki tabloyu oluşturmayı denedim. İşlemler sorunsuz şekilde tamamlandıktan sonra AWS Console üzerinden de oluşturulan tabloları görebildim.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/dynamocore_10.gif" alt="" /></p>
<p>Şimdi tablolardan birisine veri eklemeye çalışalım. Henüz elimizde bir Entity örneği bulunmuyor. Öncelikle bu varlığa ait sınıfı tasarlamak lazım. GameQuotes tablomuz için aşağıdaki gibi bir sınıf yazabiliriz.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using Amazon.DynamoDBv2.DataModel;
namespace HowToDynamoDb
{
[DynamoDBTable("GameQuotes")]
public class Quote
{
[DynamoDBHashKey]
public int QuoteID { get; set; }
public QuoteInfo QuoteInfo { get; set; }
}
public class QuoteInfo
{
public string Character { get; set; }
public int Like { get; set; }
public string Game { get; set; }
public string Text { get; set; }
}
}</pre>
<p>Quote isimli sınıfın başında DynamoDBTable isimli bir nitelik<em>(attribite)</em> yer alıyor. Bu nitelikteki isim biraz önce oluşturduğumuz tablo adı ile aynı. Ayrıca QuoteID isimli bir Parition Key tanımlamıştık. Bu anahtarı Entity tarafında DynamoDBHashKey niteliği yardımıyla işaretliyoruz. Quote sınıfı, QuoteInfo tipinden bir özellik de barındırıyor. Bu sınıfta oyunun adını, sözü söyleyen karakteri, beğeni sayısını ve tabii sözün kendisini tutuyoruz. Aslında QuoteID ile ilişkilendirdiğimiz bir içeriğin söz konusu olduğunu ifade edebiliriz. Tam bir key-value ilişkisi. JSONca düşündüğümüzde de içiçe bir tip yapısı söz konusu.</p>
<p>Bir Quote nesne örneğini DynamoDB üzerindeki ilgili tabloya yazmak için Utility sınıfına aşağıdaki metodu ekleyerek ilerleyelim.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">public void InsertQuote(Quote quote)
{
var context = new DynamoDBContext(aws);
context.SaveAsync<Quote>(quote).Wait();
}</pre>
<p>Entity Framework dünyasındaki Context kullanımına ne kadar benziyor değil mi? :) Tek yapmamız gereken AmazonDynamoDBClient nesnesi ile ilişkilendirilmiş DynamoDBContext örneği üzerinden SaveAsync metodunu çağırmak. Generic parametre olarak Quote tipini kullandığımıza dikkat edelim.</p>
<p>Artık bir deneme yapabiliriz. Main metodu içerisinde aşağıdaki gibi bir kod parçası işimizi görecektir.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">var utl = new DynamoDBUtility();
Quote quote=new Quote{
QuoteID=1001,
QuoteInfo=new QuoteInfo{
Character="Cortana",
Game="Halo 2",
Like=192834,
Text="Child of my enemy, why have you come? I offer no forgiveness, a father's sins, passed to his son."
}
};
utl.InsertQuote(quote);</pre>
<p>Ben Halo 2 oyunundan Cortana isimli karaktere ait bulduğum bir sözü girdim. Programı çalıştırdıktan sonra hemen Amazon Console'a gittim ve eklenen yeni satırın aşağıdaki ekran görüntüsünde olduğu gibi eklendiğini gördüm.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/dynamocore_11.gif" alt="" /></p>
<p>Peki kod tarafında bu içeriği nasıl çekebiliriz? Gelin aşağıdaki fonksiyonu Utility sınıfına dahil ederek devam edelim.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">public Quote FindQuoteByID(int quoteID)
{
var context = new DynamoDBContext(aws);
List<ScanCondition> queryConditions = new List<ScanCondition>();
queryConditions.Add(new ScanCondition("QuoteID", ScanOperator.Equal, quoteID));
var queryResult = context.ScanAsync<Quote>(queryConditions).GetRemainingAsync();
return queryResult.Result.FirstOrDefault();
}</pre>
<p>Aslında bir arama koşulu listesi oluşturmaktayız. Senaryomuzda sadece bir kriter var o da Parition Key alanı olarak belirlediğimiz QuoteID değerine göre arama yapmak. ScanCondition ile belirlenen kriterde karşılaştırma koşulu, kullanılacak alan ve aranan değer bilgileri parametre olarak verilmekte. Sonrasında DynamoDBContext nesne örneği üzerinden hareket ederek ScanAsync operasyonunu kullanıyor ve içeriğe ulaşmaya çalışıyoruz. Main metodunda bu fonkisyonu kullanarak az önce eklediğimiz 1001 numaralı Quote içeriğine ulaşabiliriz.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">var utl = new DynamoDBUtility();
var findingQuote=utl.FindQuoteByID(1001);
Console.WriteLine($"{findingQuote.QuoteInfo.Character}\n{findingQuote.QuoteInfo.Text}");</pre>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/dynamocore_12.gif" alt="" /></p>
<p>Siz farklı arama ifadelerini bir araya getirerek değişik denemeler de yapabilirsiniz. Örneğin eklediğiniz n sayıda Quote içerisinden, belli bir oyuna ait olup beğeni değerleri 1000 ve üzerinde olanları çekmeyi deneyebilirsiniz.</p>
<h1>Daha neler neler yapılabilir?</h1>
<p>Örneğin oluşturduğumuz tabloların silinmesi, alan içeriklerinin güncellenmesi vb standart operasyonları deneyimleyebilirsiniz. Biraz fonksiyonellikleri araştırmanızda yarar var. NuGet paketinde gelen fonksiyonellikler Amazon DynamoDB'nin sunduğu imkanlara göre inşa edilmiş durumdalar. NuGet paketi üzerinden gelen operayonları asenkron olarak çalıştırmayı denemenizi öneririm. Benim örnek tamamen senkron çalışıyor<em>(Rezalet!)</em> Görsel arayüzü olan bir uygulamada awaitable operayonları dikkate alarak arayüzün donmasını engelleyecek şekilde değişiklikler yapmanız yerinde olur. Ah bir de tabii benim gibi God Object anti-pattern'inin yolunu açan, Single Responsibility ilkesini ihlal etmiş kirli bir Utility sınıfı kullanmayın :)</p>
<p>Böylece geldik bir makalemizin daha sonuna. Bu yazımızda Amazon'un NoSQL veritabanlarından olan key-value türevli DynamoDB'sini bir .Net Core uygulamasından nasıl kullanabileceğimizi incelemeye çalıştık. Fiyatlandırma kritlerini göz önüne alarak kendi ürünleriniz için kullanabileceğinizi düşünüyorum. Ben her ihtimale karşı onları sildim :) Geliştirmesi oldukça kolay. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="https://github.com/buraksenyurt/dotnetcore/tree/master/HowToDynamoDb" target="_blank">Yazıdaki kodlara github adresimden de erişebilirsiniz.</a></p>2018-04-16T06:00:00+00:00nosqlamazonamazon dynamodbdynamodb.net corec#key value storageDynamoDbV2bsenyurtEpey zamandır NoSQL veritabanı sistemlerini kurcalamıyordum. Ağırlıklı olarak da .Net tarafında nasıl kullanılabildiklerini incelediğimi hatırlıyorum. 2017nin son çeyreği ve 2018 için kendime koyduğum hedeflerden birisi ise .Net Core dünyasını daha yakından tanımak. West-World'ün kurulum amacı da özellik bu. Sonuç olarak Amazon'un DynamoDb'sini .Net Core tarafında nasıl kullanabileceğimi incelemeye karar verdim. Bir süredir AWS Console üzerinden bir şeyler araştırıyor ve Amazon Web Service ürünleri hakkında giriş niteliğinde bilgiler edinmeye çalışıyorum.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=fbf0eef5-e606-4020-8289-25039eb08d880https://www.buraksenyurt.com/trackback.axd?id=fbf0eef5-e606-4020-8289-25039eb08d88https://www.buraksenyurt.com/post/net-core-ile-amazon-dynamodb-yi-kullanmak#commenthttps://www.buraksenyurt.com/syndication.axd?post=fbf0eef5-e606-4020-8289-25039eb08d88https://www.buraksenyurt.com/post/bir-aws-elastic-beanstalk-macerasiAWS Elastic Beanstalk Macerası2018-02-16T05:00:00+00:00bsenyurt<p><img style="float: right;" src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/ebpython_robin.gif" alt="" />Merhaba Arkadaşlar,</p>
<p>Geçenlerde sıkıldığım bir ara kendimi Google'da "How To Draw..." araması yaparken buldum. <a href="http://www.drawinghowtodraw.com/stepbystepdrawinglessons/2016/10/draw-cute-kawaii-chibi-robin-dc-comics-batman-robin-easy-steps-drawing-lesson-kids/" target="_blank">Bir internet sitesinde</a> DC Comics'in Robin karakterini nasıl çizebileceğimizi anlatan içerik ilgimi çekmişti. Geometri bilgisini iyi kullandığı için anlaşılırdı. Tabii önemli bir eksiğim vardı...Yetenek. Sonuçları sizlerle paylaşmayı çok tercih etmiyorum ama yandaki Robin'in kafasının pek yakınlarından geçemediğimi gönül rahatlığıyla itiraf edebilirim. Dolayısıyla google aramasını ve internet sayfasını kapatıp tekrardan az buçuk anlamaya çalıştığım yazılım dünyasına döndüm.</p>
<p>Aslında bazen öğrenmek istediğimiz konuyu adım adım ve her adımında da tane tane anlatan bir dokümanı takip ederiz. Ama çalıştığımız ortamlar her zaman için bir yerlerde sorunlarla karşılaşmamıza neden olabilirler. Geçtiğimiz cumartesi günü de benzer sorunlarla karşılaştım. Amacım Amazon'un <a href="http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create-deploy-python-django.html?refid=em_68105" target="_blank">şu adreste</a> yayınladığı dokümanı takip ederek Elastic Beanstalk üzerine Django ile oluşturulmuş bir web uygulamasını taşıyıp Doğu Amerika kıtasındaki herhangibir Elastic Compute Cloud(Amazon EC2) sistemi üzerinden canlı yayına almaktı. İlk başlarda kolay giden adımlar özellikle sonlara doğru çeşitli sürprizlerle karşılaşmama neden oldu.</p>
<p>Her şey o Cuma günü AWS'de açmış olduğum hesapla neler yapabileceğime bakarken başladı. Bir süre öncesinde <a href="https://www.buraksenyurt.com/post/AWS-Lambda-Uzerinde-Net-Core-Kosturmak" target="_blank">Amazon Lambda hizmetini incelemiş</a> ve .Net Core ile kullanabildiğimi gördükten sonra epey keyif almıştım. Şimdiki hedefim Elastic Beanstalk ürünüydü. Kısaca Platform as a Service gibi konumlanan bu ürün sayesinde, çeşitli platformları Amazon EC2 örnekleri ile çalışacak şekilde hazırlayabiliyoruz. Platform anlamında oldukça geniş bir ürün yelpazesi de söz konusu. <a href="http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/concepts.platforms.html" target="_blank">Buradaki adresten</a> detaylarını öğrenebileceğinize gibi .Net Core'dan Go'ya, Python'dan Java'ya, Ruby'den Php'ye, Node.js'ten Docker'a kadar pek çok uygulama için hazır ortamlar söz konusu.</p>
<p>Buradaki hazırlıklarda Infrastructure as a Service gibi konumlanan Amazon EC2 tarafını da pek düşünmemize gerek kalmıyor esasında. Bu noktada EB'nin başarılı bir Deployment aracı olduğunu da ifade edebiliriz. EB'yi kullanırken Amazon Web Console üzerinden bir kaç tıklama ile bir platformu ayağa kaldırıp yayına almamız mümkün. İşte o Cuma akşamı bunu denemiştim. Şekilden de görüleceği gibi üzerinde Python 3.6 ortamı kurulu olan 64bitlik bir Linux makine emrime amadeydi. </p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/ebpython_0_1.gif" alt="" /></p>
<p>Hatta hazır şablon olarak gelen bir giriş sayfası da bulunuyordu<em>(What's Next? kısmı da oldukça dikkat çekiciydi. Django ve Flesk hemen dikkatimi çekmişlerdi)</em></p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/ebpython_0_2.gif" alt="" /></p>
<p>Adres satırından da göreceğiniz gibi her şey Amazon'un doğu Amerika bölgesinde bir yerlerde gerçekleşmekteydi(Sanırım) Kuvvetle muhtemel domain'in arkasında o bölgeye ait bir Cloud Server deposu ve EC2 makine örnekleri yer almaktaydı. Yönetim panelini kullanarak bu platform üzerine dosya bırakma yoluyla da taşımalar yapılabiliyordu. Benim merak ettiğim konu ise kendi geliştirme ortamımda yazdığım bir uygulamay<em>ı(veya hazır şablondan üretilmiş bir tanesini)</em> komut satırından Elastic Beanstalk ortamına nasıl aktarabileceğimdi. </p>
<p>O zaman maceramıza başlayalım. Yapacaklarımız özetle oldukça basit. West-world üzerinde(ki artık 64bit çalışan Ubuntu 16.04 sistemi olduğunu biliyorsunuz) sanal bir çalışma ortamı hazırlayacağız. Ardından bu ortamda Django çatısını kullanarak hazır bir web şablonu üreteceğiz. Elastic Beanstalk için gerekli olan çevre değişkenlerini ayarladıktan sonra bir Local Repository üretip taşıma adımlarını işleteceğiz.</p>
<h1>VirtualEnv Gerekli</h1>
<p>VirtualEnv ile linux üzerinde sanal bir ortam hazırlamamız mümkün. Bunu daha çok sistemde var olan paketlerden daha eski veya yeni sürümlerini kullanmak istediğimiz uygulamalarda ele alabiliriz.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">sudo apt-get install virtualenv</pre>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/ebpython_1.gif" alt="" /></p>
<h1>Sanal Ortamın Kurulumu</h1>
<p>VirtualEnv aracı hazır olduğuna göre artık sanal ortamın kurulmasına başlanabilir.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">virtualenv ~/beanstalk-virt</pre>
<p>ile python odaklı sanal ortam kurulur. Oluşan klasör içeriğine bakıldığında Python ile hazırlanmış kod dosyaları ve ortam enstrümanları olduğu görülür. Sürüm olarak Python 2.7 söz konusudur ki Amazon Elastic Beanstalk'da bu Python sürümünü tavsiye etmektedir. Sanal ortamı etkinleştirmek içinse aşağıdaki komutu kullanabiliriz.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">source ~/beanstalk-virt/bin/activate</pre>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/ebpython_2.gif" alt="" /></p>
<p>Artık West-World'ün üzerinde tamamen izole bir çalışma sahası var. </p>
<h1>Sahne Django'nun</h1>
<p>Python tarafında web uygulaması geliştirmek için kullanılan en popüler çatılardan birisi Django. Sanal ortama pip paket yöneticisi yardımıyla ilgili çatıyı kurmak gerekiyor.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">pip install django==1.9.12</pre>
<p>Amazon dokümantasyonuna göre desteklenen Django versiyonu önemli. Ben araştırmalarımı yaptığım sırada Amazon 1.9.12 sürümünün kullanılması tavsiye ediliyordu.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/ebpython_3.gif" alt="" /></p>
<p>Kurulum başarılı bir şekilde tamamlandıktan sonra hemen hazır web şablonu kullanılarak bir proje oluşturabiliriz. Aşağıdaki komut bunun için yeterli.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">django-admin startproject amznWebStore</pre>
<p>Projenin adı amznWebStore. Klasör içeriğine bakıldığında Python kod dosyalarından oluşan basit bir içerik oluşturulduğu görülebilir. Projeyi bu haliyle local makine üzerinden çalıştırmak istersek manage.py kod dosyasının aşağıdaki gibi çağırılması yeterlidir.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">python manage.py runserver</pre>
<p>Eğer işler yolunda gittiyse varsayılan olarak localhost'un 8000 numaralı portu üzerinden web içeriğine ulaşabiliriz.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/ebpython_4.gif" alt="" /></p>
<h1>Uygulamanın Elastic Beanstalk'a Taşınması</h1>
<p>Buraya kadarki işlemlerimizi şöyle bir hatırlayalım. İlk olarak West-World üzerinde sanal bir ortam açtık. Sanal ortam üzerinde Python yüklü olarak geliyordu. Oluşturulan ortamı etkinleştirdikten sonra basit bir Web uygulamasını ayağa kaldırmak için Django Framework'ü kurduk. Hiçbir kod değişikliği yapmadan manage.py dosyasından yararlanarak bu standart şablonun 127.0.0.1:8000 adresinden ayağa kaldırıldığını gördük. Sırada bu uygulamanın Elastic Beanstalk'a taşınması var. Önce bir kaç hazırlık yapmamız gerekiyor. İlk olarak ortam gereksinimlerin text dosyaya alıyoruz.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">pip freeze > requriements.txt</pre>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/ebpython_5.gif" alt="" /></p>
<p>Dosya içeriğinde aslında tek bir gereksinim var o da taşımanın yapılacağı ortamda Django'nun 1.9.12 sürümünün olmasını istiyor. Takip eden adımda amznWebStore kök dizini altında .ebextensions isimli yeni bir klasör oluşturup içerisine django.config isimli bir dosya atmamız gerekiyor. Bu dosyanın içeriği aşağıdaki gibi.</p>
<pre class="brush:py;auto-links:false;toolbar:false" contenteditable="false">option_settings:
aws:elasticbeanstalk:container:python:
WSGIPath: amznWebStore/wsgi.py</pre>
<p>Aslında Elastic Beanstalk ortamına söz konusu uygulamayı nereden başlatacağını söylemekteyiz ki bu senaryoda wsgi.py dosyası oluyor. Bu son iki adım bize şunu öğretmekte. Sanal ortamda geliştireceğimiz web uygulaması içerisinde neleri kullanırsak<em>(söz gelimi SQLite gibi bir veritabanı, Flesk çatısı vb)</em> bunların Elastic Beanstalk'a söylenmesi gerekmekte.</p>
<p>Sırada Command Languagen Interface'i kullanarak Local Repository'nin oluşturulması adımı var. Tabii bu aşamada benim gibi aşağıda görülen sorunlarla karşılaşabilirsiniz.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/ebpython_7.gif" alt="" /></p>
<p>İlk olarak eb isimli CLI aracı sisteminizde yüklü olmayabilir. Python ile yazılmış olan bu aracı kullanabilmek için pip yöneticisi ile kurmak gerekiyor. Lakin bu kurulum sanal ortamda gerçekleştirilebilen bir kurulum da değil. Benim düştüğüm bir diğer hata da bu oldu. deactivate komutu ile beanstalk-virt isimli sanal ortamdan çıktıktan sonra gerekli kurulum işlemini yaptım. Sonrasında sanal ortamı etkinleştirip eb init operasyonunu bir kez daha denedim.</p>
<p>Bu sefer daha farklı bir durumla karşılaştım. İlk olarak hangi bölge üzerine taşıma yapmak istediğimi sorduğunu düşündüğüm bir liste ile karşılaştım. Amazon web sitesi üzerinden yaptığım örneği düşünerekten us-east-2<em>(13ncü bölge)</em> seçimini yaptım. Tabii sonrasında gelen hata mesajı gayet açıktı. Credential bilgilerimi bildirmediğim için yetki hatası almıştım. Hemen <a href="https://console.aws.amazon.com/iam/home#/home" target="_blank">Amazon Web Console</a>'a geçerek ve AdministratorAccess Policy'sini kullanan westworld-buraksenyurt isimli bir kullanıcı oluşturdum. Access Key ID ve Secret Access Key değerlerini credential bilgilendirmesi için kullanarak adımı tamamlamayı başardım.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/ebpython_8.gif" alt="" /></p>
<p>Sonunda uygulama oluşturuldu. Artık tek yapılması gereken ortamın EB üzerine taşınmasıydı. Aşağıdaki komut ile bunu denedim.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">eb create my-eb-sample-env</pre>
<p>Evdeki hesap çarşıya uymamış gibiydi.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/ebpython_9.gif" alt="" /></p>
<p>Üstüne üstelik bir de şu vardı.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/ebpython_10.gif" alt="" /></p>
<p>Ne yazık ki sonuç pek beklediğim gibi olmadı. Komut satırı hareketliliklerini izlerken Elastic Beanstalk üzerinde my-eb-sample-env isimli uygulamanın oluşturulduğunu gördüm ancak site üzerinden yaptığım uygulama gibi yeşil değil kırmızı renkteydi. Ayrıca komut satırına requriements.txt dosyasının geçersiz olduğuna dair hata mesajı düşmüştü. Requirements.txt dosyasının oluşturulduğu adıma geri dönerek sorunu anlamaya çalıştım. İlk iş içeriğini aşağıdaki hale getirdim.</p>
<pre class="brush:plain;auto-links:false;toolbar:false" contenteditable="false">Django==1.9.12</pre>
<p>Başka bir şeye ihtiyacım yoktu çünkü. Tekrardan </p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">eb deploy</pre>
<p>ile taşıma işlemini yaptım. Şaşılacak şekilde yeşil oku gördüm. Uygulama Elastic Beanstalk üzerinde sağlıklı bir şekilde ayağa kalkmış gibi duruyordu. Komut satırından</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">eb open</pre>
<p>ile siteyi açtırmak istediğimdeyse yine hüsranla karşılaştım. HTTP_HOST header bilgisinin geçersiz olduğu söyleniyordu.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/ebpython_11.gif" alt="" /></p>
<p>Bunun üzerine amznWebStore klasöründeki settings.py dosyasını açıp ALLOWED_HOSTS değerinin olduğu satırı bulup aşağıdaki hale getirdim.</p>
<pre class="brush:py;auto-links:false;toolbar:false" contenteditable="false">ALLOWED_HOSTS = ['my-eb-sample-env.prii9kimtp.us-east-2.elasticbeanstalk.com']</pre>
<p>Sonrasında tekrar deploy ve tekrar open.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">eb deploy
eb open</pre>
<p>Nihayet! Uygulama Elastic Beanstalk üzerine başarılı bir şekilde taşınmış ve ayağa kaldırılmıştı. </p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2018/01/ebpython_12.gif" alt="" /></p>
<p>Biraz yorucu bir çalışma olduğunu ifade edebilirim ancak West-World üzerinde kurgulanan senaryonun Amazon Elastic Beanstalk üzerinde konuşlanması tatmin ediciydi de diyebilirim. Bu çalışma bana bir çok şey kattı. Bir PaaS'in tam olarak ne işe yarayabileceğini görme fırsatı buldum. Amazon Console penceresini kullanırken her deployment denemesi sonrası web panelindeki anlık hareketleri inceleyip başarılı bir log sisteminin nasıl olabileceğini ve monitoring'in ne kadar önemli olduğunu anladım. Belki Django ile oluşturulan web uygulaması için hiç kod yazmadım ama taşıma öncesinde platformun hangi gereksinimlere ihtiyacı olduğunun nasıl söylenebileceğini gördüm. Her anlamda yararlı bir çalışma olduğunu ifade edebilirim. Umarım sizler için de bilgilendirici olmuştur. AWS tarafını incelemeye devam ediyorum. Yeni bir şeyler öğrendikçe paylaşmaya çalışacağım. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.</p>2018-02-16T05:00:00+00:00pythonawsamazon web servicescloud computingpaasdjangoiaasamazonamazon elastic cloudamazon ec2bsenyurtBu yazımızda Django çatısından üretilmiş standart bir web uygulamasını, Amazon'un Platform As A Service olarak konumlandırdığı Elastic Beanstalk üzerine nasıl taşıyabileceğimizi öğrenmeye çalışıyoruz. Yolda tabii ki başımıza garip garip olaylar da geliyor. Özellikle sonlara doğru yaşadığımız sıkıntıları çözmeye de çalışıyoruz. Haydi gelin başlayalım.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=f1115529-4919-4642-ba2a-1301a6e150d71https://www.buraksenyurt.com/trackback.axd?id=f1115529-4919-4642-ba2a-1301a6e150d7https://www.buraksenyurt.com/post/bir-aws-elastic-beanstalk-macerasi#commenthttps://www.buraksenyurt.com/syndication.axd?post=f1115529-4919-4642-ba2a-1301a6e150d7https://www.buraksenyurt.com/post/AWS-Lambda-Uzerinde-Net-Core-KosturmakAWS Lambda Üzerinde .Net Core Koşturmak2018-01-11T21:30:00+00:00bsenyurt<p><img style="float: right;" src="https://www.buraksenyurt.com/image.axd?picture=/2017/12/awscore_11.gif" alt="" />Merhaba Arkadaşlar,</p>
<p>Çok yeni bir dünyanın içerisindeyiz uzun zamandır. Cloud Computing ile başladı. C#'ın Linux, MacOSX üzerinde çalıştığına şahit olurken, React Native'ın dünyayı sarsan yükselişine tanık olduk. Oysa ki daha bir süre öncesine kadar Scrum metodolojilerine alışmaya çalışıyor, TFS'e nasıl plug-in yazarıza bakıyorduk. Üniversite yıllarımızda internet bağlantısı bile olmayan bilgisayarlarda yazdığımız faktöryel hesaplama fonksiyonlarını, doğrudan sahibi olmadığımız Quantum bilgisayarlara yaptırmak için Serverless sistemlerden yararlanabileceğimiz bir dünya söz konusu artık. Şirketin hantallaşan iş alanlarını birer microservice haline getirip docker üzerinden host ettiğimiz gezegenler var artık. Çok hızlı dediğimiz Apache sunucularının yerini alan NGinx'e bakarken IIS'i unutup gidiyoruz belki de. Gelişiyoruz, değişiyoruz...Ve bu ikisini sürekli yapıyoruz. Adapte olmak zorundayız.</p>
<p>Konumuz Serverless, AWS Lambda ve .Net Core.</p>
<p>Günümüz bulut sistemleri göz önüne alındığında Microsoft Azure, Amazon Web Services ve Google Cloud Platform ilk aklımıza gelen ürünler oluyorlar sanıyorum ki. Neredeyse tamamının serverless olarak bildiğimiz yetenekleri de bulunuyor ki son yılın belki de en moda kavramlarından birisi bu. Kısaca Backend As A Services(BaaS) ya da Function As A Services(FaaS) şeklinde anılan Serverless teknolojisini halen daha anlamaya çalışıyorum. İşin aslı bu yeni yaklaşımdaki amaç, elimizdeki iş fonksiyonelliklerini sunucuların bakım, ölçekleme gibi ihtiyaçlarını düşünmeden sürekli dağıtım çarkının içerisine kolayca dahil edebilmek, hizmette oldukları süre boyunca parasını ödemek, böylece maliyetlerimizi mümkün olduğunca azaltmak.</p>
<p>Araştırmalarım şiddetini arttırınca gecenin bu saatlerinde internetten okuduğum bir yazıdaki şekli de aşağıdaki gibi renklendirmeye çalıştım. Şekil bir Web API uygulamasını AWS üzerine aldığımızda bilinen kullanımıyla yeni yaklaşım arasında nasıl bir fark oluştuğunu betimlemekte. Kullanıcı talepleri önce Amazon Web Service üzerindeki API Gateway'e geliyor. Talepler, Lambda üzerinden geçerek .Net Core'un çalışma zamanına inip oradan ilgili fonksiyonun işletilmesi, üretilen cevabın da geriye döndürülmesi işlemleri gerçekleşiyor. Özetle tanıdık olduğum senaryolardaki IIS ve NGinX gibi talebi karşılayan uygulamaların yerini AWS alıyor diyebiliriz.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2017/12/awscore_9.gif" alt="" /></p>
<p>AWS Lambda uzun zamandır ilgimi çeken bir üründü. Nitekim çok geniş bir uygulama desteği bulunuyor. Node Js, Python, Go, Ruby ve tabii .Net Core<em>(Tek üzücü olan şey konuya hazırlandığım 2017 Aralık ayı itibariyle AWS'nin .Net Core 1.0.4 SDK'sını desteklemesiydi)</em> Önümüzdeki aylar için yapılacaklar listeme eklediğim ödevlerden birisi de .Net Core ile yazdığım bir uygulamayı Lambda üzerinden yayınlamaktı.</p>
<p>Temelde AWS üzerinde 3 modelde uygulama geliştirebiliriz. Plain Lambda Function, Serverless Application ve Asp.Net Core App as Serverless Application<em>(Çizim buna ait)</em> Plain Lambda Function modeli ile bir C# sınıfının fonksiyonlarını AWS üzerinden tetiklenebilir hale getiriyoruz. İkinci modelde, yazılan uygulamanın API Gateway arkasında çalışacak şekilde CloudFormation<em>(YAML veya JSON formatında belli bir şablon kuralına göre taşımaya ait bilgileri yazdığımız dil olarak düşünülebilir)</em> kullanılarak taşınması söz konusu. Son modelde ise Asp.Net Core uygulamasının tek bir Lambda fonksiyonu haline getirilerek AWS üzerine taşınması söz konusu. Bu durumda API Gateway bir Proxy görevini üstleniyor diyebiliriz. Benim bu yazıdaki amacım ise bir Handler sınıfı ve içerisindeki fonksiyonları Lambda üzerine taşımak.</p>
<blockquote>
<p>Serverless yaklaşımı ile ilgili olarak iki yakın arkadaşımın harika birer yazısı var. Deniz İrgin'in "Sunucusuz Bir Dünya Mümkün mü?" yazısına <a href="https://medium.com/codefiction/serverless-architecture-sunucusuz-bir-d%C3%BCnya-m%C3%BCmk%C3%BCn-m%C3%BC-f7abab6ea0c8" target="_blank">bu adresten</a>, Arda Çetinkaya'nın da "Nedir bu Serverless?" isimli makalesine <a href="http://www.minepla.net/2016/09/nedir-bu-serverless/" target="_blank">şu adresten</a> ulaşabilirsiniz.</p>
</blockquote>
<p>Pek tabii her şeyin başında AWS'de bir hesap açmak gerekiyor. Bu hesap açma işlemi sırasında sizden bir de kredi kartı istenecek<em>(Ne yazık ki)</em> Free Plan'ı seçmeniz benimki gibi demo uygulamalarınız için yeterli olacaktır. Kritik noktalardan birisi AWS hesabını açtıktan sonra Identity and Access Management kısmından bir kullanıcı oluşturmamızın gerekliliği. Bu kullanıcıyı çeşitli yetkiler ile donattıktan sonra<em>(Genelde Administrator olarak)</em> bir Application ID ve Secret Key değeri üretilecek. Bu değeleri serverless<em>(biraz sonra değineceğim) </em>çatısına aşağıdaki komutlar ile bildirmek gerekiyor ki taşıma<em>(Deployment)</em> işlemleri sırasında AWS tarafındaki authenticate adımları başarılı sonuçlansın.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">serverless config credentials --provider aws --key Key_Değeri_Gelecek --secret Secret_Key_Değeri_Gelecek</pre>
<p><a href="https://serverless.com/framework/" target="_blank">Serverless</a>, Node.js ile yazılmış olan bir CLI<em>(Command Language Interface)</em> aracı. Bu aracı kullanarak AWS Lambda tarafında uygulama geliştirme ve taşıma gibi çeşitli operasyonları gerçekleştirebiliriz. Bu benim için oldukça ideal bir yaklaşım. Nitekim West-World üzerinde Visual Studio bulunmuyor<em>(Bu sene sadece Visual Studio Code kullanacağım)</em> Dolayısıyla AWS Lambda uygulamaları için gerekli hazır proje şablonlarını yükleyebileceğim bir ortam yok. Ama CLI üzerinden serverless çatısını kullanarak gerekli geliştirmeleri pekala yapabilirim. İlk etapta Nodejs'in son sürümünün yüklü olması gerektiğini söylemeliyim. Bu yüzden aşağıdaki komutlar ile Nodejs'i sisteme yüklemek gerekiyor. </p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
sudo apt-get install -y nodejs</pre>
<p>Yüklemenin ardından aşağıdaki komut ile serverless çatısını sisteme kurabiliriz.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">sudo npm install serverless -g</pre>
<p>Eğer her şey yolunda giderse aşağıdaki komutların sonucu olarak versiyon numarasını ve create komutu ile kullanabileceğimiz şablonları görebilmemiz gerekir.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">serverless --version
serverless create --help</pre>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2017/12/awscore_1.gif" alt="" /></p>
<p>Serverless çatısının başarılı bir şekilde yüklenmesinin ardından ben, hellolambda isimli bir klasör oluşturdum ve sonrasında içerisinde aşağıdaki komutu çalıştırarak Lambda dünyasına "Hello World" dedim.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">serverless create --template aws-csharp --name bssdemo</pre>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2017/12/awscore_2.gif" alt="" /></p>
<p>Ekran görütüsünden de görüleceği üzere C# için bir şablon otomatik olarak oluşturuldu. Buradaki Handler.cs, serverless.yml gibi içerikler hiç bozulmadan AWS'deki hesabımız ile ilişkilendirilip kullanılabilirler. Handler sınıfı içerisinde Hello isimli bir metod yer almakta. Bu metod Lambda tarafındaki fonksiyon olarak da düşünülebilir. Kabaca API Gateway'e gelecek olan talep sonrası işletilecek fonksiyon olduğunu söyleyebiliriz. Peki "Hello" isimli fonksiyonu sistem nereden bilecek? İşte serverless.yml içerisindeki aşağıdaki kısım burada devreye giriyor.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">functions:
hello:
handler: CsharpHandlers::AwsDotnetCsharp.Handler::Hello</pre>
<p>Tahmin edeceğiniz üzere Handler sınıfının kendisinin de içerisindeki fonksiyonun da adını değiştirebilir hatta n sayıda fonksiyonu sisteme dahil edebiliriz. Birden fazla handler'da burada söz konusu olabilir. İşin sırrı YAML içeriğinde gizli<em>(Biraz sonra değiştireceğiz)</em> </p>
<p>Tam build işlemlerine başlamıştım ki bir hatayla karşılaştım. global.json dosyasındaki SDK versiyonu 1.0.4ü gösteriyordu. West-World ise .Net Core'un 2.0 versiyonunu kullanıyordu. Dolayısıyla AWS'nin şu an desteklediği .Net Core 1.0.4 SDK'sı makinede yüklü değildi. Hemen bu versiyonu yüklemeye karar verdim. Ama endişelerim de vardı. Ya 2.0.0 ortamı bozulursa?!</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">sudo apt-get install dotnet-dev-1.0.4</pre>
<p>Bu komutla sisteme .Net Core 1.0.4 ortamını da yüklemiş oldum. Sonrasında paketi yüklemeyi tekrar denedim. Bulunduğum klasör itibariyle dotnet aracı .Net Core 1.0.4'ı dikkate almaya başlamıştı<em>(Bu arada build ve restore işlemlerinde .Net 1.0'ın 2.0'a göre acayip yavaş olduğunu belirtmek isterim)</em> </p>
<p>Derken ilk deploy işlemi sırasında "ServerlessError: The security token included in the request is invalid." şeklinde bir hata aldım. Sorun AWS hesabıma ait Credential bilgilerinin makinem için ayarlanmamasından kaynaklanıyormuş<em>(Thanks a lot Stackoverflow)</em> Bunun üzerine önce aşağıdaki komutlarla gerekli kayıt işlemlerini gerçekleştirdim<em>(Siyah ile boyalı kısımları söylemicim)</em></p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">export AWS_ACCESS_KEY_ID=application_id gelecek
export AWS_SECRET_ACCESS_KEY=Secret_key gelcek
serverless deploy</pre>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2017/12/awscore_3.gif" alt="" /></p>
<p>Sonrasında tekrardan build ve deploy işlemlerini gerçekleştirdim.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">sh build.sh
serverless deploy -v</pre>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2017/12/awscore_4.gif" alt="" /></p>
<p>Bir yerlere varıyor gibiydim. Küçük bir deneme yaptım. serverless çatısının invoke fonksiyonunu kullanarak şablon ile birlikte gelen hello operasyonunu çağırmayı denedim. Aşağıdaki gibi.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">serverless invoke -f hello -l</pre>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2017/12/awscore_5.gif" alt="" /></p>
<p>Sanki uygulama Lambda üzerinden çalıştırılmış gibiydi. Bu tabii standart şablon uygulaması. Değiştirmekte yarar var. Öncelikle HTTP taleplerine cevap vermesi için Amazon.Lambda. APIGatewayeEvents paketinin çözüme dahil edilmesi gerekiyor. Aşağıdaki komut ile bu işlemi yapabiliriz.</p>
<pre class="brush:bash;auto-links:false;toolbar:false" contenteditable="false">dotnet add package Amazon.Lambda.APIGatewayEvents -v:"1.1.0"</pre>
<p>Sonrasında Handler.cs dosyasının hem adını hem de içeriğini aşağıdaki gibi değiştirdim.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using Amazon.Lambda.Core;
using Amazon.Lambda.APIGatewayEvents;
using System;
using System.Net;
using System.Collections.Generic;
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
namespace AwsDotnetCsharp
{
public class SampleHandler
{
public APIGatewayProxyResponse GetGreetingsMessage(APIGatewayProxyRequest request, ILambdaContext context)
{
var response = new APIGatewayProxyResponse
{
StatusCode = (int)HttpStatusCode.OK,
Body = "{ \"Motto \": \"Merhaba ahbap. Nasıl gidiyor bakalım? :)\" }",
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
return response;
}
public APIGatewayProxyResponse GetLocalWeatherCondition(APIGatewayProxyRequest request, ILambdaContext context)
{
var response = new APIGatewayProxyResponse
{
StatusCode = (int)HttpStatusCode.OK,
Body = "{ \"Weather \": \"Sıcaklık 29 Derece. Hava güneşli\" }",
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
return response;
}
}
}</pre>
<p>SampleHandler sınıfı içerisinde iki fonksiyon yer almakta. Yaptıkları çok önemsiz. Ancak parametreleri ve dönüş tiplerine dikkat etmek lazım. Her ikisi de HTTP Get taleplerine cevap verip JSON formatında içerik döndürmekteler. Tabii eklenen bu iki fonksiyon için dağıtım kanalına da bilgi vermemiz gerekiyor. Bunun için de yml içeriğini aşağıdaki gibi düzenledim <em>(service: bssdemo aslında benim AWS üzerinden oluşturduğum bucket'a verdiğim ad. Geliştireceğimiz .Net uygulamasını bu hizmetin olduğu yerde konuşlandıracağız)</em></p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false">service: bssdemo
provider:
name: aws
runtime: dotnetcore1.0
package:
artifact: bin/release/netcoreapp1.0/deploy-package.zip
functions:
greetings:
handler: CsharpHandlers::AwsDotnetCsharp.SampleHandler::GetGreetingsMessage
events:
- http:
path: greetings/hi
method: get
utility:
handler: CsharpHandlers::AwsDotnetCsharp.SampleHandler::GetLocalWeatherCondition
events:
- http:
path: utility/weather
method: get</pre>
<p><em>(yml içeriğindeki girintiler oldukça önemlidir. Ben weather için yazdığım path ifadesini http ile aynı hizaya koyduğumda, serverless aracı ilgili path sekmesini bulamadığını söyledi)</em></p>
<p>sevice, provider, package ve functions. AWS özellikle bu kısımlara bakacak. provider tarafında aws ve .Net Core 1.0 kullanılacağı belirtiliyor. package tarafında build işlemi sonrası oluşan artifact işaret edilmekte. functions kısmında hangi operasyonları sunacaksak onlara ait bilgiler bulunuyor. handler'lar tip ve metod adlarını ifade ederken http sonrası gelen bilgiler de URL'in şekillenmesi için. get bildirimi tahmin edeceğiniz üzere talebin HTTP Get olacağını belirtmekte.</p>
<p>Kodun düzenlenmesini tamamladıktan sonra tekrardan build ve deploy işlemlerini gerçekleştirmek lazım. Aslında n tane fonksiyona yeni bir fonksiyon eklediysek sadece bu fonksiyonu deploy edebiliriz de<em>(Nasıl olabilir bir araştırın bakalım)</em></p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2017/12/awscore_6.gif" alt="" /></p>
<p>Artık API Gateway'in tetikleyeceği iki Lambda fonksiyonu söz konusu. Doğruyu söylemek gerekirse Postman aracı ile denemeleri yaptığımda gördüğüm sonuçlar beni mutlu etti.</p>
<p>İlk önce greetings/hi adresine HTTP Get talebi gönderdim.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2017/12/awscore_7.gif" alt="" /></p>
<p>Ardından utility/weather için bir talep daha.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2017/12/awscore_8.gif" alt="" /></p>
<p>Sonuçlar tatmin ediciydi. Daha önceden yazdığımız bir çok Web API'yi buraya entegre edebiliriz diye düşünüyorum. Pek tabii fonksiyonlar tamamen deneme amaçlı geliştirilmiş durumdalar. Siz içeriklerini istediğiniz gibi genişletebilirsiniz. AWS dünyası oldukça kapsamlı. Henüz MSDN rahatlığını bulabilmiş değilim dökümantasyonlarında. Bazen kayboluyorum ama ilgi çekici olduğunu da ifade edebilirim. Kavramlar yeni yeni oturmaya başladılar. <a href="http://www.codefiction.tech/" target="_blank">Codefiction</a> gibi web sitenizi AWS üzerine alabilirisiniz ya da şirketinizin elektronik ticaret alt yapısına ait fonksiyonellikleri burada barındırabilirsiniz. Bunları bir düşünün :) Böylece geldik bir makalemizin daha sonuna. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.</p>2018-01-11T21:30:00+00:00awsamazon web servicesserverless.net coreasp.net coreasp.net core web apiweb apibsenyurtBu yazımızda Amazon Web Service'lerinden Lambda ürününü kullanmaya çalışıyoruz. Geliştireceğimiz basit bir Asp.Net Core Web API hizmetini Lambda üzerine fonksiyon olarak yerleştiriyoruz.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=a1402e66-4840-44cb-9d5c-1a3e252c9d801https://www.buraksenyurt.com/trackback.axd?id=a1402e66-4840-44cb-9d5c-1a3e252c9d80https://www.buraksenyurt.com/post/AWS-Lambda-Uzerinde-Net-Core-Kosturmak#commenthttps://www.buraksenyurt.com/syndication.axd?post=a1402e66-4840-44cb-9d5c-1a3e252c9d80