SCOM 2012 Agent Troubleshooting Adımları

SCOM 2012 agent kurulumu sırasında alınan sık hatalardan birisi de admin$ paylaşımına erişilememesidir. Bu sebeple Management Server ilgili istemciye ulaşıp ajan kurulum paketlerini kopyalayamaz. Paralelde Wİndows Remote Registry’e ulaşımda da problem olacağı için Health Service kurulumunda sıkıntı olacaktır.

Bunun için gerekli ilk kontrollerden birisi Management Server ve istemci bilgisayar arasında aşağıdaki portların açık olması gerekiyor.

  • RPC endpoint mapper Port number: 135 Protocol: TCP/UDP
  • *RPC/DCOM High ports (2000/2003 OS) Ports 1024-5000 Protocol: TCP/UDP
  • *RPC/DCOM High ports (2008 OS) Ports 49152-65535 Protocol: TCP/UDP
  • NetBIOS name service Port number: 137 Protocol: TCP/UDP
  • NetBIOS session service Port number: 139 Protocol: TCP/UDP
  • SMB over IP Port number: 445 Protocol: TCP
  • MOM Channel Port number: 5723 Protocol: TCP/UDP

Aynı zamanda hedef bilgisayardaki aşağıdaki servislerin çalışıyor durumda olması gerekiyor:

  • Netlogon
  • Remote Registry
  • Windows Installer
  • Automatic Updates

Read More

SCOM 2012 R2 – SQL 2014 Desteği

İki gün önce önemli bir destek duyurusu System Center ailesi için yapıldı. Artık System Center Operations Manager 2012 R2 için veritabanı olarak SQL Server 2014 kullanılabilir durumda.

Enterprise veya Standard 64-Bit sürüm desteği sayesinde yapınızda SQL 2014 kurulumu gerçekleştirdiyseniz aynı zamanda SCOM veritabanı olarak kullanabilirsiniz.

Read More

Azure Storage Services – Part 9:Storage Services REST API Reference

Makalemizin bu bölümünde sözü tekrardan Fatih Doğan’a bırakıyoruz.

————————————————————

Storage Servıces REST API Reference

Storage servislerinde kullanabileceğiniz REST API’ları, Blob,Table ve Queue servislerine programlanabilir bir şekilde erişebilmenizi sağlıyor. Sadece Azure üzerindeki Storage servisleri demediğimi fark etmişsinizdir umarım. Geliştirme yapıyorsanız ve uygulamanızı test edecekseniz, gerçek bir ortam ile değilde lokal bir alana kurabileceğiniz bir emulatör ile geliştirmeyi tercih edersiniz. Sözünü ettiğimiz REST API’larını Azure Storage Emulatör’ünde de kullanabiliyorsunuz.

Önceki makalelerde de bahsettiğimiz gibi RESTful bir API’dan bahsediyorsak, HTTP/HTTPS istek gönderebilen ve alabilen bütün uygulamaların bu özellikleri kullanabileceği anlamına geliyor. Tabi Azure Storage servislerine erişim sağlamak istiyorsanız öncelikli geçitinizin HTTPS olması sizin güvenliğiniz için daha iyi olacaktır.

Storage Hesabı

Storage servislerini kullanabilmeniz için bir storage hesabına ihtiyacınız var. Bu storage hesabı, kullanacağınız storage servislerinde authentication olarak kullanılıyor. Ayrıca storage servislerinin alan adına dikkat ettiğinizde, hesap adının servis yolu içerisinde kullanıldığını göreceksiniz.

Blob Servisi

Blob servisinin genel amacı dosyalamadır. Buraya dosya olarak nitelendirebileceğiniz her şeyi atabilirsiniz. Blob servisinde kullanacağınız iki adet özellik var ; Container ve Blob.

– Container’ı kısaca klasör olarak nitelendirebilirsiniz. İçerisinde sizin bloblarınızı bulundurur.

– Blob ise dosyanın kendisidir. Her blob bir container içerisinde olmalıdır. Containersız bir blob olmaz.

Bloblar ise kendi arasında ikiye ayrılıyor ; Block ve Page.

– Block bloblar üzerinde fazla değişiklik yapmayacağınız, depolama ya da streaming amaçlı dosyalar için optimize edilmiştir.

– Page bloblar, rastgele okuma ve yazma işlemlerine göre optimize edilmiş blob tipidir.

Container içerisinde yeniden bir container oluşturamıyorsunuz ama container içerisindeki bloblarınızı organize etmek için sanal bir hiyerarşi oluşturabiliyorsunuz. Örneğin “dosyalar” isimli bir containera, “videolar/kediler.mp4” adında bir blob yükleyebilirsiniz. Böylece dosyanıza sanki “dosyalar” altındaki “videolar” klasöründe tutuluyormuş gibi davranabiliyorsunuz.

64 MB’dan küçük bir block blobu, “Put Blob” özelliğini kullanarak yükleyebiliyorsunuz. Bundan daha büyük bir block blob yüklemek isterseniz “Put Block List” özelliği ile dosyanızı maksimum 4 MB olacak şekilde parçalara ayırarak yükleyip, bu blob grubuna tek bir blobmuş gibi davranabiliyorsunuz. Şu anda desteklenen maksimum block blob büyüklüğü ise 200 GB.

Page blobların böyle bir kısıtlaması yok. “Put Blob” ile maksimum 1 TB olacak şekilde page blobunuz oluşturuluyor. “Put Page” özelliği ile de içerisine verilerinizi yazdırabiliyorsunuz.

Bloblar “Get Blob” özelliği sayesinde okunabiliyor. Client isterse bütün blobu ya da belirli bir bölümünü okuma gibi işlemler yapabilir.

http://msdn.microsoft.com/en-us/library/azure/dd135733.aspx

Table Servisi

Table servisi, OData protokolünü implemente eden bir tablolama hizmetidir. Bu tablolar datayı entity olarak tutarlar. Entity ise belli başlı özellikleri ve bu özelliklere karşılık gelecek değerleri olan bir yapıdır – row olarak düşünebilirsiniz. Storage Table servisi içerisine depolanacak her entity, PartitionKey ve RowKey özelliklerini barındırmalıdır. PartitionKey sayesinde entity belirli bir bölgeye ayrılırken, RowKey sayesinde ise bölge içerisindeki entitylerin benzersizliği – unique olması sağlanır. Bu iki key birleştirilerek entitynin tablo içerisinde benzersizliği sağlanmış olur.

Table servisi, entitylerin tablo yapısına uyması kuralını uygulamaz. Geliştiriciler belli bir şema uygulamak isterlerse bunu geliştirme sırasında uygulayabilirler.

http://msdn.microsoft.com/en-us/library/azure/dd179363.aspx

Queue Servisi

Queue servisi ile uygulamalar arası mesajlaşma gereksinimlerinizi karşılayabilirsiniz. Queue servisinde kullacağınız iki adet özellik bulunuyor ; Queue ve Message

Bir storage hesabında farklı isimleri olması şartıyla sınırsız sayıda Queue açabilirsiniz. Her queue de sınırsız sayıda Message bulundurabiliyor. Bir mesajın maksimum büyüklüğü ise 64 KB olarak belirlenmiş. 2011-08-18 versiyonundan öncesinde ise 8KB olarak tanımlı.

Bir mesaj queuedan okunduktan sonra, okuyan kişinin bu mesajı silmesi beklenir. Mesaj okunduktan sonra belirli bir süre boyunca diğer dinleyicilere görünmez hale getirilir. Eğer belirlenen süre aşılırsa ve mesaj hala silinmemişse, diğer dinleyicilerin okuması için mesaj yeniden görünür hale getirilir.

http://msdn.microsoft.com/en-us/library/azure/dd179423.aspx

Bu makalemizde de Blob, Table ve Queue servislerinin genel yapısını ve geliştirme kısmında bilinmesi gereken yanlarını inceledik.

Daha detaylı bilgi için:

http://msdn.microsoft.com/en-us/library/azure/dd179355.aspx

Read More

Azure Storage Services – Part 8:PowerShell ile Storage Service Kullanımı

Diğer yazılarımızda farklı platformlar üzerinden (GUI dahil) Azure Storage hizmetlerinin nasıl yönetileceğini deyaylı inceledik. Bu makalemizde ise sistem yöneticilerinin vazgeçilmez araçlarından olan PowerShell ile Storage hizmeti üzerinde yönetim aksiyonlarını inceliyor olacağız.

Azure subscription üzerinde PowerShell ile aksiyonlar almak için ilk yapılması gereken işlem Azure PowerShell modullerinin yüklenmesidir. Azure PowerShell modullerini Microsoft Web Platform Installer ile indirebilir ve kurabilirsiniz. Son dönemde Microsoft bu tarz eklenti ve paketleri WPI üzerinden sunmaya başladı. En güncel sürümleri indirmesi ve kolay şekilde yapılandırması sebebi ile WPI işlemlerimizi önemli ölçüde arttırdı.

image

Kurulumu hızlıca aşağıdaki şekilde gerçekleştirebiliriz.

image

image

Kurulum tamamlandıktan sonra artık kurulumu gerçekleştirdiğiniz bilgisayar üzerinde Azure PowerShell modülüne sahip oluyorsunuz. Azure komutlarını çalıştırmak için isterseniz özelleştirilmiş Azure PowerShell konsolunu açabilir yada varsayılan PowerShell konsolunda Azure modülünü yükleyerek devam edebilirsiniz.

Aşağıda kurulum ile birlikte gelen Azure PowerShell konsolunu görebilirsiniz.

image

Makale gereği PowerShell ile Storage hizmeti üzerinde aksiyonlar alacağız. Ancak PowerShell ile Azure üzerinde bu tarz işlemlere geçmeden önce var olan Azure üyeliğinize PowerShell içerisinden bağlanmanız gerekmektedir. Bu noktada iki seçeneğiniz bulunuyor.

  • Azure AD yöntemi ile ilgili credential bilgileri bir değişkene atanır ve bağlantı gerçekleştirilir.
  • Sertifika yönteminde ise Azure yönetim panelinden yönetim sertifikası kullanılarak otantikasyon gerçekleştirilir. Bu otantikasyon ancak sertifika geçerli olduğu sürece aktif olacaktır.

Azure AD yöntemi ile hızlıca Azure üyeliğimize bağlantı gerçekleştirelim. Öncelikle Get-Credential komutu ile kimlik bilgilerimi $kimlik değişkenine atıyorum.

image

Görüldüğü gibi kullanıcı adı ve secure.string şeklinde parola değişkene atanmış.

image

Ardından Add-AzureAccount komutu ile bağlantımızı gerçekleştiririz.

image

Ancak görüldüğü gibi hata aldık. Bu hatanın temel sebebi –credential parametresinin yalnızca okul veya iş hesapları ile kullanılabilmesidir. Eğer yukarıdaki gibi bir Microsoft hesabı ile Azure üyeliğinize bağlanmaya çalışırsanız hata mesajı ile karşılaşırsınız. Bunun çözümü için Azure paneli üzerinden bir organizasyon hesabı oluşturulabilir ya da sertifika bazlı yönetim yöntemi kullanılabilir.

Sertifika yönteminde yapılması gereken ilk önce üyeliğin içerisinde yer alan PublishSettings dosyasının indirilmesidir. Bunun için aşağıdaki komut kullanılır.

image

Bu komut bizi Azure kimlik doğrulama sayfasına yönlendirir. Kimlik doğrulama işleminden sonra istenilen hesap seçilir ve PublishSettings dosyası yüklenir.

image

Dosya indirildikten sonra bir sonraki adımda PowerShell konsolu içerisinde bu dosyayı import edeceğiz.

image

Ardından başarılı olduğunu test etmek için hızlıca var olan sanal makinelerimizi listeleyebiliriz.

image

Görüldüğü gibi var olan Azure sanal makinelerimi listeleyebiliyorum. Artık storage hesabı üzerinde PowerShell ile aksiyon alabiliriz.

Azure PowerShell Storage komutlarında PowerShell’in klasik fiil-isim yapısı kullanılmaya devam ediliyor. Storage yönetimi için kullanılan sık fiiler aşağıdaki gibidir.

  • Get
  • New
  • Remove
  • Set
  • Start
  • Stop

Bu fiiller ile http://msdn.microsoft.com/en-us/library/azure/dn806401.aspx adresinde bulunan komutların tamamını çalıştırabiliriz.

Öncelikle var olan storage hesaplarımızı listeleyelim.

image

İstersek yeni bir storage hesabını yine komut satırı ile oluşturabiliriz.

image

Görüldüğü gibi New-AzureStorageAccount komutuna location veya affinitygrup parametreleri tanımlayarak yeni bir depolama hesabı oluşturulabilir.

image

Bu noktada dikkat edilmesi gereken konulardan birisi depolama hesabı isminin tamamının küçük harflerden oluşması ve boşluk karakteri içermemesidir. Bu tarz bir isimlendirmede panel üzerinde bu tarz bir isim verdiğiniz aldığınız hatanın benzerini PowerShell üzerinde de alırsınız.

Oluşturulan hesabın detaylarını da yukarıdaki çıktıda görebiliyoruz. En önemli çıktılardan birisi endpointlerdir. Daha önceki makalelerde bahsettiğimiz gibi depolama hesabı içerisinde 3 farklı hizmet için (table, blob, queue””) enpoint bilgileri bize sunulmuştur.

Bu endpointler üzerinde aksiyon almak da PowerShell ile oldukça basit. Örneğin Blob ile başlangıcı yapalım.

Blob üzerinde işlem yapmak için Storage hesabı için size sunulan erişim anahtarına sahip olmanız gerekir. Bu bilgileri PowerShell ile aşağıdaki değişkenlere atayalım.

$storageAccount = “aniltest123”

$storageKey = “zPW1k7C6iAoL2sg97xeIFe2Y5noX5tVllfS4sHBhbfuOiW7d7DsCa7VxX7t6Gwxb9wyjnT+Qjg6zJtcxB3iPbg==”

Ardından bu iki değeri kullanarak yeni bir storage context oluşturulur.

$NewContext = New-AzureStorageContext  –StorageAccountName $storageAccount -StorageAccountKey $storageKey

image

Blob storage yapısında bloblarımızı barındırmak için Container yapısını kullandığımızdan daha önce bahsetmiştik. Bu sebeple bu yeni hesabımız üzerinde bir adet container oluşturmamız gerekmektedir. Bunun için de aşağıdaki komut yeterli olacaktır.

image

Bu işlemleri yaparken otantikasyon bilgimiz NewContext değişkeni içerisinde yer almaktadır. Yukarıdaki komut ile birlikte blob storage içerisinde public erişime kapalı bir adet container oluşturmuş olduk.

Artık bir blobumuz olduğuna göre bu blob içerisine kopyalama işlemini başlatabiliriz.

image

Görüldüğü gibi Set komutu ile blob içeriğini buluta upload edebildik.

image

Aslında report.csv dosyasımı text ismi ile upload ettim. Artık bana sunulan endpoint üzerinden erişim yetkilerine göre bu dosyaya erişim sağlayabiliriz.

PowerShell yetenekleri sayesinde bu işi otomatize edebilir, çoklu dosyaları upload edebilir, upload status bilgilerini görebilir, alınan hatalara göre exceptionlar belirlenebilir.

Oluşturulan bu dosyaya erişmek istediğimizde, henüz public access olmadığı için aşağıdaki hata alınacaktır.

image

Bu izin atamasını da Set-AzureStorageContainerAcl komutu ile gerçekleştirebiliriz. Bu konutun –Permission isimli bir parametresi bulunur ve aşağıdaki değerleri alabilir.

  • Container: Belirtilen container ve içerisindeki tüm bloblara full read erişimi verilir.
  • Blob: Container yerine sadece blob’a full read erişimi verilir.
  • Off: Yalnızca storage owner içeriğe erişebilir.

Biz aşağıdaki komut ile Container bazında erişim yetkisi verelim.

image

Aynı dosyaya tekrardan erişmek istediğimde dosya otomatik olarak download edilir.

image

image

Benzer aksiyonları New-AzureStorageTable ve New-AzureStorageQueue komutları ile Table ve Queue hizmetleri için de gerçekleştirebiliriz.

Örneğin çok basit bir tablo oluşturalım.

image

Bu tablonun içerisine veri girebilmek için de Storage Client Library (Microsoft.WindowsAzure.Storage.dll) kullanılabilir. Bunun için öncelikle Table içerisine satır ekleyebilecek bir fonksiyon hazırlamamız gerekiyor. Örneğin aşağıdaki fonksiyon işimizi görebilir.

image

Ardından öncelikle account ve key bilgileri aynı şekilde tanımlanır. Sonrasında ise Cloud Storage nesnesi için instancelar oluşturulur.

image

Şimdi çok basit bir döngü ile satırları fonksiyonumuzu kullanarak ekleyelim.

image

Datanın çıktısını görmek için ise aşağıdaki komut satırı işimizi görecektir.

image

Görüldüğü gibi loop ile insert edilen tüm değerler aşağıdaki çıktıda görülmüştür.

image

Bu makalede aslında PowerShell ile Azure Storage servislerini en ince ayrıntısına kadar yönetilebileceğine dair fikir vermeye çalıştık. Default komutlar yetmediği noktada Azure Storage Client Library erişimini gerçekleştirip aksiyon alabildik.

Bu şekilde Azure Storage hizmetleri üzerindeki aksiyonların tamamını PowerShell ile gerçekleştirebilir ve otomatize edebiliriz.

Read More

Azure Storage Services – Part 7:.NET ile Storage Service Kullanımı

Makale serimizin 7. bölümünde sözü Fatih Doğan’a bırakacağız. Kendisi bu ana kadar öğrendiğimiz Azure storage hizmetlerini .NET ile nasıl ayrıntılı şekilde yönetebileceğimizi anlatıyor olacak.

———————————————–

Storage üzerinde yapabileceğiniz bütün işlemlerin programlanabilir olması, düzenli olarak yapmanız gereken işleri küçük bir uygulama yazarak otomatize etmenize olanak sağlıyor. Hatta bütün bu işlemler RESTful bir API üzerinden yapıldığı için HTTP isteği gönderebilen bütün dillerden storage management yapabiliyorsunuz. Tabi HTTP headerlar ve bodylerle uğraşmak istemiyorsanız, kendi programlama dilinize ait, bu işlemleri kolayca yapabileceğiniz wrapperlar bulmak zorunda kalıyorsunuz – yazdığınız dile ait storage wrapper bulamıyorsanız, GitHub sizi ve yazacağınız wrapperı bekliyor.

Tabi konu .NET olunca ve Storage’da bir Microsoft hizmeti olunca, aradığımız wrapperın da Microsoft tarafından temin edilmesi pek şaşırtıcı olmuyor. Böyle dediğime bakmayın, Microsoft tarafından temin edilen wrapperlar arasında sadece .NET yok ; Node.js, Java, PHP, Ruby ve Python da var.
Biz ise makale gereği .NET ile, daha açık konuşmak gerekirse .NET dillerinden biri olan C# ile Storage hesabımız üzerinde yapabileceğimiz işlemleri inceleyeceğiz.

0. Ön Hazırlık

Azure hesabınıza giriş yaparak, üzerinde çalışacağınız Storage hesabınızı seçin ve “Manage Account Key” sekmesine geçiş yapın. “Storage Account Name” ve “Primary Access Key” bölümlerini ise bir yere not edin. Ayrıca NuGet’den “WindowsAzure.Storage” araması yaparak gerekli wrapperı projenize referans etmeniz gerek. Referans etmeniz gereken bir diğer assembly ise “System.Configuration”.

Tabi her şey referans eklemekle bitmiyor. Bir yere not ettiğiniz Storage Account Name ve Primary Access Key’i kullanarak app.config – ya da bir Web uygulaması yazıyorsanız web.config içerisine aşağıdaki formata uyacak şekilde gerekli eklemeleri yapıyoruz.

<connectionStrings>
  <add name="StorageConnectionString" connectionString="DefaultEndpointsProtocol=https;AccountName=StorageAccountName;AccountKey=PrimaryAccessKey" />
</connectionStrings>

Ekleme sonrası ulaşacağınız sonuç buna benzer bir tanımlama olmalı;

<connectionStrings>
  <add name="StorageConnectionString"
       connectionString="DefaultEndpointsProtocol=https;AccountName=storagexpress;AccountKey=u8ZH06jlpIv1Qvrqskb5AkC2NxpGM365CFLo3H8VQzonVZc8sPjP26yKrFYz6V8mHKdtOFu41y+UyESCxkrtiw==" />
</connectionStrings>

Projeye gerekli referansları ekledikten sonra proje içerisinde kullanılacak using statementlarını ekliyoruz.

using System.Configuration;

using Microsoft.WindowsAzure.Storage;

using Microsoft.WindowsAzure.Storage.Auth;

using Microsoft.WindowsAzure.Storage.Blob;

using Microsoft.WindowsAzure.Storage.Table;

using Microsoft.WindowsAzure.Storage.Queue;

Storage hesabına erişim sağlamak için yeni bir “CloudStorageAccount” nesnesi oluşturuyoruz.

CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString);

1. Blob Storage

Önceden oluşturduğumuz “CloudStorageAccount” yardımıyla blob storage işlemlerini yapacağımız “CloudBlobClient” nesnesini oluşturuyoruz.

CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

1.1 Container Oluşturma

Sonrasında ise Blob Storage içerisindeki işlem yapacağımız containerın referansına ihtiyacımız var. Bu referans sayesinde container üzerinde işlemler yapabileceğiz. Bu referansı almanın ise birkaç yolu var. Birincisi “CloudBlobClient” ögesine ait “ListContainers” metodu ile blob storageınız içerisindeki bütün containerların bir referansını alabilirsiniz. İkincisi ise, işlem yapmak istediğiniz containerın adını biliyorsanız ya da o isimde bir container oluşturmak istiyorsanız yine “CloudBlobClient” ögesine ait “GetContainerReference” adlı metodu kullanıyoruz;

CloudBlobContainer blobContainer = blobClient.GetContainerReference("mystorage");

if (blobContainer.Exists())
{
    blobContainer.Create();
    blobContainer.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob });
}

“SetPermissions” metodu ile containerın permission ayarlamalarını yapabilirsiniz. PublicAccess tarafında ise seçebileceğiniz üç adet seçenek var. Birincisi, örnekte de görebileceğiniz gibi “Blob”. Bu seçeneği kullanarak, container içerisindeki bloblara erişimin herkese açık olduğunu, ama containerın içeriğinin listelenemeyeceğini belirtiyorsunuz. İkincisi ise “Container” ki bu seçenek containerı herkese açık hale getiriyor. Üçüncü ve son olarak “Off” ile de sadece yetkisi olan kişilerin containerınıza erişim sağlayabileceğini belirtiyorsunuz.

1.2 Container’a Dosya Yükleme

CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference("myblob");

using (System.IO.MemoryStream stream = new System.IO.MemoryStream(new System.Net.WebClient().DownloadData(new Uri("http://www.bing.com/robots.txt"))))
    blockBlob.UploadFromStream(stream);

Yukarıdaki örnekte de görebileceğimiz gibi ilk olarak işlem yapacağımız blobun referansını elde ediyoruz. Sonrasında ise bir dosyanın içeriğini Stream olarak alıyoruz ve “UploadFromStream” metodunu kullanarak blob üzerine yükleme işlemini başlatıyoruz. Örnekte ise Bing’e ait robots.txt dosyasının içeriğini stream olarak alıyoruz ve “UploadFromStream” metodunu kullanarak yükleme işlemini başlatıyoruz.

1.3 Container İçerisindeki Blobları Listeleme

 foreach (IListBlobItem blobItem in blobContainer.ListBlobs())
 {
     if (blobItem is CloudBlockBlob)
     {
         CloudBlockBlob cloudBlockBlob = (CloudBlockBlob)blobItem;
         Console.WriteLine("CloudBlockBlob: {{ Properties.Length : {0} , Uri : {1} }}", cloudBlockBlob.Properties.Length, cloudBlockBlob.Uri);
     }
     else if (blobItem is CloudPageBlob)
     {
         CloudPageBlob cloudPageBlob = (CloudPageBlob)blobItem;
         Console.WriteLine("CloudPageBlob: {{ Properties.Length : {0} , Uri : {1} }}", cloudPageBlob.Properties.Length, cloudPageBlob.Uri);
     }
     else if (blobItem is CloudBlobDirectory)
         Console.WriteLine("CloudBlobDirectory : {{ Uri : {0} }}", blobItem.Uri);
 }

“ListBlobs” metodunu kullanarak container içerisindeki bütün blobları listeleyebiliyoruz. Yukarıdaki örnekte ise gelebilecek blobları tiplerine göre ayırıyoruz ve ona göre çıktı sağlıyoruz.

1.4 Container İçerisindeki Bir Blobu İndirme

 blockBlob.DownloadToFile("<Dosya Yolu>", FileMode.OpenOrCreate);

Örnekte de görebileceğiniz gibi, “CloudBlockBlob” ögesinin “DownloadToFile” metodu ile blobunuzu indirebilirsiniz. Onun dışında, öge içerisindeki “DownloadTo” ile başlayan metodlarla, bloblarınızı farklı şekillerde de indirebilirsiniz.

1.5 Bir Blobu Silme

 blockBlob.DeleteIfExist();

“CloudBlockBlob” içerisindeki “Delete” metodu ile referansını aldığınız blobu silebilirsiniz. “DeleteIfExists” metodunu da kullanabilirsiniz. Arasındaki fark ise, blobun hali hazırda var olup olmadığını kontrol ederek işlem yapmasıdır. Eğer blobu bulabilirse siler.

2. Table Storage

 CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

Blob Storage örneğinde olduğu gibi, “CloudStorageAccount” ögesini kullanarak bir “CloudTableClient” oluşturuyoruz.

2.1 Tablo Oluşturma

CloudTable table = tableClient.GetTableReference("users");

table.CreateIfNotExists();

Table client oluşturulduktan sonra işlem yapmak istediğimiz tablonun referansını alıyoruz. Bu örnekte “users” adlı bir tablo ile işlem yapacağız. Tablonun var olup olmadığıyla ilgili bir bilginiz yoksa eğer “CreateIfNotExists” adlı metodu kullanabilirsiniz. Bu metod, eğer tablo yoksa oluşturacaktır.

2.2 Insert işlemleri

Insert işlemlerinden bahsetmeden önce, neleri insert edebileceğimizden bahsedelim. İlk önce nasıl bir yapı kullanılması gerektiğini örnekle gösterdikten sonra üzerinde açıklama yapacağız ;

public class UserEntity : TableEntity

{

public UserEntity() { }

public UserEntity(string name, string surname)

{

PartitionKey = name;

RowKey = surname;

}

public string Email { get; set; }

}

Burada bir kaç şey dikkatimizi çekiyor. Birincisi “TableEntity” sınıfından alınan kalıtım. Bunun nedeni ise, table storage altyapısı gereği, ögelerinizin bir kurala uyması gerektiği. TableEntity kalıtımı ile birlikte sınıfınıza “RowKey” ve “PartitionKey” adlı elemanlar ekleniyor. Bu ögeler sayesinde tablonuzdaki bütün girdilerin benzersiz (a.k.a. unique) olması sağlanıyor.

Sonrasında ise ögemizi oluşturuyoruz ve insert işlemini gerçekleştiriyoruz ;

 UserEntity user = new UserEntity("Jack", "Sparrow")
 {
     Email = "jack.sparrow@outlook.com"
 };

 TableOperation insertOperation = TableOperation.Insert(user);

 table.Execute(insertOperation);

Insert,Update,Delete ve Merge işlemlerini yapmak için “TableOperation” oluşturmak gerekiyor. TableOperation ögesinin içerisinde bu işlemler için tanımlanmış statik metodlar mevcut.

TableOperation ögesi oluşturulduktan sonra, bu işlemin tabloda çalıştırılması için “CloudTable” ögesinin “Execute” metodunu çağırmamız gerekiyor.

2.3 Batch Insert İşlemleri

TableBatchOperation batchOperation = new TableBatchOperation();

UserEntity user1 = new UserEntity(“John”, “Coss”)

{

Email = “john.coss@outlook.com”

};

UserEntity user2 = new UserEntity(“John”, “Bell”)

{

Email = “john.bell@outlook.com”

};

batchOperation.Insert(user1);

batchOperation.Insert(user2);

table.ExecuteBatch(batchOperation);

Birden fazla işlem yapacaksanız, her bir işlemin sunucuya gidip gelmesini beklemektense, yapacağınız bütün işlemlerin tek bir gidişte gönderilmesini isteyebilirsiniz. Bu işlemler bir “yığın” halinde gönderildiği için ise “Batch” adı veriliyor.

Öncelikle bir “TableBatchOperation” oluşturuyoruz. Batch olarak göndermek istediğiniz bütün işlemleri bu öge üzerinde tanımlayacağız. Bu örnekte ise iki adet “UserEntity” ögesi oluşturduk “TableBatchOperation” ögesine insert işlemlerini gerçekleştirdik. Sonrasında ise “CloudTable” ögesinin “ExecuteBatch” metoduna, hazırladığımız “TableBatchOperation” ögesini parametre olarak gönderiyoruz. Yalnız atlamamanız gereken bir ayrıntı var ; Batch işlem yapmak istiyorsanız, batch içerisinde kullanacağınız ögelerin PartitionKeyleri aynı olmalı. Bu yüzden örnek içerisinde kullanılan iki UserEntitysinde kullanılan isim “John” olarak tanımlı.

2.4 Query Oluşturma

 TableQuery<UserEntity> query = new TableQuery<UserEntity>()
                                    .Where(
                                        TableQuery.GenerateFilterCondition(
                                            propertyName: "PartitionKey",
                                            operation: QueryComparisons.Equal,
                                            givenValue: "John"
                                        )
                                    );

 foreach (UserEntity item in table.ExecuteQuery(query))
 {
     Console.WriteLine("UserEntity : {");
     Console.WriteLine("    PartitionKey : {0}", item.PartitionKey);
     Console.WriteLine("    RowKey : {0}", item.RowKey);
     Console.WriteLine("    Email : {0}", item.Email);
     Console.WriteLine("}");
 }

Tablonuza sorgu çekmek, Table storageda biraz farklı. Sanırım sınıf içerisindeki metodların, Linq ile birlikte gelen extension metodlar ile karışmasını istemediklerinden dolayı böyle bir yola başvurmuşlar. Yukarıdaki karışıklığı biraz açmak gerekirse ; Öncelikle bir “TableQuery” oluşturuyoruz. Bu sınıf generic bir sınıf olduğundan dolayı işlem yapmak istediğimiz entitynin tipini verebiliyoruz. Sonrasında ise içerisine string olarak bir parametre alan “Where” metodumuz var. El ile sorgu yazma alışkanlığımız olmadığından dolayı (!) sorgu oluşturmak için sınıf içerisinde birkaç static metod tanımlı. “GenerateFilterCondition” metodu içerisine, sorgulanacak propertynin adı (propertyName), eşitliği belirleyecek operasyon (queryOperation) ve karşılaştırılacak değeri (givenValue) parametre olarak alıyor. “QueryComparisons” adlı sınıf içerisinde ise eşitliği belirleyebilecek operasyonlar tanımlı. Biz ise bu örnekte “Equal” ögesini kullanıyoruz. Böylece “PartitionKey”lerin “John”a “eşit” olduğu entityleri çekebiliyoruz.

2.5 Sadece Bir Girdiyi Getirme

 TableOperation retrieve = TableOperation.Retrieve<UserEntity>("John", "Bell");
 TableResult tableResult = table.Execute(retrieve);
 UserEntity retrievedUser = (UserEntity)tableResult.Result;

“TableOperation” sınıfı içerisindeki “Retrieve” metoduna, parametre olarak “PartitionKey” ve “RowKey” göndererek tekil girdileri getirebilirsiniz. Hazırlanan sorguyu “Execute” ettiğinizde gelecek “Result” ise sorgunuzun sonunda dönen sonuç olacağından, sonucu cast ederek girdiye ulaşabilirsiniz.

2.6 Bir Girdiyi Update Etme

 retrievedUser.Email = "johnBell@outlook.com";
 TableOperation replaceOperation = TableOperation.Replace(retrievedUser);
 table.Execute(replaceOperation);

Örnek olması için bir önceki başlıkta getirdiğim ögenin “Email” özelliğine başka bir değer atıyorum. Sonrasında ise “TableOperation” sınıfı içerisindeki “Replace” metoduna, update edilmesini istediğimiz entityi parametre olarak yolluyoruz. Sonrasında ise hazırladığımız “TableOperation” ögesini “Execute” ediyoruz.

2.7 Girdiyi Update ya da Insert Etme

retrievedUser.Email = "john.bell@outlook.com";
TableOperation replaceOrInsertOperation = TableOperation.InsertOrReplace(retrievedUser);
table.Execute(replaceOrInsertOperation);

Bazen elinizdeki ögenin tablonuzda olup olmadığını bilemiyorsunuz. Update işlemi yapmaya çalışırsanız ve tabloda öyle bir öge yoksa hata alırsınız. Insert etmeye çalışırsanız, tabloda aynı PartitionKey ve RowKeye sahip bir öge varsa hata alırsınız. İşte o yüzden, emin olmadığınız durumlarda “InsertOrReplace” metodunu kullanarak “TableOperation” oluşturabilirsiniz. Sonrasında ise yine aynı şekilde, oluşturulan “TableOperation” ögesi “Execute” ediliyor.

2.8 Dynamic Sorgu (Projection)

Sorgu çekmeye çalıştığınız tablonun yapısını bilmiyorsanız, ya da elinizde bu tabloya ait bir entity sınıfı yoksa, bu sorgu türünü kullanabilirsiniz. Nasıl kullanıldığını bir örnek ile açıklayalım ;

TableQuery<DynamicTableEntity> projectionQuery = new TableQuery<DynamicTableEntity>().Select(new[] { "Email" });
EntityResolver<string> resolver = (pk, rk, ts, prop, etag) => prop.Keys.Contains("Email") ? prop["Email"].StringValue : null;

foreach (string email in table.ExecuteQuery(projectionQuery, resolver))
    Console.WriteLine(email);

Öncelikle önceki örneklerde oluşturduğumuz gibi bir “TableQuery” oluşturuyoruz. Yalnız bu sefer entity tipi olarak “DynamicTableEntity” kullanıyoruz. “Select” metodu ile de getirmek istediğiniz kolonları belirtiyoruz. Bu örnekte ise “EMail” kolonunu çekiyoruz.

Sonrasında ise “EntityResolver” sınıfını kullanarak, sorgu sırasında getirilecek sonuçların bize göre anlamlandırılmasını sağlıyoruz. Generic bir sınıf olduğundan dolayı, getirmek istediğimiz değerin tipini veriyoruz. Bu örneğe göre, “Email” özelliğini “string” değer olarak tanımladığımızdan, tipini “string” olarak belirliyoruz. Eğer birden fazla kolon belirttiyseniz bu tipe dynamic ya da belirttiğiniz ögeleri bulunduran bir sınıfın tipini verebilirsiniz.

“ExecuteQuery” metoduna, hazırlanan sorguyu ve sorgudan geriye dönecek sonuçları resolve edecek “EntityResolver” ögesini parametre olarak gönderiyoruz.

2.9 Girdi Silme

TableOperation deleteOperation = TableOperation.Delete(retrievedUser);
table.Execute(deleteOperation);

Silmek istediğiniz ögeyi, “TableOperation” sınıfının “Delete” metoduna parametre olarak göndererek, geriye dönen “TableOpration” ögesini “Execute” edin.

2.10 Tablo Silme

table.DeleteIfExists();

“CloudTable” ögesinin “DeleteIfExists” metodu ile, aldığınız tablo referansına ait bir tablo var ise silebilirsiniz.

3. Queue Storage

Table ve Blob Storage başlıklarında da yaptığımız gibi, Queue işlemleri yapmak istiyorsak bir client oluşturmamız gerekiyor.

CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();

3.1 Queue Oluşturma

Bir queue ile işlem yapmak istiyorsanız, işlem yapmak istediğiniz queuenin referansını almanız gerekiyor. Sonrasında ise bu referansa ait bir queue yoksa oluşturabilirsiniz.

CloudQueue queue = queueClient.GetQueueReference("myqueue");

queue.CreateIfNotExists();

Bu örnekte ise “myqueue” adlı bir queuenin referansını alıyoruz. Aldığımız referans sonrasında, eğer bu isimde bir queue yoksa oluşturulması için “CreateIfNotExists” metodunu çağırıyoruz.

3.2 Queueya Mesaj Ekleme

 for (int i = 0; i < 5; i++)
 {
     CloudQueueMessage message = new CloudQueueMessage("Merhaba Dünya !!!");
     queue.AddMessage(message);
 }

Yukarıdaki örnekte 5 adet mesaj oluşturuyoruz ve bunları queueya ekliyoruz. Queueya eklemek için kullanılacak mesajı “CloudQueueMessage” sınıfını kullanarak tanımlıyoruz. Sonrasında ise “CloudQueue” ögesinin “AddMessage” metodunu kullanarak mesajımızı gönderiyoruz.

3.3 Queueya Göz Atma

Queuedaki bir mesajı queuedan silmeden getirmek için Peek özelliğini kullanabilirsiniz.

CloudQueueMessage peekedMessage = queue.PeekMessage();
Console.WriteLine(peekedMessage.AsString);

“CloudQueue” ögesinin “PeekMessage” metodu ile mesajı getirebilirsiniz. Örnekte ise aldığımız mesajı konsolda yazdırıyoruz.

3.4 Queueya Eklenen Mesajı Düzenleme

CloudQueueMessage updatedMessage = queue.GetMessage();
updatedMessage.SetMessageContent("Hello World !!!");
queue.UpdateMessage(updatedMessage, TimeSpan.FromSeconds(0), MessageUpdateFields.Content | MessageUpdateFields.Visibility);

İlk olarak mesajı “GetMessage” metodu ile çekiyoruz. Sonrasında ise, “CloudQueueMessage” ögesinin “SetMessageContent” metodunu kullanarak içerik değişikliğini yapıyoruz. İçerik değişikliğini yaptıktan sonra ise, “CloudQueue” ögesinin “UpdateMessage” metodunu kullanarak mesajı güncelliyoruz. Bu metod ise içerisine sırasıyla, güncellenecek mesaj, bu değişiklik etkili olana kadar geçecek süre ( ki bu örneğe göre değişikliğin hemen yapılması gerektiğini söylüyoruz ) ve son olarak mesajın güncellenen bölümlerini belirtiyoruz (örneğe göre mesajın içeriğinde ve görünürlüğünde değişiklik yapıldığı için “Content” ve “Visibility” ögelerini yolluyoruz).

3.5 Queuedan Mesajı Silme

 CloudQueueMessage deletedMessage = queue.GetMessage();
 queue.DeleteMessage(deletedMessage);

“CloudQueue” sınıfı içerisindeki “DeleteMessage” metodu ile mesajları silebilirsiniz.

3.6 Queuedaki Mesaj Sayısını Getirme

 queue.FetchAttributes();

 Console.WriteLine("{0} adet mesaj var.", queue.ApproximateMessageCount);

En güncel mesaj sayısını almak istiyorsanız, öncelikle “CloudQueue” ögesinin “FetchAttributes” metodunu kullanarak, queuenizin güncel bilgileri almasını sağlamanız gerekiyor. Sonrasında ise “CloudQueue” ögesinin “ApproximateMessageCount” özelliği, size asıl mesaj sayısına yakın bir sayı getirecektir. “FetchAttributes” metodu çağırıldıktan sonra queue üzerinde yapılabilecek mesaj ekleme ya da kaldırma işlemleri, bu propertyi güncel olmaktan çıkaracaktır. Bundan dolayı property “ApproximateMessageCount” olarak adlandırılmıştır.

3.7 Queuedaki Mesajları Getirme

 Console.WriteLine("Mesajlar : {");
 foreach (CloudQueueMessage item in queue.GetMessages(5, TimeSpan.FromMinutes(5)))
 {
     Console.WriteLine("    {0}", item.AsString);
 }
 Console.WriteLine("}");

Birden fazla mesajı getirmek isterseniz “CloudQueue” ögesinin “GetMessages” metodunu kullanabilirsiniz. Örnekte “GetMessages” metoduna iki adet parametre gönderilmiş. Bu parametreler sırasıyla, getirilmek istenen mesaj sayısı ve bu mesajların ne kadar bir süre sonra queuedan silineceğini gösteriyor. Yani örneğe göre beş adet mesaj çağırılıyor ve bu mesajlar 5 dakika sonra silinecek.

3.7 Queueyu Silme

queue.DeleteIfExists();

“CloudQueue” ögesinin “DeleteIfExists” metodunu kullanarak, eğer referansını aldığınız queue var ise silebilirsiniz.

Bu makalede Blob, Table ve Queue Storage üzerinde, C# kullanarak yapabileceğimiz işlemleri inceledik. Tabi kütüphaneyi de ayrıca incelemenizi tavsiye ederim. Örneklerde kullandığımız kodlara aşağıdaki linkten ulaşabilirsiniz.

http://1drv.ms/14q1jOE

Read More

Azure Storage Services – Part 6:Redundancy

Makale serimizin önceki bölümlerinde farklı Azure storage opsiyonlarını ve ölçeklenebilirlik limitlerini inceledik. Yazıların bir kısmında ise storage hizmetinin ve dolayısı ile içerisindeki farklı veri tiplerinin (blob, entity, mesaj) yedeklilikleri için bu makalemizi referans gösterdik.

Azure tarafındaki redundancy opsiyonlarını incelemeden önce bir önceki makalede yaptığımız gibi Redundancy terimini inceleyelim.

http://en.wikipedia.org/wiki/Redundancy

Mühendislikte de sıklıkla kullanılan Redundancy aslında kritik bir sistem içerisindeki kritik bileşenlerin birden fazla şekilde yapılandırılması ile bir yedeklilik yada koruma yöntemi oluşturulmasıdır. Sistemin kritiklik seviyesi yükseldikçe tutulan koruma/yedek sayısı da artacaktır. Örneğin uçaklarda bulunan bazı kritik bileşenlerin herhangi bir sorun oluştuğunda devreye girmesi için 2 farklı ek kopyası daha bulunur.

Bilişim teknolojilerinde de redundancy terimini sıklıkla kullanırız. Özellikle veri tabanı sistemlerinde kritik verinin iki yada daha fazla tabloda daha tutulması ile bu verinin yedekliliği sağlanmış olur.

Makale serisinin başından beri sürekli savunduğumuz arguman Azure’un en kritik uygulamalarınızı bile barındırabilecek teknolojiye sahip olduğu ve ihtiyaçlarınızı karşılayabildiğidir. Uygulama içerisinde en önemli bileşen olan verinin Azure içerisindeki güvenliği aslında bu argumanın en önemli noktası. Bu sebeple Microsoft Azure storage hizmetleri içerisinde hizmet bağımsız barındırılan verilerin tamamı yüksek erişilebilirlik ve yedeklilik sağlanması amacı ile koruma altına alınmıştır.

Bu makale bu korumanın detaylarını inceliyor olacağız.

Öncesinde Azure tarafından sunulan SLA taahhütlerini incelemekte fayda var.

http://azure.microsoft.com/en-us/support/legal/sla/

Görüldüğü gibi Storage bölümünde aşağıdaki ibareler mevcut.

  • We guarantee that at least 99.99% of the time, we will successfully process requests to read data from Read Access-Geo Redundant Storage (RA-GRS) Accounts, provided that failed attempts to read data from the primary region are retried on the secondary region.
  • We guarantee that at least 99.9% of the time, we will successfully process requests to read data from Locally Redundant Storage (LRS), Zone Redundant Storage (ZRS), and Geo Redundant Storage (GRS) Accounts.
  • We guarantee that at least 99.9% of the time, we will successfully process requests to write data to Locally Redundant Storage (LRS), Zone Redundant Storage (ZRS), and Geo Redundant Storage (GRS) Accounts and Read Access-Geo Redundant Storage (RA-GRS) Accounts.

Azure Storage hizmetlerinde redundancy sağlanabilmesi için farklı replikasyon yöntemleri kullanıma sunulmuştur. Bu makalemizde sunulan replikasyon çeşitlerini detaylı şekilde inceliyor olacağız.

Locally Redundant Storage (LRS)

LRS replikasyon yönteminin size sağladığı temel fayda storage hesabınız içerisinde tutulan verinin 3 farklı kopyasının aynı bölgedeki veri merkezinde tutulmasıdır. Yani hesabınızı oluşturduğunuz bölgeye göre oluşturulan tüm verilerin 3 farklı kopyası yine aynı meri merkezi içerisinde tutulacaktır.

Diğer replikasyon yöntemleri ile karşılaştırıldığında daha ekonomik bir çözüm olan LRS’sin en büyük handikapı bölgesel yada veri merkezi seviyesinde oluşabilecek problemlere karşı dayanıklı olmamasıdır. Verilerinizin bulunduğu donanım üzerinde gerçekleşen bir problemde diğer kopyalardan uygulamanız çalışmaya devam edebilir ancak veri merkezinin tamamını etkileyen bir kesinti durumunda sizin de verilerinize erişiminiz kesintiye uğrayacaktır.

LRS tanımı depolama hesabı oluşturma aşamasında belirlenir.

image

Geo-Redundant Storage (GRS)

GRS’in LRS’den en büyük farklı tutulan ek kopyaların aynı veri merkezinde değil farklı bir veri merkezinde barındırılmasıdır. Bu da otomatik olarak size bölgesel yada kıtasal oluşacak problemlerde dahi koruma sağlayacaktır.

Bu sebeple kritik uygulamaların verilerinin GRS ile korunması şiddetle önerilir. GRS ile korunan bir depolama hesabında yazılan veriler öncelikle Primary olarak seçilen veri merkezine gönderilir ve 3 farklı kopyası yine bu veri merkezinde farklı donanımlarda tutulur. Ardından ise bu veri ikinci bir veri merkezine gönderilir ve burada da 3 farklı kopyası ayrı donanımlarda tutulur. Böylece GRS ile verinizin 6 farklı kopyasını dünya üzerindeki farklı veri merkezlerinde tutmuş olursunuz.

GRS replikasyonunun seçilmesi aynı şekilde depolama hesabı oluşturulması esnasında gerçekleştirilir.

image

Yukarıdaki ekranda seçilen bölge (West Europa) birincil veri merkezi olarak yapılandırılır ve gönderilen tüm veriler ilk önce bu veri merkezindeki 3 kopyada saklanır. Ardından ise aşağıdaki tabloya göre otomatik olarak ikinci veri merkezi belirlenir ve asenkron kopyalama başlatılır.

image

Herhangi bir failover durumunda failover seviyesinin Stamp olduğunu unutmamak gerekiyor. Yani disaster durumunda tek bir storage hesabının taşınması yerine Stamp içerisinde tüm storage hesapları ikincil veri merkezlerine taşınacaktır. Herhangi bir failover durumunda ilgili tüm Azure Storage müşterilerine bir notifikasyon iletilir. Ardından müşterilerin account.-servisismi-.core.windows.net ismindeki DNS girdileri primary veri merkezindeki secondary veri merkezine yönlendirilmesi gerekmektedir.

Bu yönlendirme ile birlikte var olan Blob, Table ve Queue URI’leri tekrardan aktif olarak çalışmaya başlayacaktır. Böylece URI değişikliğini uygulama seviyesinde yapmanıza gerek kalmadan aynı URI ler ile ikincil veri merkezinden hizmet vermeye devam edeceksiniz.

Dikkat edilmesi gereken bir diğer nokta da aradaki replikasyonun asenkron olmasıdır. Bu da verilerin öncelikle primary veri merkezinde sonrasında ise ikinci veri merkezine bir süre sonra  yazılması manasına gelmesidir. Bu sebeple bir disaster anında ikincil veri merkezindeki verilerin son güncellemeleri alamamış olması beklenebilir. Bu tarz disaster senaryolarında RTO (Recovery Time Objective) değerleri önemlidir. Azure RTO ile ilgili bize herhangi bir SLA sunmamasına rağmen 15 dakikadan daha az şeklinde bir değer belirtir. Yani en fazla 15 dakikalık yazılan verilerinizi kaybedebilirsiniz şeklinde anlayabiliriz.

Diğer kritik değer de RTO (Recovery Time Objective) ‘dir. Bu da ne kadar sürede failover işleminin gerçekleştirileceğini belirtir. Azure bu noktada bize bir süre vermez çünkü bu sürenin var olan problemin keşfedilmesi, recover yapılmasına karar verilmesi ve DNS kayıtlarının değiştirilmesi gibi değişkenlere bağlı olduğunu savunur. Microsoft tarafındaki ilk aksiyon primary veri merkezinde tekrardan erişimin açılmasıdır. Ancak problemin devam edeceği ön görüldüğünde ikinci veri merkezi devreye alınır.

Read-Access Geo-Redundant Storage (RA-GRS)

RA-GRS ise GRS ile gerçekleştirilen ikinci veri merkezi replikasyonuna ek olarak ayrıca ikinci veri merkezindeki veriye read-only erişim izni verir. Böylece uygulamalar birincil veri merkezinde çıkan bir sorun sonrasında ikinci veri merkezinden veri okuma işlemini hızlıca gerçekleştirebilir.

Bu replikasyon modelini seçtiğinizde GRS’e ek olarak size ikinci bir erişim URI’si sunulur. Primary veri merkezi erişimi için hesap.blob.core.windows.net adresinden erişim sağlanırken, RA-GRS aktif edildiğinde ayrıca hesap-secondary.blob.core.windows.net URI’sine sahip olursunuz.

Azure tarafındaki failover aksiyonunu beklemeden primary URI üzerinde erişim sağlanamadığı anda uygulamalarınızın ikinci URI’den verileri okumasını sağlayabilirsiniz.

Bu replikasyon modeli aynı şekilde hesap oluşturulurken seçilebilir.

image

Zone-Redundant Storage (ZRS)

Son replikasyon/redundancy modeli ise ZRS’dir. Yalnızca block bloblar için kullanılabilir olan bu replikasyon modelinde LRS ile GRS arası bir opsiyon sunulur.

LRS’den farkı iki yada üç farklı kopyayı aynı bölge içerisindeki farklı veri merkezlerinde tutabilmesidir. Bölge aynı kalmak şartı ile birbirinden farklı lokasyonlardaki veri merkezlerinde bu kopyalar tutulabilir. Özetle tam olarak veri merkezi seviyesinde gerçekleşecek problemlerin önüne geçmek için hizmete sunulan bir özelliktir.

Yapılandırma için benzer adımlar izlenebilir.

image

Görüldüğü gibi Azure Storage hizmetleri ile birlikte farklı replikasyon/redundancy çözümleri sunulmaktadır. Fiyat detayları ile birlikte uygulamalarınızın kullandığı verilerin kritikliğini göz önüne alarak seçimi gerçekleştirmelisiniz.

Yukarıda gördüğümüz gibi temel sıralama

RA-GRS > GRS > ZRS > LRS şeklindedir.

Oluşturulan depolama hesaplarını replikasyon modelleri panel üzerinden değiştirilebilir.

image

Şimdilik ZRS replikasyon modeli ile oluşturulan storage hesaplarının farklı replikasyon modellerine değiştirilmesi desteklenmemektedir.

Read More

Azure Storage Services – Part 5:Scalability

Makale serimizin bu bölümünde Azure Storage hizmetlerinin ölçeklenebilirlik limitlerini inceliyor olacağız. İsterseniz öncesinde Scability (Ölçeklenebilirlik) ne anlama geliyor buna biraz bakalım.

http://en.wikipedia.org/wiki/Scalability linkinde görebileceğimiz gibi Scability aslında her sistemin (bu bir process yada uygulama da olabilir) artan iş yükünü karşılayabilecek şekilde yukarı veya aşağı esnekliğini nitelendirir.

Örneğin yatay büyüme (Scale-Out) bu sisteme üye ekleyerek artan talepleri karşılamayı sağlar. 2 web sunucunuz varken artan kullanıcı sorguları sebebi ile bu sayıyı 4’e çıkarak scale-out yapmış olursunuz.

Ya da dikey büyüme (Scale-Up) bu sistemdeki bir üyeye ek kaynaklar ekleyerek talepleri karşılamayı sağlar. Örneğin var olan sunucu üzerindeki CPU kaynağını yada hafızayı arttırmak aslında dikey bir ölçeklendirme yapmak anlamına gelir.

Yukarıdaki Wikipedia makalesini inceleyenler “Performans tuning versus hardware scalability” bölümünde paralel çalışan sistemlerin performansa etkisinin %70’e kadar çıkabildiğini gösteren Amdahl yasasını fark etmişlerdir.

\frac{1}{\alpha+\frac{1-\alpha}{P}}

Bu formüle göre aynı algoritmik işlem için 4 çekirdek kullanırsak elde edeceğimiz değer 2.105

\frac{1}{0.3+\frac{1-0.3}{4}} = 2.105

Eğer çekirdek sayısını 8’e çıkarırsak

\frac{1}{0.3+\frac{1-0.3}{8}} = 2.581

Görüldüğü gibi çekirdek sayısı iki katına çıktığında hız yaklaşık 5’te 1 oranında arttı. Bu yüzdendaha fazla donanım her zaman uygun yaklaşım olmayabilir.

Microsoft dünyasında da bir sistemin ölçeklenebilirliğini benzer metricler ile anlayabiliriz. Bu yazımızda ise Azure Storage Services için Scabilitiy detaylarına bakıyor olacağız.

İkinci makalemizde belirttiğimiz gibi Storage hizmetlerinden faydalanabilmek için ilk aksiyonumuz bir storage hesabı oluşturmaktı. Bu noktada Microsoft size iki seçenek sunuyordu:

  • Premium Storage
  • Standard Storage

Premium Storage yeni duyurulan bir hizmeti ve HDD yerine SSD diskler sayesinde sanal makineler ile yüksek performans elde edilmesini sağlıyordu. Özellikle I/O duyarlı yükler için tercih edilebilir bir seçenek olarak karşımıza çıkıyordu.

Farklı coğrafi lokasyonlarda değişmekle birlikte örneğin Avrupa ve Asya bölgeleri için Standard Storage Account ölçek limitleri aşağıdaki gibidir:

image

Özetle:

  • Her bir Storage Account kapasitesi içerisinde tüm servisler ile birlikte (blob, table, queue) 500TB’dır. Bu limitin üzerine çıkılması için ikinci bir Storage Account oluşturulması gereklidir.
  • 1KB’lık nesne boyutları ile saniyede toplam 20.000 Entity yada mesaj işlenebilir. Entity ve mesaj detaylarını önceki yazılarımızda incelemiştik.
  • Geo-Redundant ve Locally Redundant replikasyon modelleri için (detayları bir sonraki yazımızda inceliyor olacağız) farklı bant genişliği limitleri bulunmaktadır. Inbound (Storage Account’a gönderilen veriler) Geo-redundant için 5 Gigabit/s Locally-Redundant için 10 Gigabit / s limitleri bulunur. Outbound için ise (Storage Account’dan alınan veri) Geo-redundant için 10 Gigabit/s Locally-Redundant için 15 Gigabit / s limitleri bulunur.

Premium Storage Account için de limitler bulunuyor.

image

Özetle:

  • Premium Storage içerisinde barındırılan VM disklerinin kapasitesi maksimum 32 TB olabilir.
  • Snapshot için kapasite 10TB’dır.
  • Inbound ve Outbound için toplam 50 Gigabits/s limit bulunur.

Görüldüğü gibi Premium hesap ile birlikte yüksek performans dışında daha yüksek ölçeklenebilirlik seviyeleri de sunulmaktadır.

Bildiğimiz gibi Storage Account oluşturulduğunda Blob, Table ve Queue şeklinde 3 farklı hizmete sahip oluruz. Storage hesabı oluştururken seçtiğimiz lokasyon içerisinde (bu lokasyonunda seçimi uygulama performansınız için önem taşır, uygulamanızın yer aldığı lokasyona yakın yada aynı lokasyonda storage account oluşturmanız daha efektif olacaktır) tek bir namespace altında bu 3 hizmet için URI adresleri bize sunulur.

Bu 3 hizmet içerisinde de bloblarımızı, entitylerimizi yada mesajlarımızı barındırabiliriz. Bu noktada en önemli konulardan birisi her bir nesnenin aynı zamanda bir partition anahtarına sahip olduğudur. Bu sayede bu nesnelere erişim sağlanabilir, farklı sunucular üzerinde barındırılmasına rağmen load balancing aksiyonları alınabilir. Bu 3 farklı hizmet için kullanılan partition key detayları aşağıdaki gibidir:

  • Blob = ContainerName + BlobName
  • Entity = TableName + PartitionKey
  • Message = QueueName

Partition anahtarı sayesinde aynı anahtara sahip tüm nesneler aynı grup altında toplanır ve aynı partition içerisinden erişim sağlanır. Aynı zamanda bu partition da bir partition sunucusu üzerinde barındırılır.

Storage hizmetinin bu yapısından dolayı tek bir partition için sahip olduğumuz limitleri bilmemiz uygulama dizaynı sırasında çok önemli oluyor.

Single Queue = Queue içerisinde tüm mesajlar tek bir queue partition tarafından erişilir. Bu partitionda saniyede toplam 2000 mesajı işleyebilir.

Single Table Partition = Table partition aslında aynı partition anahtarına sahip tüm entitylerdir. Bu table partition için throughput limitleri aşağıdaki gibidir:

  • 2000 Entity / Second

Bu limitin partition için olduğunu unutmamak gerekiyor. Table’ın kendisi 20000 entity işleyebilir.

Single Blob = Her bir single blob için 60 MBytes / s limit bulunmaktadır.

Peki yukarıdaki limitlere ulaşıldığında uygulamaya erişen kullanıcılar nasıl bir mesaj ile karşılaşacaklar? Aşağıdakine oldukça benzer:

serviceunavailable

Peki uygulamanız Azure Storage tarafındaki ölçek sınırlarına ulaştığında neler yapılması gerekiyor? Aşağıdaki adımlar izlenebilir:

  • İlk önce bu yoğun kullanıma ve limitlerin aşımına sebep olan yükün analiz edilmesi gereklidir. Tasarımda değişikliğe gidilerek daha az bant genişliği yada kaynak kullanımı sağlanabilir mi kontrol edilmelidir.
  • Verilen tasarım kararına göre aynı zamanda ikinci bir storage account kullanımı düşünülebilir. Aynı Azure Subscription içinde birden fazla storage account oluşturulabilirsiniz. Uygulamanızı da verileri bu iki storage account üzerinde tutacak şekilde tasarlamanız gerekmektedir.
  • Bant genişliği ile ilgili bir limite takılırsanız istemci tarafındaki verinin sıkıştırılması gibi bir yöntemi düşünebilirsiniz.
  • Retry stratejisi belirleyebilirsiniz.

Son madde önemli noktalardan birisi. Uygulamanız Azure storage üzerinde aksiyon alırken Busy yada Timeout mesajları sebebi ile herhangi bir data kaybı, data yazamama problemi yaşamaması gerekir. Bu sebeple SERVER BUSY, TIMEOUT gibi hata mesajları için bir retry stratejisi belirlenebilir.

SERVER BUSY, TIMOUT gibi mesajlarla Azure içerisindeki tümleşik load balancing yapısı gereği de karşılaşabilirsiniz. Örneğin sizin nesnelerinize erişimin arttığı noktalarda Azure kendi içerisinde partitionları farklı bir node’a otomatik olarak taşıyacaktır. Bu anlarda yukarıda bahsettiğim mesajların alınması normaldir. Bunun için aşağıdaki retry stratejilerinden birini kullanabilirsiniz:

  • No Retry
  • Fixed Backoff
  • Exponential Backoff

Bu caching detayları için sözü Fatih’e bırakalım.

“Bazen her şey planlandığı gibi gitmiyor ve “normalde” çalışan bağlantı isteğiniz, bir anda sizi geri dönüşü olmayan bir hataya itebiliyor.
Bu tür hataları almamak için, uygulamanızın bu koşullarda ne yapacağını bilmesi gerekiyor. Yani uygulamanızın bir retry stratejisine sahip olması gerek.

Genellikle kullanılan retry stratejilerinden üç tanesini şöyle sıralayabiliriz ;

1. No Retry

Hazırladığınız ve işlem için gönderdiğiniz verinin, diğer uca ulaşıp ulaşmadığı sizin için hiç önemli değilse bu stratejiyi kullanabilirsiniz.
Çünkü bu strateji ile, yaptığınız işlemin başarısız olduğu durumlarda uygulamanızın hata almasını engelleyebilirsiniz fakat işlemin tekrarı gibi bir şey söz konusu olmaz.

2. Fixed Backoff

Bu strateji ile birlikte uygulamanızın, ne kadar süre aralıkla, en fazla kaç defa tekrar bağlantı kurmayı deneyeceğini belirleyebilirsiniz.
Örneğin ; 30 saniye aralıklarla, en fazla 5 defa bağlantı kurmayı dene gibi bir yaklaşımda bulunabilirsiniz.
Bu stratejinin de dezavantajı var tabi. Bağlantı kurmaya çalışan birden fazla iş parçacığınız varsa, hepsinin aynı anda bağlantı kurmaya çalışabileceğini göz önünde bulundurmanız gerekiyor.
Bu da bizi üçüncü retry stratejisine yönlendiriyor.

3. Exponential Backoff

Bu strateji, başarısızlıkla sonuçlanan her bağlantı sonrasında bekleme süresini biraz daha arttırarak, hem diğer iş parçacıkları ile çakışma sorununu ortadan kaldırıyor
hem de sürekli olarak aynı aralıkla bağlantı kurmaya çalışmadığımızdan dolayı, kurmaya çalıştığımız bağlantının başarı oranını arttırıyor.
Bekleme süresinin belirlenmesi aşamasında kullanılabilecek formül için bir kaç tanımlama yapacak olursak ;

TDefaultBackoff = Normal bekleme süresi
TMaxBackoff = Beklenebilecek en yüksek süre
TMinBackoff = Beklenebilecek en düşük süre
TRetries = Deneme sayısı
TBackoff = Beklenecek süre

Yukarıdaki tanımlamalara göre formülümüzü bu şekilde tanımlayabiliriz ;

TBackoff = Random(0.8 * TDefaultBackoff, 1.2 * TDefaultBackoff) * (2^TRetries – 1)
TBackoff = Minimum(TMinBackoff + TBackoff, TMaxBackoff)

Bu formülü bir C# uygulamasına uyarlamamız gerekirse şöyle bir kod elde edebiliriz ;

int retries = 1;
var defaultBackoff = TimeSpan.FromSeconds(30);
var minBackoff = TimeSpan.FromSeconds(3);
var maxBackoff = TimeSpan.FromSeconds(90);
var random = new Random();

double backoff = random.Next((int)(0.8D * defaultBackoff.TotalMilliseconds),
(int)(1.2D * defaultBackoff.TotalMilliseconds));
backoff *= (Maş.Pow(2, retries) – 1);
backoff = Maş.Min(minBackoff.TotalMilliseconds + backoff,
maxBackoff.TotalMilliseconds);

Read More