|
|
|
WCF - One Way Ticket |
|
| Gönderiliyor lütfen bekleyin... |
|
|
One Way Ticket...One Way Ticket... Bu
sözleri duyduğumda aklıma bu şarkıyı yapan eruption ve cover versiyonunu
söyleyip efsaneleşen Boney M grupları gelir. Ancak One Way ikilisi ne
tesadüftürki .Net Remoting mimarisinde de karşımıza çıkmaktadır. Kısaca
tek yön olarak çevirebileceğimiz bu iki kelime aslında fırlat ve unut(fire
and forget) anlamındada düşünülebilir. Yada bir başka deyişle
istemci tarafından olaya bakıldığında, "metodu çağırdım gerisi umrumda
değil" de denebilir. Aynı kelimelerin Windows Communication
Foundation içerisinde de yer alması elbetteki şaşırtıcı değildir.
Nitekim One Way operasyonlar aslında asenkron istemci-sunucu modelininde
önemli bir parçasıdır.
Normal şartlarda Windows Communication
Foundation istemcileri servisten bir talepte bulunduklarında, proxy
tarafından hazırlanan mesaj sunucuya gönderilir. Servis gelen mesajı
alır, çözümler ve gereken yürütme işlemlerini gerçekleştirir. Burada söz
konusu yürütmeye dahil olan metodların çalıştırılmasının sonucunda
istemciye bu işlemin tamamlandığı bilgisi eğer geri dönüş değeri var ise
onunla birlikte döner. Bu, talep/cevap mesajlaşma deseni
(request/response messaging pattern) olarak adlandırılan klasik
çalışma modelidir. Ancak burada istemcinin çağrıda bulunduğu metodun
tamamlanışını beklemesi gerekir. Aksi takdirde ilerlemesi söz konusu
değildir. Burada bahsi geçen konu kod satırında bir alt ifadeye
geçilememesidir. Çok doğal olarak servis tarafındaki metodun
çalışmasının uzun sürdüğü durumlarda istemci uygulama beklemede
olacaktır.
Özellikle istemci tarafındaki
uygulamaların çağrıda bulundukları metodlar geriye değer
döndürmüyorlarsa asenkron programlama (asynchronous programmin)
adına One Way tekniğinden yararlanılabilir. One Way tekniği
uygulanması kolay olmasına rağmen dikkat edilmesi gereken noktalara
sahiptir. İşte bu makalemizde söz konusu noktalara değinerek One Way
tekniğinin WCF açısından detaylarını görmeye çalışacağız.
 |
İstemci programların uzak
metod çağrımlarında uygulamaları duraksatmasını engellemek adına
kullanılabilecek tek yol One Way değildir. Diğer Asenkron
erişim modelleride ele alınabilir. Bunlar ilerleyen
makalelerimizde ele alınacaktır.
One Way ve diğer asenkron modellerinde istemci ve sunucu
uygulamaların aynı zaman diliminde çalışıyor olmaları gerekir.
Bunun aksi bir durumda ise Message Queue sisteminin
kullanılmasında fayda vardır. |
One Way formasyonuna uygun bir çağrım
için OperationContract niteliğinin IsOneWay özelliğine
true değerini aktarmak yeterlidir. OneWay metodlar ile ilişkili
bilinmesi gereken öncelikli kurallar vardır. Herşeyden önce OneWay
olarak işaretlenenen metodlar geri dönüş değerine sahip olmazlar. Bir
başka deyişle bu metodlar void olarak tanımlanırlar. Burada
metoda parametre olarak ref veya out tipinden aktarımlar
yapılmak istenebilir ancak buda mümkün değildir. Diğer taraftan söz
konusu metodlar içerisinde çok doğal olarak istisnalar(Exceptions)
olabilir. Burada söz konusu olan SOAP hata mesajları (SOAP Fault
Message) istemci tarafına gönderilmez. Bu sebeplerden ötürü istemci
servis üzerindeki metodun başarılı bir şekilde tamamlanıp
tamamlanmadığını asla bilemez.
Ancak en azından istemcinin gönderdiği
metod çağrısı mesajının servise ulaşıp ulaşmadığının bilinmesinde yarar
vardır. Eğer servis uygulaması çalışmıyorsa çok doğal olarak istemci bir
istisna alacaktır ki bu durumda istemciden gönderilen talebin ulaşmadığı
zaten doğrudan anlaşılabilir. Ancak bazı iletişim protokollerinde
(örneğin Tcp) gelen mesajlar tampona alınırarak işlenirler. Arka
arkaya gelen bu taleplere ait mesajların toplu olarak bir maksimum
sayısı vardır. Sonuçta birden fazla istemci söz konusudur ve bunların
gönderecekleri sayısız çağrı bulunmaktadır. Böyle bir durumda eğer
servis tarafında kabul edilebilen maksimum talep sayısı aşılırsa gelen
yeni talepler var olan yarım kalmışlar tamamlanıncaya kadar beklemeye
alınır. Dolayısıyla istemci uygulama her ne kadar OneWay çağrısı yapsada
beklemede kalır. Bu durumla başedebilmek için güvenilir oturumlar
(Reliable Session) açılmasında fayda vardır. Güvenilir oturumlar
sayesinde servis, bir çağrı aldığında gelen mesajı işlemeye başladığına
dair istemciye bilgi gönderebilir.
One Way tekniği istemci için önem arz
eden SendTimeout sürelerini önemsemez. Normal şartlarda
istemciler bir metod çağrısında bulunduklarında varsayılan olarak 1
dakikalık bir timeout süreleri vardır. Eğer bu süre içerisinde servisten
bir cevap gelmesse otomatik olarak TimeoutException tipinden bir
çalışma zamanı hatası alınır. One way operasyonlarında çok doğal olarak
bu tip bir süre kontrolü önemli değildir. Nitekim istemci tarafı çağrıda
bulunduğu metod için bir cevap beklememektedir. Ama varsayılan olarak
bazı aksilikler olacaktır ki ilerleyen kısımlarda buna değinmeye
çalışacağız.
Şimdi örnek bir uygulama üzerinden
ilerleyerek One Way tekniğini nasıl ele alabileceğimizi inclemeye
çalışacak ve dikkat edilmesi gereken durumları analiz edeceğiz. Bu
makalemizdeki örneğimizde, file-based olarak web üzerinde barındırılan
bir servis uygulaması yer alacaktır. İstemciyi olayları kolay bir
şekilde takip edebilmek adına bir konsol uygulaması olarak
tasarlayabiliriz. Burada diğer makalelerimizden farklı olarak
wsHttpBinding bağlayıcı tipini ele alacağız. Bu tip aslında
BasicHttpBinding bağlayıcı tipine benzerdir ancak güvenilir
oturumlara (reliable sessions) sahip, transcation
yönetimine izin veren Http ve Https iletişim
protokollerinin kullanılabildiği, WS-Adressing işlemlerin
yapılabildiği bir ortam sunarak ekstra imkanlar sağlar. Geliştirilecek
servis uygulaması için WCF Service şablonu kullanılabilir. Bu
amaçla ilk olarak Visual Studio 2005 ile aşağıdaki gibi bir servis
uygulaması açarak işe başlanmalıdır. WCF Service uygulaması file-based
olarak host edileceğinden ve istemcilerin tek bir adresten ilgili
servise erişmeleri istendiğinden projenin Properties penceresindeki
özelliklerden port numarası sabit bir değere ayarlanabilir. Bu işlem
için öncelikle Dynamic Ports özelliğine false değer atamak
gerekir.

Servisimiz için gerekli tiplerimizi ise
aşağıdaki gibi geliştirebiliriz. Söz konusu tipler App_Code
klasörü içerisinde yer almaktadır.

IRaporUretici Arayüzü İçeriği;
[ServiceContract(Name = "RaporlamaServisi", Namespace =
"http://www.bsenyurt.com/RaporlamaServisi/2007/30/05")]
public interface IRaporUretici
{
[OperationContract(IsOneWay
= true)]
void RaporUret(string kullaniciAdi);
[OperationContract(IsOneWay
= true)]
void SatisYapildi(int productId);
} |
RaporUretici sınıfı içeriği;
public class
RaporUretici
:
IRaporUretici
{
#region IRaporUretici Members
public void RaporUret(string kullaniciAdi)
{
Thread.Sleep(65000);
// 1 dakika 5 saniye duraksatma
FileStream fs = new
FileStream("C:\\Izleme.txt", FileMode.Append, FileAccess.Write);
StreamWriter writer = new
StreamWriter(fs);
writer.WriteLine(kullaniciAdi + "
İÇİN RAPOR ÜRETME EMRİ VERİLDİ");
writer.Close();
fs.Close();
}
public void SatisYapildi(int productId)
{
Thread.Sleep(65000);
// 1 dakika 5
saniye duraksatma
FileStream fs = new
FileStream("C:\\Izleme.txt", FileMode.Append, FileAccess.Write);
StreamWriter writer = new
StreamWriter(fs);
writer.WriteLine(productId + " ÜRÜNÜ
İÇİN SATIŞ YAPILDI");
writer.Close();
fs.Close();
}
#endregion
} |
Arayüz tanımlaması içerisinde dikkat
edilecek olursa OperationContract niteliğinin IsOneWay
özelliğine true değeri atanmıştır. Servis sözleşmesini uygulayan
sınıf içerisinde sembolik olarak iki metod yer almaktadır. Özellikle bu
metodların içerisinde Thread sınıfının static Sleep metodu
yardımıyla uygulama 65 saniye duraksatılmaktadır. Burada 1 dakikalık
TimeOut sınırının aşılmasının doğuracağı bazı sonuçlar olacaktır. Bu
sonuçlar ilerleyen kısımlarda ele alınacaktır. Servis tarafında yer alan
web.config dosyasının içeriği aşağıdaki gibi tasarlanabilir.
web.config içeriği;
<?xml
version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service
behaviorConfiguration="RaporlamaServisiBehavior"
name="RaporlamaServisi.RaporUretici">
<endpoint
address="http://localhost:2215/RaporlamaServisi/Service.svc"
binding="wsHttpBinding" bindingConfiguration=""
name="RaporlamaServisiEndPoint"
contract="RaporlamaServisi.IRaporUretici" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="RaporlamaServisiBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.web>
<compilation debug="true"/>
</system.web>
</configuration> |
Servis web tabanlı olarak host
edildiğinden svc uzantılı bir dosyanında var olması
gerekmektedir. Bu dosyanın içeriğinde servis sözleşmesini uygulayan
sınıfın adı ve fiziki dosya adı aşağıdaki gibi yer alır.
Service.svc;
| <%
@ServiceHost Language=C# Debug="true"
Service="RaporlamaServisi.RaporUretici"
CodeBehind="~/App_Code/Service.cs"
%> |
Servis ile ilgili işlemlere geçmeden
önce çalıştığından emin olmakta fayda vardır. Servis başarılı bir
şekilde hazırlanmışsa aşağıdaki ekran görüntüsünün elde edilmesi
gerekir.

Artık istemci için gerekli kodlar
yazılıp testlere başlanabilir. Öncelikli olarak istemci uygulamalar için
gerekli proxy tipinin üretilmesi gerekir. Bunun için komut satırında
(Visual Studio 2005 Command Prompt) svcutil.exe aracı
kullanılabilir yada Visual Studio 2005 ortamında konsol uygulamasında
Add Service Reference seçeneği ile aşağıdaki ekran görüntüsünde
olduğu gibi eklenebilir.

Bu işlemin ardından istemci
uygulamasına ait proje içerisinde gerekli proxy tipi ve App.config
konfigurasyon dosyası üretilmiş olacaktır.

İstemci uygulamaya ait kodlar aşağıdaki
gibi geliştirilebilir.
using System;
using System.Text;
using
System.ServiceModel;
using System.Collections.Generic;
using
Istemci.localhost;
namespace Istemci
{
class Program
{
static void Main(string[] args)
{
try
{
RaporlamaServisiClient srv = new
RaporlamaServisiClient("RaporlamaServisiEndPoint");
Console.WriteLine("Rapor üretimini başlat..." +
DateTime.Now.ToString());
srv.RaporUret("Mayk");
Console.WriteLine("Rapor üretimi başlatıldı..." +
DateTime.Now.ToString());
Console.WriteLine("Ürün satışı yapıldı bilgisini gönder..." +
DateTime.Now.ToString());
srv.SatisYapildi(1001);
Console.WriteLine("Ürün satışı yapıldı bilgisi gönderildi..." +
DateTime.Now.ToString());
srv.Close();
}
catch (Exception
hata)
{
Console.WriteLine(hata.Message);
}
}
}
} |
RaporlamaServisiClient nesnesi
örneklendikten sonra RaporUret ve SatisYapildi isimli metodlar
çağırılmaktadır. Bu metodları işaret eden servis sözleşmesinde OneWay
oldukları belirtilmiştir. Buna göre istemci uygulamanın, bu metodlar
içerisindeki 65 saniyelik sürelerden etkilenmeden diğer kod satırlarını
işletmesi gerekmektedir. Bakalım gerçekten böyle mi olacak?
Testleri yapabilmek için hem sunucu
uygulamanın hemde istemci uygulamanın aynı zaman diliminde çalışıyor
olmaları gerekmektedir. Dolayısıyla Solution özelliklerinde
Multiple Startup Projects seçilmeli ve önce servis uygulaması
ardından istemci uygulama çalışacak şekilde ayarlanmalıdır.

Bu aşamadan sonra uygulama
çalıştırılırsa ilk etapta aşağıdaki gibi bir ekran görüntüsü ile
karşılaşılır.

Görüldüğü gibi RaporUret çağrısı
kolayca aşılmış ancak, SatisYapildi çağrısından sonra istemci
uygulama ekranı duraksamıştır. Oysaki ikinci metodda OneWay
olarak çağrılmaktadır. Dolayısıyla aynen ilk metod çağrısında olduğu
gibi buradada istemci uygulamanın diğer kod satırlarından işlemlerine
devam etmesi beklenir. Ne varki böyle olmamıştır. Sonuç olarak bir süre
bekledikten sonra aşağıdaki ekranda görülen hata mesajı ile
karşılaşılır.

Peki sorun nedir? İstemci uygulama
neden çalışma zamamında bir istisna alarak sonlanmıştır? Hatta yeterli
süre beklenildiğinde sunucu tarafında Izleme.txt dosyasının
içeriğine bakıldığında metod içeriklerinin çalıştığıda gözlemlenebilir.

Ne varki istemci açısından bazı
sorunlar olduğu ortadadır. Problemin nedeni oturumlardır (Sessions).
Aynı oturum içerisinde gelen arka arkaya iki çağrı söz konusudur. Bu
çağrılar doğal olarak aynı andalık ilkesine (Concurrency) göre
değerlendirilir. Dolayısıyla ikinci çağrıdan sonra istemci uygulama, ilk
çağrı sonucunun tamamlanmasını beklemek durumunda kalmıştır. Bu sebepten
servisin özellikle aynı oturum içerisinden gelecek eş zamanlı metod
çağrılarına cevap verebilecek şekilde özelleştirilmesi gerekir. Burada
elebetteki Session moddan vazgeçilmesi tercih edilebilir. Örneğin
PerCall mode seçilebilir. Ancak oturumların (Sessions)
kullanım amaçları göz önüne alındığında bir çözüm yolu bulunmasında
fayda vardır. Yapılması gereken servis sözleşmesini uygulayan
RaporUretici sınıfına, ServiceBehavior niteliğini uygulamak ve
ConcurrencyMode özelliğine Multiple değerini aşağıdaki gibi
vermektir.
namespace
RaporlamaServisi
{
[ServiceBehavior(ConcurrencyMode= ConcurrencyMode.Multiple)]
public class RaporUretici
: IRaporUretici
{ |
Uygulamamızı bu haliyle test
ettiğimizde ise aşağıdaki ekran görüntüsü ile karşılaşırız.

Herşey ilk etapta yolunda gibidir.
Nitekim SatisYapildi metod çağrısı sonrasındaki kodlarda çalışmıştır.
Ancak uygulama kapanırken yine bir hata mesajı alınmıştır. Bu hata
mesajının üretildiği nokta istemci tarafında servis için Close
metodunun çağrıldığı yerdir. Bu çağrıya gelindiğinde istemci uygulama
uzun bir süre beklemede kalmıştır. Sonrasında ise bir istisna mesajı
fırlatarak sonlanmıştır. Bunun sebebi kullanılan WsHttpBinding tipinin
özellikleridir. WsHttpBinding oturumları kullanan ve varsayılan
olarak mesaj seviyesinde güvenlik (Message-Level Security)
kullanan bir bağlayıcı (Binding) tipidir. İstemci Close metodunu
çağırdığında servis tarafında kendisi için açılan oturumu(Session)
kapatmak ister. Buna karşılık servis ilgili oturuma ait işlemlerin
bitmesini bekler ve tamamlandıklarından emin olduktan sonra bunu
istemciye bir mesaj ile bildirir. Örnekte çok doğal olarak servis
tarafındaki işlemler 1 dakika sınırını aştığından, söz konusu mesaj
istemciye iletilemez. Buda doğal olarak istemci tarafında bir istisna
mesajı fırlamasına neden olur. Çözüm olarak güvenlik ile ilgili ayarlar
kapatılabilir ki bu önerilen bir yöntem değildir. Diğer bir yöntem ise
iletişim seviyesinde güvenlik (transport levet security)
kullanmaktır. Ancak bu yöntemde sertifika kullanılması gerekir nitekim
Https politikası söz konusudur.
Ancak mesaj seviyesinde yapılabilecek
bir seçenek daha vardır. Buda güvenilir bir oturum (Reliable Session)
açmaktır. Nitekim bu sayede istemcinin yaptığı çağrılar sonucu servisten
bir bilgi beklenmesine gerek kalmayacaktır. Bunun için servis tarafında
ve istemci tarafında wsHttpBinding tipi için konfigurasyon
ayarları yapılmalı ve ReliableSession için Enabled
özelliklerine true değeri atanmalıdır. Aşağıdaki ekran
görüntüsünde servis tarafı için ilgili değişikliklerin Microsoft
Service Configuration Editor yardımıyla nasıl yapıldığı
gösterilmektedir.

Bu değişiklikler sonucu servis tarafı
için konfigurasyon dosyasının içeriği aşağıdaki gibi olur.

Benzer değişikliklerin istemci tarafı
içinde yapılması gerekir. Bunun sonucu olarak istemci tarafındaki
konfigurasyon dosyasındada aşağıdaki değişiklikler olacaktır.

Artık uygulamımızı bu haliyle test
edebiliriz. Aşağıda uygulamanın son halinin test sonuçlarına ait ekran
görüntüsü yer almaktadır.

Sonuç itibariyle basit bir One Way
Ticket şarkısından oldukça farklı noktalara geldik. Bu ana kadar
gördüklerimizden aşağıdaki sonuçları çıkartabiliriz.
- OneWay tekniği ile Windows
Communication Foundation uygulamalarında asenkron çağırımlar
gerçekleştirilebilir ve performans artışı sağlanır. Çünkü
istemci uygulama, servis tarafındaki metod sonuçlarını beklemeden
yoluna devam eder.
- Günvenilir oturumlara (Reliable
Sessions) izin verilmesi halinde istemci tarafında Close
metodu uygulandığında servis ile olan bağlantı(Connection),
servisten cevap beklenmeden sonlandırılabilir.
- Özellikle oturum(Session)
kullanıldığı durumlarda servis üzerinde aynı oturuma ait arka arkaya
metod çağırımlarında, istemci uygulamanın duraksamasını engellemek
adına ConcurrencyMode özelliğinin değeri Multiple
olarak set edilebilir.
- ConcurrencyMode özelliğinin
Multiple olarak belirlenmesi halinde servisin gerçektende
thread-safe olup olmadığına dikkat edilmelidir. Nitekim Multiple
değeri ile, servis tarafındaki uygulama Multi-Thread hale
gelmektedir.
Bu makalemizde asenkron programlama
çeşitlerinden birisi olan One Way metod çağırım tekniğini incelemeye
çalıştık. Asenkron programlamaya ilişkin başka örnekleri ilerleyen
makalelerimizde incelemeye çalışacağız. Böylece geldik bir
makalemizin daha sonuna. Bir sonraki makalemizde görüşünceye dek
hepinize mutlu günler dilerim.
Örnek Uygulama İçin
Tıklayınız.Burak Selim ŞENYURT
selim@bsenyurt.com
Makale:
WCF - One Way Ticket .NET 3.0 ve .NET 3.5 Özel Bölümü Burak Selim Şenyurt
|
|
Bu konu hakkında yayınlanan yorum bulunmamaktadır.
"Yorum Yaz" tabını kullanarak sizde yorumlarınızı yazabilirsiniz.
|
|
|
|
|
|
|
-
-
Eklenen Son 10
-
Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
|
|
|