Windows Azure'da Worker Role Kullanımı

0 dakikada yazıldı

31108 defa okundu

Düzenle

Bugüne kadar birçok detaya bakmış olsak da Worker Role'lere hiç göz atmadık. Bunun nedenlerinden biri tabi ki Worker Role'lerin aslında özüne bakılacak olursa süper basit olmasıydı :) Ama yine de hızlıca bir göz atalım istiyorum. Hatta Worker Role'lere bakarken genel Azure senaryosunu da devreye alaray WebRole, Worker Role ve Storage Queue yapılarını yan yana getirip güzel bir resim çizelim ne dersiniz? ;)

Yeni bir Worker
Role...Yeni bir Worker Role...

Taze bir Worker Role

Yeni bir Azure projesi yaratıp içine sadece bir Worker Role eklerseniz Solution Explorer içerisinde sizi pek de kalabalık bir dosya sayısı beklemeyecek :) Worker Role'ler biliyorsunuzki Azure ortamında host edilirken içerisinde IIS olmayan sanal makinelerde barındırılıyorlar. O nedenle ASP.NET'in de doğal olarak bütün application lifecycle'ından kurtulmuş durumdalar.

Yeni bir Worker Role projesinde tek bir CS dosyası
var.Yeni bir Worker Role projesinde tek bir CS dosyası var.

Yukarıdaki ekran görüntüsünden de inceleyebileceğiniz üzere :) yeni bir worker role projesinde sadece bir tane kod dosyası var. Onun dışında hiçbir şey yok! :) Tertemiz bir manzara söz konusu. Worker Role'lerin kullanımı genelde arkaplanda yapılacak işlemlerle ilgili oluyor. Web Role ön tarafta kullanıcının veri girişini alıp sistemdeki veriyi kullanıcıya göstermekle yükümlüyken Worker Role ise arkada diğer işlemleri yapmakla ve süreçleri takip etmekle yükümlü.

[C#]

public override void Run()\ {\     // This is a sample worker implementation. Replace with your logic.\     Trace.WriteLine("$projectname$ entry point called""Information");\ \     while (true)\     {\         Thread.Sleep(10000);\         Trace.WriteLine("Working""Information");\     }\ }

Sıfırdan yaratılan bir worker role'ün tek kod dosyasında da yukarıdaki kod yazıyor :) Şimdi hemen bu noktadan "While(True)" gördüğünüz gibi "Nasıl yani?" diyor olabilirsiniz :) Konseptimiz şu, eğer bir Worker Role'un içerisinde Run metodundan çıkılırsa worker role çatlamış oluyor / kapanmış oluyor. Böyle bir durumda doğal olarak FC Guest Agent da gidip "Bu Worker kapandı" diyip Worker'ı tekrar açıyor :) Yani özetle bir worker role'un Run metodunun hiçbir zaman bitmemesi gerekiyor. Bunun için de basit bir While(True) işi görmeye yetiyor. Tabi çılgın looplara girmemek adına arada Thread'i Sleep'e almak mantıklı olacaktır ama yoğun işlemler yaptığınızda Sleep süresini de yönetmenizde fayda var. Aşırı yoğun senaryolarda Sleep yapmayabilirsiniz de, çünkü zaten Worker'ın yapacağı birçok iş vardır. Tüm bu işler / işlemler de tahmin edebileceğiniz üzere Whie(True) döngümüz içerisinde gerçekleştirilir.

Eeehh :) Worker olayı bu kadar :) Basit olacağını söylemiştim. Web Role'lerde olan tüm Role özellikleri Worker Role'lerde de var. Yani yine vm size ve instance count gibi değişkenler ayarlanarak Worker Role'ler de genişletilebiliyor. Şimdi isterseniz gelin Web Role ve Worker Role'ün beraber kullanımına göz atalım.

Web Role ve Worker Role el ele!

Yeni bir Cloud Service projesi yaratıp içine bir Worker ve bir de Web Role koyuyoruz. Web Role'ün hemen global.asax'da ConfigurationPublisher'ı set ediyoruz ki Storage Account'umuzu da kullanabilelim rahatlıkla.

[C#]

void Application_Start(object sender, EventArgs e)\ {\     // Code that runs on application startup\     CloudStorageAccount.SetConfigurationSettingPublisher(\                                 (configName, configSettingPublisher) =>\     {\         var connectionString = RoleEnvironment.GetConfigurationSettingValue(configName);\         configSettingPublisher(connectionString);\     }\     );\ }

Publisher hazır olduktan sonra web sitesine bir ASPX dosyası, sayfaya da bir TextBox ve Button ekleyin :) Sonra da Button'un Click'e aşağıdaki kodu yazalım.

[C#]

var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");\ var Client = storageAccount.CreateCloudQueueClient();\ CloudQueue q = Client.GetQueueReference("yenikuyruk");\ CloudQueueMessage yeniMesaj = new CloudQueueMessage(\                                 string.Format("text:{0}",TextBox1.Text));\ q.AddMessage(yeniMesaj, TimeSpan.FromMinutes(1),TimeSpan.FromMinutes(2));

Kodumuza baktğımızda DataConnectionString diye bir yerden StorageAccount connection stringinin alındığını ve "yenikuyruk" adında bir kuyruk yaratılıp TextBox içerisindeki metnin kuyruğa mesaj olarak konduğunu görebiliriz. Tabi burada örnek olduğu için konu ve işlemler epey basit duruyor ama buradaki senaryoyu gerçek hayattaki bir senaryoyla eşleştirmek gerekirse... bir E-Ticaret sitesinde alışveriş yapan bir müşterinin alışveriş sepetinin SQL Azure'a tamamen kaydedildikten sonra sipariş onaylandığında da siparişle ilgili işlemlerin yapılması üzerine sipariş ID'sini kuyruğa attığını düşünebilirsiniz. Özetle arka tarafta yapılması gereken bir işlemle ilgili bilgileri SQL Azure ve Blob'lara koyduktan sonra Web Role yani web sitesi işlemin bir referansını da kuyruğa atıyor. Böylece bu noktadan sonra Worker Role'ler gelip kuyruğa bakıp eğer yeni işlem varsa işlemi alıp üzerinde çalışabilecekler.

Yeni Worker Role'ümüze geçtiğimizde ise yine Worker Role içerisinde de Storage Client'ı kullanacağımız için SettingsPublisher'ı ayarlamamız gerekiyor.

[C#]

public override bool OnStart()\ {\     ServicePointManager.DefaultConnectionLimit = 12;\ \     CloudStorageAccount.SetConfigurationSettingPublisher(\                             (configName, configSettingPublisher) =>\     {\         var connectionString = RoleEnvironment.GetConfigurationSettingValue(configName);\         configSettingPublisher(connectionString);\     }\     );\     return base.OnStart();\ }

Herşey hazır olduğuna göre artık Worker Role içerisindeki kodumuzu yazmaya başlayabiliriz. Amacımız Storage Account'a bağlanıp kuyrukta yapılması gereken işlem var mı? yok mu? kontrol etmek. Eğer işlem varsa, işlemi yapıp kuyruktan kaldırmamız, eğer işlem yoksa bir süre sonra tekrar kontrol etmemiz gerekecek.

[C#]

public override void Run()\ {\     var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");\     var Client = storageAccount.CreateCloudQueueClient();\     CloudQueue q = Client.GetQueueReference("yenikuyruk");\ \     while (true)\     {\         CloudQueueMessage mevcutMesaj = q.GetMessage();\ \         if (mevcutMesaj != null)\         {\             string s = mevcutMesaj.AsString;\ \             Trace.WriteLine(string.Format("Gelen Mesaj : {0}", s), "Information");\ \             q.DeleteMessage(mevcutMesaj);\         }\         Thread.Sleep(10000);               \     }\ }

Yukarıdaki kod tam da planladığımız şeyi yapıyor. Run metodu içerisindeki önceki StorageAccount'a sonra da web arayüzünen mesajların aktarıldığı kuyruğa ulaşıyoruz. While(True) döngüsü içerisinde kuyruktan sürekli bir mesaj isteyip eğer gelen mesaj null değilse yani mesaj varsa mesajı alıp Trace olarak yazıyoruz. Bu noktada tabi ki sizin farklı kodlar yazarak işlemler yapmanız mümkün. Bizim örnek test amaçlı olduğu için ben sadece Trace'e yazdırdım.

Herşey bittikten sonra artık kuyruk üzerinden DeleteMessage diyerek aldığımız ve işlemlerini tamamladığımız işin mesajını da siliyoruz.

Sanırım şu anda hem Worker Role, Web Role ve Storage Queue ile beraber taşları yerli yerine oturtabilmişizdir ;) Uygulamanızı çalıştırmadan da her iki role'ün de CSDEF ve CSCFG'lerinden Storage Account connection stringlerini yazmayı unutmayın. Uygulamayı çalıştırdıktan sonra Compute Emulator'ın console görüntülerinden Trace'leri izleyebilirsiniz ;)

Hepinize kolay gelsin.