Burak Selim Senyurt(MVP)
Matematik Mühendisi bir .NET Severin Yazıları...

Microsoft.Net Services - Service Bus için REST Tabanlı Hello World

Cuma, 20 Kasım 2009 08:45 by bsenyurt

Merhaba Arkadaşlar,

Bir önceki yazımızda Microsoft.Net Services alt yapsının önemli parçalarından birisi olan Service Bus hizmetini incelemeye çalışmış ve basit bir Hello World uygulama koleksiyonu geliştirmiştik. Bu yazımızda ise REST bazlı geliştirilen bir WCF servisine herhangibir tarayıcı yardımıyla HTTP Get metoduna göre, Service Bus üzerinden nasıl ulaşabileceğimizi incelemeye çalışacağız.

REST bazlı modelde bilindiği üzere Web tabanlı olarak yayınlanan servislere HTTP protokolünün Get,Post,Put,Delete gibi metodları yardımıyla erişilebilmektedir. Bu URL bazlı erişim sayesinde herhangibir tarayıcı uygulamanın söz konusu servis operasyonlarını kullanabilmesi mümkündür. Üstelik istemciler arada bir proxy nesnesine ihtiyaç duymadan doğrudan HTTP taleplerini gönderebilir. Bunlara ek olarak birde servis operasyonlarının Syndication(RSS,Atom gibi) tabanlı içerik yayınlayabilme kabiliyetleri eklendiğinde Web programlama modeline uygun bir hizmet üretiminin gerçekleştirilebildiği gözlemlenecektir.

WCF mimarisi, .Net Framework 3.5 sürümünden bu yana Web programlama modelini desteklemektedir. Bu nedenle REST(Representational State Transfer) bazlı WCF servisleri kolayca geliştirilebilir. Bizde bu günkü örneğimizde sunucu tarafında, RSS 2.0 formatında içerik yayınlaması yapan ve REST tabanlı olarak çalışabilen bir WCF servisini geliştirecek ve buna olan istemci erişimleri için Service Bus' tan yararlanacağız. Tahmin edeceğiniz üzere Microsoft.Net Services üzerinde örneğimiz için bir Service Namespace' i oluşturulması gerekmektedir. Ben bu günkü örneğimiz için günlük öneri yemek listesini sunacak bir hizmete uygun aşağıdaki isimlendirmeyi kullanmayı tercih ettim.

Bundan sonraki ilk adımımız servis uygulamasını geliştirmek olacaktır. Söz konusu uygulama WCF Web programlama modelini(Web Programming Model) kullanacağından ve Service Bus üzerinden iletişimi sağlayacağından aşağıdaki şekilde görülen Microsoft.ServiceBus, System.ServiceModel.Web ve System.ServiceModel assembly' larını referans etmelidir.

Gelelim sunucu uygulama tarafındaki kodlarımıza;

using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Syndication;
using System.ServiceModel.Web;
using Microsoft.ServiceBus;

namespace ServerApp
{
    // Servis sözleşmesi
    [ServiceContract(Namespace = "http://www.buraksenyurt.com/MyFoodCompany")]
    public interface IDailyFoodListContract
    {
        [OperationContract]
        [WebGet] // Http Get taleplerine cevap verecek bir operasyon olduğunu belirtiyoruz
        Rss20FeedFormatter GetDailyFoodList(string Day);
    }

    // Servisi uygulayan tip
    [ServiceBehavior(Name = "DailyFoodListService", Namespace = "http://www.buraksenyurt.com/MyFoodCompany")]
    public class DailyFoodListService
        :IDailyFoodListContract
    {
        #region IDailyFoodListContract Members
       
        // GetDailyFoodList metodu RSS 2.0 Formatında basit bir Syndication içeriği döndürmektedir.
        public Rss20FeedFormatter GetDailyFoodList(string Day)
        {
            // Öncelikli olarak Feed oluşturulur
            SyndicationFeed foodFeed = new SyndicationFeed();
            foodFeed.Id=String.Format("Day_{0}",Day);
            foodFeed.Title = new TextSyndicationContent("Günlük Yemek Listesi");

            // Feed içerisindeki Item listesi hazırlanır
            List<SyndicationItem> foodItems = new List<SyndicationItem>();
            foodItems.Add(new SyndicationItem( "Aperatifler","Patlıcanlı Musakka", new Uri("http://myfoodcompany/Food/Musakka"), "10001", DateTime.Now));
            foodItems.Add(new SyndicationItem("Çorbalar", "Mercimek Çorbası", new Uri("http://myfoodcompany/Food/MercimekCorba"), "12034", DateTime.Now));
            foodItems.Add(new SyndicationItem("Ana Yemekler", "Mozeralla Peynirli Makarna", new Uri("http://myfoodcompany/Food/MakarnaMozeralla"), "10025", DateTime.Now));

            // Item listesi feed' e eklenir.
            foodFeed.Items=foodItems;

            // RSS 2.0 formatındaki Feed içeriği üretimi için SyndicationFeed nesne örneği Rss20FeedFormatter sınıfının yapıcı metoduna parametre olarak geçirilir.
            return new Rss20FeedFormatter(foodFeed);
        }

        #endregion
    }

    //// Kanal arayüzü
    //public interface IDailyFoodListChannel
    //    : IDailyFoodListContract, IClientChannel
    //{
    //}

    class Program
    {
        static void Main(string[] args)
        {
            Uri address = ServiceBusEnvironment.CreateServiceUri("https", "MyFoodCompany", "Foods");

            // REST bazlı bir WCF Servisi host işlemi gerçekleştirileceğinden WebServiceHost nesne örneğinden yararlanılır
            WebServiceHost host = new WebServiceHost(typeof(DailyFoodListService), address);
            host.Open(); // Servis açılır

            Console.WriteLine("Servis açıldı. Servis durumu {0}\nService Adresi {1}", host.State,address.ToString());
            Console.WriteLine("Operasyon Adı : GetDailyFoodList\n");
            Console.WriteLine("Çıkmak için bir tuşa basınız");
            Console.ReadLine();

            host.Close(); // Servis kapatılır
        }
    }
}

WCF Servis sözleşmemiz içerisinde yer alan GetDailyFoodList operasyonu, string parametre alıp RSS 2.0 formatında içerik üreten basit bir fonksiyonellik sunmaktadır. Bu operasyonun HTTP Get taleplerine cevap verebilmesi istendiğinden WebGet niteliği ile imzalanması gerekmektedir. Diğer yandan WCF çalışma zamanının REST tabanlı talepleri değerlendirmesi istendiğinden ServiceHost yerine WebServiceHost tipinin kullanılması gerektiğide aşikardır. Bunun dışında servis operasyonumuz tamamen deneysel olarak günlük öneri yemek listesini üretmektedir. Pekala dünya üzerindeki restoran zincirlerine veya herhangibir evin mutfağındaki dokunmatik ekranlara bu tip bir servis yardımıyla hizmet götürüyor olsaydık daha fazla parametre alacak ve veri kaynağı olarak Azure üzerinde yer alacak bir Database Service' ini kullanacak bir operasyon da geliştirebilirdik. Kimbilir belki ilerleyen zamanlarda bu tip komple bir örneğide geliştirme fırsatımız olur. Wink 

Servis uygulamamız tarafında çalışma zamanı konfigurasyon bilgileri içinde App.config dosyasının aşağıdaki gibi düzenlenmesi yeterlidir.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <webHttpRelayBinding>
        <binding name="DailyFoodListServiceBinding">
          <security relayClientAuthenticationType="None" />
        </binding>
      </webHttpRelayBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="DailyFoodServiceBehavior" name="ServerApp.DailyFoodListService">
        <endpoint address="" behaviorConfiguration="credentialBehavior" binding="webHttpRelayBinding" bindingConfiguration="DailyFoodListServiceBinding" name="RelayEndpoint" contract="ServerApp.IDailyFoodListContract" />
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="credentialBehavior">
          <transportClientEndpointBehavior credentialType="SharedSecret">
            <clientCredentials>
              <sharedSecret issuerName="Sizin Issuer Name değeriniz" issuerSecret="Sizin için üretilen Key değeri"/>
            </clientCredentials>
          </transportClientEndpointBehavior>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="DailyFoodServiceBehavior">
          <serviceDebug httpHelpPageEnabled="false" httpsHelpPageEnabled="false" includeExceptionDetailInFaults="True" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Konfigurasyon içeriğinde dikkat çekici noktaların başında kullanılan bağlayıcı tip gelmektedir(webHttpRelayBinding). Bu gereklidir nitekim Service Bus ile iletişim kurulacaktır. Diğer yandan clientCredentials elementi içerisinde, Service Bus projemizdeki ilgili Namespace için üretilen Issuer Name ve Issuer Key değerleri yer almalıdır. Bundan sonrası son derece kolaydır. Servis uygulaması çalıştırıldıktan sonra tarayıcı üzerinden GetDailyFoodList operasyonuna yapılan çağrı aşağıdaki örnek ekran görüntüsünde olduğu gibi karşılanacaktır.

Görüldüğü üzere Wednesday için bir talepte bulunulmuş ve bir içerik elde edilmiştir. Bu örnekte en çok dikkat edilmesi gereken nokta ise operasyon talebinin yapıldığı adres bilgisidir.

https://myfoodcompany.servicebus.windows.net/Foods/GetDailyFoodList?Day=Wednesday Volaaa!!! Laughing Parametreyi nasıl gönderdiğimize, https protokolüne göre bir URL bilgisi yazıldığına dikkat edilmelidir.

Tabiki işin sağlamasını yapmak amacıyla servis uygulamasını kapatıp aynı talebi göndermeyi deneyebilirisiniz. Bu durumda aşağıdaki ekran görüntüsü ile karşılaşılacaktır.

Yanlız burada dikkat edilmesi gereken noktalardan birisi de, geriye bir istisna(Exception) mesajının gönderilmeyişidir. Bu çok doğaldır nitekim servis uygulaması çalışmıyor olsa bile Service Bus üzerinde gelen talebin değerlendirildiği bir hizmet bulunmaktadır.

Örneği geliştirirken meraktan yaptığım bir testte yanlış Issuer Key değeri göndermek oldu. Böyle bir vakada gönderilen HTTP Get talebi sonrası aşağıdaki ekran görüntüsü ile karşılaşılacaktır.

Görüldüğü üzere 401 Unauthorized hatasını aldık. Bir başka deyişle Credential bilgilerimiz doğrulanmadı.

Bu hızlı örnek ile Service Bus hizmetinden REST bazlı olarakta nasıl yararlanabileceğimizi görmüş olduk. Bir önceki yazımızda kullandığımız örnekte geliştirdiğimiz istemci uygulamada hatırlayacağınız üzere, sözleşme tanımlamış, kanal oluşturmuş ve TCP bazlı olan iletişim üzerinden kanal bazlı metod çağrısı ile isteğimizi Service Bus tarafına göndermiştik. REST modelinde ise bir istemci geliştirmediğimizi sadece bir URL kullandığımızı hatırlatmak isterim. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.

RestBased.rar (25,30 kb)

Microsoft.Net Services - Service Bus için Hello World

Çarşamba, 11 Kasım 2009 09:45 by bsenyurt

Merhaba Arkadaşlar,

Bu gün itibairyle İstanbul' da sağnak yağışlı bir hava hakim. Oysaki bir kaç güne kadar güneşli ve ılıman bir hava vardı. Hal böyle olunca Cloud Computing ile ilgili bir şeyler karıştırmanın tam vaktidir diye düşündüm. Daha önceki Windows Azure Service Platformu Hakkında İlk İzlenimler başlıklı yazımızda Amazon' dan Cloud Computing with Windows Azure Platform isimli bir kitabı sipariş ettiğimi ve önümüzdeki dönemlerde bu konu ile ilişkili yazılarımı sizlerle paylaşacağımı belirtmiştim. Ne var ki aradan geçen uzun süreye ve Amazon' dan kitabı elden teslim eden kurye ile sipariş etmeme rağmen kitap elime bir türlü ulaşmadı Undecided ve Amerika' da bir çıkış noktasında takıldı kaldı. Oysaki kütüphanede yer alan sayısız kitap hep sorunsuz ulaşmıştı. Bir kargo firması bir Amazon ile yazışma derken arada gidip gelen sayısız elektronik postanın arkasından en azından paramı geri almaya başardım ama ne varki kitabıma ulaşamadım. Peki yıldım mı? Yılmadım. Bu kez siparişimi Amazon.co.uk sitesinden verdim(Sterlin farklarını hesaba katmanızı öneririm). Kitap siparişin bir sonraki gününde UPS tarafından bana ulaştırıldı. En azından içim rahatladı ve kitabıma kavuştum.Wink Gel gelelim şu an okuduğunuz yazıyı yazmak için bu kitabı bir günde bitirmedim elbetteki. Aslına bakarsanız geçtiğimiz günlerde .Net Services SDK' sının Kasım sürümü ve çok doğal olarak dökümantasyonu yayınlandı. İşte bu yazımızda dökümantasyondan edindiğim ilk izlenimler ışığında geliştireceğimiz basit bir Hello World örneği yazmaya çalışıyor olacağız.

Windows Azure platformunun önemli parçalarından birisi olan Microsoft .Net Services, internet tabanlı uygulama servisleri olarak düşünülebilir. Bu anlmada internet tabanlı uygulamaların Cloud üzerinde yer alan uygulamalar veya kaynaklar(Resources) ile iletişimini servis bazlı olarak koordine edebilen bir servis alt yapısı olarak düşünülebilir. Şu aşamada Microsoft .Net Service' lerin iki uygulama biçimi vardır. Service Bus ve Access Control Service. Özellikle Firewall arkasında kalan istemcilerin Cloud üzerinde yer alan bir uygulama ile haberleşmesi sırasında gerekli olan karmaşık konfigurasyon işlemleri, güvenlik gibi konuları Service Bus üzerine alarak kolay bir şekilde çözümlemeye çalışır. Öyleki Firewall arkasında duran uygulamaların Cloud üzerindeki bir uygulama ile olan haberleşmesinde genellikle port açılması veya VPN kullanılması yolu tercih edilir. Port açılması bir güvenlik riski doğurmakla birlikte, VPN kullanımında da sistem seviyesinde karmaşık konfigurasyon ayarları yapılması gerekmektedir. Oysaki Service Bus bu karmaşıklığı ele alarak istemcilerin Cloud üzerindeki uygulamalar ile konuşabilmesini kolaylaştırmaktadır. Üstelin Authentication gibi işlevlere de sahiptir. 

Service Bus çok basit anlamda birbirlerine zayıf bağlı olan(Loosely Coupled) uygulamaların güvenli bir şekilde iletişim kurabilmesini sağlamak, platforma bakılmaksızın gerekli karmaşık konfigurasyon ayarlarını sağlamak amacıyla kullanılmaktadır. İlk etapta Windows Azure platformu üzerinde yer alan Azure ve SQL Service uygulamaları ile olan iletişiminde kullanılabileceği düşünülebilir. Bu açıdan bakıldığında Azure platformu üzerindeki uygulamalar ve veritabanları ile haberleşilirken kullanılan bir servis alt yapısı olarakta görülebilir. Aşağıdaki şekil Service Bus alt yapısını bu açıdan değerlendirmektedir.

Aslında bu şekil bize şunları ifade etmektedir; App A, üzerinde bulunduğu Platform' daki Firewall gibi sorunlara takılmadan Azure Platform' u üzerinde konuşlandırılmış bir Cloud servisine, uygulamasına veya kaynağına(Resource) erişmek için Service Bus alt yapısını kullanmaktadır. Şekilde yer alan App B, Cloud üzerinde yer alan bir uygulama olarak düşünülmektedir. Buna göre App A ile App B' nin haberleşmesinde Service Bus gerekli bağlantıyı, koordinasyonu sağlamakta ve güvenli bir iletişimi tesis etmektedir. Diğer taraftan App A yine Service Bus aracılığıyla başka bir platform üzerinde yer alan App C isimli uygulama ilede güvenli bir iletişim sağlayabilmektedir.

Peki Service Bus alt yapısının en belirgin özellikleri nelerdir?

  • Firewall, NAT Gateway gibi unsurların arkasında duran uygulama ve servislerin birbirleriyle haberleşebilmelerini gerekli konfigurasyon ayarlamalarını üstüne aldığı için kolaylaştırır. Geliştiricinin veya tarafların hangi sistem gereksinimlerine ihtiyaçları olduğunu, bulundukları farklı platformlar arasındaki haberleşme sorunlarını düşünmelerine gerek yoktur.
  • Standart REST modelini de desteklediğinden kolay bir şekilde kullanılabilir ama istenirse WCF bazlı yaklaşım değerlendirilerek profesyon programcılar tarafından değerlendirilmeside sağlanabilir.
  • .Net platformundan olmayan uygulamalara REST ve HTTP tabanlı erişilebilmesini sağlar.
  • Cloud üzerindeki servislere Anonymous kullanıcıların erişebilmesi, izin verildiği takdirde mümkündür.
  • Servislerin internet üzerinden erişilebilen sabit URL adresleri ile keşfedilmesi(Discovery) lokasyona bakılmaksızın mümkündür.
  • Servislere yapılan şüpheli saldırıların bloklanmasına yardımcı olur.

vb...

Bu kısa How To niteliğindeki yazımızda aynı makine üzerinde yer alan bir istemci ile yine aynı makine üzerinde yer alan ve servisi host eden başka bir uygulama arasında Service Bus aracılığıyla Credential bazlı bir iletişimin nasıl kurulabileceği incelenmektedir. Gerçek anlamda Cloud üzerindeki bir uygulama, servis veya kaynak ile haberleşilmese de durumu simule edebileceğimiz bir örnek olacaktır.

Tabiki işin daha çok detayı vardır ancak adet olduğu üzere konuyu kavramının en iyi yolunun çok basit bir örnek geliştirmekle mümkün olabileceği kanısındayım. İşlemlere başlamadan önce Microsoft .Net Services SDK' sının Kasım 2009 sürümünü indirmemiz ve sistemimize yüklememiz gerekmektedir. Bu SDK içerisinde .Net Services olanaklarından yararlabilmemiz için gerekli tipler ve üyeleri yer almaktadır. SDK' nın yüklenmesi yeterli değildir. Ayrıca Windows Azure platformu üzerinden bir servis hesabının açılması ve burada kullanacağımız Service Bus için bir Namespace bildirimi yapılması gerekmektedir. Söz konusu hizmetlerden şu an için ücretsiz yararlanılabilmekte olup 2010 içerisinde ücrete tabi olacağına dair bilgiler de yer almaktadır. (Ancak yazıyı hazırladığım bu günlerde Microsoft.Net Service' leri ücretsiz olarak kullanılabilmekteydi.) Kayıt işlemleri için https://netservices.azure.com/ adresinden yararlanılmaktadır. Örneğin benim Azure üzerinde yer alan projemde bu yazımızdaki örnek için oluşturduğum AlgebraService Namespace ve bilgileri aşağıdaki şekilde görüldüğü gibidir.

Dilerseniz Namespace detaylarına da bakabilir gerekirse silerek hizmetten kaldırabilirsiniz. Namespace oluşturulduktan sonra istemci ve servis tarafının kullanacağı ehliyet(Credential) bilgilerinin de otomatik olarak oluşturulduğu görülecektir. Service Bus örneğimiz için bunlar Default Issuer Name ve Default Issuer Key değerleridir. Bu bilgiler Service Namespace' ine ait Summary bölgesinde görülebilmektedir.

Örneğimizde servis ve istemci uygulamalar aynı makine üzerinde geliştirilecek olsalarda, aralarındaki Credential tabanlı iletişim için yukarıda bilgileri yer alan Service Bus hizmeti kullanılacaktır. Service ve Host uygulamalarımız Visual Studio 2008 ortamında geliştirilmekte olan basit Console uygulamalarıdır ve her ikiside, System.ServiceModel ile .Net Services SDK' sının yüklenmesi sonrasında gelen Microsoft.ServiceBus assembly' larını referans etmektedir.

Servis tarafındaki kodlarımızı aşağıdaki gibi geliştirebiliriz.

using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using Microsoft.ServiceBus;

namespace AlgebraHost
{
    // Servis sözleşmesi
    [ServiceContract(Namespace = "http://algebraservice/ServiceBus/")]
    public interface IAlgebraContract
    {
        [OperationContract]
        double Sum(double x, double y);
    }

    public interface IAlgebraChannel
        : IAlgebraContract, IClientChannel
    {
    }

    // Sözleşmeyi uygulayan tip
    [ServiceBehavior(Name="Algebra")]
    public class AlgebraService
        : IAlgebraContract
    {
        #region IAlgebraContract Members

        public double Sum(double x, double y)
        {
            return x + y;
        }

        #endregion
    }


    class Program
    {
        static void Main(string[] args)
        {
            // Servis adresi elde edilir
            // İlk parametre schema, ikinci parametre Service Bus üzerinde oluşturulan Solution adı ve üçüncü parametrede servis yoludur
            Uri serviceUri = ServiceBusEnvironment.CreateServiceUri("sb", "AlgebraService", "AlgebraService");

            // İletişim için gerekli olan issuer adı ve şifresi bilgileri TransportClientEndpointBehavior nesne örneğinde toplanır
            TransportClientEndpointBehavior credential = new TransportClientEndpointBehavior();
            credential.CredentialType = TransportClientCredentialType.SharedSecret; // Credential tipi
            credential.Credentials.SharedSecret.IssuerName = "SİZİN ISSUER NAME DEĞERİNİZİ"; // Issuer adı
            credential.Credentials.SharedSecret.IssuerSecret = "SİZİN İÇİN ÜRETİLEN KEY DEĞERİ// Issuer için otomatik üretilmiş olan key değeri

            // ServiceHost nesne örneklenir
            // İlk parametre servis tipidir
            // İkinci parametre ise servis adresidir
            ServiceHost host = new ServiceHost(typeof(AlgebraService), serviceUri);
            IEndpointBehavior serviceRegistrySettings = new ServiceRegistrySettings(DiscoveryType.Public);

            // Config dosyasında tanımlanan tüm Endpoint' lere gerekli Credential davranışı eklenir.
            foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
            {
                endpoint.Behaviors.Add(serviceRegistrySettings);
                endpoint.Behaviors.Add(credential);
            }

            // Servis açılır
            host.Open();

            Console.WriteLine("Servisin orjina adresi \n {0}:\n Service Durumu {1} ",serviceUri,host.State);
            Console.WriteLine("Kapatmak için bir tuşa basınız");
            Console.ReadLine();

            // Servis kapatılır
            host.Close();
        }
    }
}

Aslında standart bir WCF Servisi yazılmış ve host edilmiştir. Ancak Service Bus üzerinde tanımlı Service Namespace' in kullanılması içinde bir takım ek işlemler yapılmıştır. Söz gelimi bu iletişim için gerekli Credential bilgileri TransportClientCredentialType tipi yardımıyla servisin üzerindeki tüm endPoint' lere birer çalışma zamanı davranışı(Behavior) olarak bildirilmektedir. Buna göre servis, istemci ile olan tüm iletişiminde Azure üzerindeki projemiz için üretilen Name ve Key değerleri kullanılacaktır. Diğer yandan servisin adresi belirlenirken, Service Namespace bilgisinin kullanıldığı dikkatten kaçmamalıdır. Nitekim Azure üzerindeki ilgili servisin adresinin bilinmesi gerekmektedir. Bu amaçla sb isimli Service Bus schema adından da CreateServiceUri metodu içerisinde yararlanılmaktadır. Elbette servis tarafında WCF çalışma zamanı(WCF Runtim) için gerekli konfigurasyon ayarlarının da bildirilmesi gerekmektedir. Bu amaçla servis uygulamasına ait App.config dosyası aşağıdaki gibi geliştirilebilir.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="AlgebraHost.AlgebraService">
        <endpoint contract="AlgebraHost.IAlgebraContract" binding="netTcpRelayBinding"/>
      </service>
    </services>
  </system.serviceModel>
</configuration>

Dikkat çekici nokta TCP bazlı iletişim için kullanılan bağlayıcı tiptir(Binding Type).

Gelelim yine Console olarak tasarladığımız istemci uygulama tarafı kodlarına.

using System;
using System.ServiceModel;
using Microsoft.ServiceBus;

namespace AlgebraClient
{
    // Sözleşme tipi(Contract Type)
    [ServiceContract(Namespace = "http://algebraservice/ServiceBus/")]
    public interface IAlgebraContract
    {
        [OperationContract]
        double Sum(double x, double y);
    }

    public interface IAlgebraChannel
        : IAlgebraContract, IClientChannel
    {
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Başlamak için bir tuşa basınız");
            Console.ReadLine();
           
            // Bağlantı protokolünün (Http, Tcp) otomatik olarak belirleneceği bildirilir
            ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.AutoDetect;

            string sbNamespace = "AlgebraService";
            string sbIssuer = "SİZİN ISSUER NAME DEĞERİNİZ";
            string sbIssuerKey = "SİZİN ISSUER KEY DEĞERİNİZ";

            // Servis adresi üretilir
            Uri serviceUri = ServiceBusEnvironment.CreateServiceUri("sb", sbNamespace, "AlgebraService");

            // İletişim için gerekli olan issuer adı ve şifresi TransportClientEndpointBehavior tipinden nesne örneği ile bildirilir.
            TransportClientEndpointBehavior credential = new TransportClientEndpointBehavior();
            credential.CredentialType = TransportClientCredentialType.SharedSecret;
            credential.Credentials.SharedSecret.IssuerName = sbIssuer;
            credential.Credentials.SharedSecret.IssuerSecret = sbIssuerKey;

            // İletişimin kanalını üretecek olan fabrika nesnesi oluşturulur. İlk parametre ile config dosyasındaki Client Endpoint yeri belirtilir, ikinci parametre ilede Service Bus üzerindeki adres bilgisi belirtilir
            ChannelFactory<IAlgebraChannel> channelFactory = new ChannelFactory<IAlgebraChannel>("AlgebraEndpoint", new EndpointAddress(serviceUri));
            // İletişimin hangi kullanıcı adı ve şifre ile gerçekleştirileceği ilgili TransportClientEndpointBehavior nesne örneğinin davranış olarak bildirilmesiyle gerçeklenir
            channelFactory.Endpoint.Behaviors.Add(credential);

            // İletişim kanalı oluşturulur ve açılır
            IAlgebraChannel clientChannel = channelFactory.CreateChannel();
            clientChannel.Open();           
         
            // Sum operasyonuna çağrı yapılır
            Console.WriteLine("Sum Result {0} + {1} = {2} ", 2,4,clientChannel.Sum(2,4).ToString());
         
            // İletişim kanalı ve kanal üretme fabrikası kapatılır
            clientChannel.Close();
            channelFactory.Close();
        }
    }
}

İstemci tarafında da dikkat edileceği üzere Servis sözleşmesnin bir kopyası yer almaktadır. Nitekim çalışma zamanındaki proxy üretimi için servis sözleşmesinin sunduğu içeriğin bilinmesi gerekmektedir. Burada devreye ilgili servis sözleşmesini implemente eden kanal arayüz referansıda girmektedir. İstemci tarafı için yapılan adımlar aslında sırasıyla aşağıdaki gibidir;

  1. Bağlantı modu belirlenir(ConnectivityMode)
  2. Host servisin adresi belirlenir(Uri bilgisi belirlenirken Azure Projesi üzerinde oluşturduğumuz Service Namespace adı kullanılır)
  3. Gerekli Crendetial tanımlamaları yapılır ve bağlantı için uygulanması sağlanır(TransportClientEndpointBehavior)
  4. Kanal oluşturulur ve Credential' ı değerlendirmesi davranış(Behavior) eklenmesi yardımıyla belirtilir
  5. Kanal bağlantısı açılır.
  6. Gerekli servis operasyonları icra edilir.(Kobay olarak sıkça kulladığımız Sum operasyonu Wink )
  7. Bağlantılar kapatılır.

Çok doğal olarak istemci uygulamanın WCF Çalışma zamanı içinde bir takım konfigırasyon ayarlarının yapılması gerekmektedir. İşte istemci tarafı config dosyası içeriği;

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <client>
      <endpoint name="AlgebraEndpoint" contract="AlgebraClient.IAlgebraContract" binding="netTcpRelayBinding"/>
      <!-- Service Bus ile iletişim kurmak için TCP protokolü kullanılacaktır. netTcpRelayBinding bunu belirtmektedir-->
    </client>
  </system.serviceModel>
</configuration>

Önce sunucu uygulamamız sonrasında ise istemci uygulamamız çalıştırıldığında aşağıdakine benzer bir ekran görüntüsü ile karşılaşılması muhtemeldir.

Eğer bu şekilde bir sonuç aldıysak istemci uygulamamızın host edilen servis ile Service Bus üzerinden haberleştiğini düşünebiliriz. Aslında emin olmak için deneme amacıyla oluşturduğumuz Service Namespace' ini kaldırmamız yeterli olacaktır Wink Lakin bu durumda aşağıdaki sonuç ile karşılaşırız(EndpointNotFoundException)

Böylece Azure Service Platformu üzerindeki ilk atılımımızı gerçekleştirmiş olduk arkadaşlar. Umarım birşeyler aktarabilmişimdir. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.

AlgebraHost.rar (47,27 kb)

Windows Azure Service Platformu Hakkında İlk İzlenimler

Perşembe, 22 Ekim 2009 19:15 by bsenyurt

Merhaba Arkadaşlar,

Güneşli açık bir hava ve sessiz bir gün yada gece...Deniz kenarında veya caddenin herhangibir köşesinde...Mutlaka zaman zaman gökyüzüne bakıp bulutları bazı nesnelere benzettiğimiz olmuştur. Yandaki resimde görüldüğü gibi gülen bir bulutla karşılaşma ihtimalimiz az olsada, arabaya, ördeğe veya başka bir şekle benzettiğimiz bulut sayısı oldukça fazladır. Bugünkü yazımızda bulutlar ile pek bir haşır neşir olacağımızı düşünebilirsiniz. Ancak tabiki yazılımsal anlamda Wink

Microsoft' un son yıllarda Cloud Computing mimarisi için getirdiği geliştirmelerden biriside Windows Azure Services platformudur. Bu platformu servis bazlı bir işletim sistemi olarak düşünebiliriz. Ama bu çok basit bir yaklaşım olur. Bu konuda aslında pek çok kaynakta yazılmakta ve çizilmektedir. Ancak ürün henüz nihai halini almadığından sürekli olarak değişimlere uğramaktadır. Söz gelimi daha önce yayınlanan SDK içerisine Microsoft.Net Services bloku içerisinde yer alan Workflow Services modeli, Temmuz 2009' da yayınlanan CTP sürümünde kaldırılmışdır. Aslında konunun detaylarına girdiğimde çok kısa bir sürede kaybolduğumu ifade edebilirim. Bu nedenle yazımızın bundan sonraki kısımlarında mimarinin ne getirdiğini sizlere araştırma sonuçlarımdan aktarmaya çalışacağım.

Windows Azure Service Platformu iki ana parçayı içermektedir. İlk parça olan Windows Azure, bulut tabanlı işletim sistemidir. Bu işletim sistemi üzerinde ise çeşitli servis inşa blokları(Building Blocks) yer alır(Microsoft SQL Services, Microsoft .Net Services, Live Services, Microsoft Sharepoint Services, Microsoft Dynamics CRM Services) gibi. Aşağıdaki şekilde söz konusu mimari model daha net görülebilmektedir.

 

Windows Azure platformunu aslında şu cümle ile tanımlayabiliriz; Azure, internet tabanlı bulut bilişim ortamını(Internet Based Cloud Computing) sağlayarak, uygulamaların çalıştırılması veya verinin saklanması için Microsoft veri merkezlerinin(Data Centers) kullanılabilmesini sağlayan bir platformdur. Bu tanımlamaya göre Windows Azure Service platformunu bir Cloud Computing Fabrikası olarak düşünülebilir. Öyleki bir veri merkezi olarak, uygulama veya servislerin Internet üzerinde geliştirilmesi(Development), dağıtılması(Deployement, yönetilmesi(Management) mümkündür. Bu açıdan bakıldığında Windows Azure Service platformunun iki temel fonksiyonelliği olduğu söylenebilir. Uygulama çalıştırmak ve veri saklamak.

Peki Internet üzerinde yer alan böyle bir bulut kümesinin ne gibi bir faydası olabilir? Herşeyden önce uygulamaların çalıştırılacağı verinin fiziki olarak saklanacağı ortama ait IT karmaşıklığını düşünememize gerek kalmamaktadır. Bir başka deyişle host ortamının fiziki sunucu özelliklerinin ayarlanması, oluşturulması, bunlar için gerekli yazılımların tesis edilmesi gibi maliyetlerin düşünülmesine gerek kalmamaktadır. Üstelik Cloud içerisine dahil edilen uygulama veya veri kümelerinin istenen anda istenilen yerden kullanılabilmesi de mümkündür.

Windows Azure tarafında önem arz eden kavramlardan olan veri depolama(Data Storage) bloku, BLOB(Binary Large OBjects), kuyruk(Queue) ve basit tablo(Simple Table) verilerinin saklanması için gerekli servisleri sunmaktadır. Ancak aksine ilişkisel veritabanları tarafından sunulan, sorgulama(query), arama(Search),raporlama(Reporting) vb yetenekleri sağlamamaktadır. Bu yeteneklerin, Cloud üzerinde saklanan veri kümelerinde kullanılabilmesi için Microsoft SQL Services' lerden yararlanılması gerekmektedir.

Microsoft .Net Services şu anda 2 temel fonksiyonelliği karşılamaktadır. Uygulamalar arası bağlanabilirlik(Application Connectivity) ve Erişim kontrolü(Access Control).  Uygulamalar arası bağlanılabilirlik için Microsoft .NET Services Bus bloku kullanılmaktadır. Bu blok, çeşitli mesajlaşma desenlerine göre Internet üzerindeki uygulamalar arasında bir network altyapısının oluşturulabilmesini sağlamaktadır. Erişim kontrolü için Microsoft .NET Access Control Service bloku ele alınır. Bu blok ile aslında Claims tabanlı erişim kontrolünün Cloud üzerinde gerçeklenmesi sağlanır.

Aslında Microsoft .Net Service' leri, bütünüyle servis bazlı geliştirme fabrikası olarak düşünülebilir. Microsoft .Net Service' lerini geliştirirken kullanılan SDK, WCF ile entegrasyon da sağlamaktadır. Bu sayede var olan .Net geliştirme teknikleri ile tasarlanan WCF uygulamalarının Cloud servisi haline getirilmesi mümkündür. Önemli olan noktalardan bir diğeride, Microsoft .Net Service' in sadece .Net geliştiriciler için tasarlanmış olmayışıdır. Desteklenen REST, SOAP, WS* gibi protokoller sayesinde Java ve Ruby gibi diller için geliştirilmiş olan SDK' lardan yararlanarak da Cloud servisleri geliştirilebilir.

Windows Azure platformu ile ilişkili olarak başlangıç noktamız http://www.microsoft.com/windowsazure/ adresi olmalıdır. Bu adresten gerekli SDK ve Visual Studio 2008/2010 Beta X araçlarının indirilierek kurulması geliştirilmeye başlanması için yeterlidir. Ek olarak örneğin .Net Services geliştirilmesi yapılacaksa bu konu ile ilişkili SDK' nın http://www.microsoft.com/windowsazure/developers/dotnetservices/ adresinden tedarik edilmesi gerekmektedir.

Ben bu konuya oldukça meraklıyım aslında. Nitekim işin içerisinde Service kavramı var Cool Bu nedenle bende boş durmadım ve önümüzdeki sene Cloud Computing ve Windows Azure ile ilişkili olan araştırmalarımı daha sağlıklı devam ettirebilmek adına Amazon' dan Cloud Computing with the Azure Platform adlı kitabı sipariş ettim. Bakalım önümüzdeki sene Azure ile ilişkili olarak ne gibi bir macera beni(ve doğal olarak siz değerli okurlarımı) bekliyor olacak. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.