17 Mayıs 2007 Perşembe

MS Message Queue ile Asenkron Programlama

Birden çok programı asenkron konuşturmak gerekirse ne yaparsınız?  Bir sunucu üzerinde veriyi çekeceksiniz başka bir sunucu ile o veriye ait hesaplamaları yapacaksınız üçüncü bir sunucu ile yeni iş süreçleri oluşturup farklı sistemleri ve kişileri haberdar edeceksiniz. Tüm bu sistem tamamen birbirinden yalıtılmış ve tamamen asenkron olması gerekiyorsa ne yapmalısınız?

MSMQ en basit çalışma yapısı şekilde gösterildiği gibidir. Birçok iş uygulamasında uzak sistemler arasında sender-reciver mantığı ile çalışan haberleşme mekanizmalarına sahiptir. Dağınık programlar arasında ki veri iletişimi MS Message Queue (MQ) ile yapılabilmektedir. MQ programların birbirleri ile asenkron haberleşmek için kullanabilecekleri bir FIFO kuyruktur. ObjectFormater nesnesini desteklediği için object remoting içinde kullanılabilir. Transaction desteğinden server cluster desteğine kadar iş ihtiyaçlarını karşılayabilecek güçlü bir yapıya sahiptir.
MQ işlemleri System.Messaging isim uzayı kullanılır. Kodlama ile bir kuyruk açabilir, kuyruğa yeni mesajlar ekleyebilir ve sıra ile mesajları okuyabilirsiniz.
MessageQueue nesnesine üzerinden çalışılacak message path ve formater'ı vermelisiniz.

[cs]
// eğer messageQ yoksa oluştur
if (!MessageQueue.Exists(this.SMSQInfo.QPath)) {
 MessageQueue.Create(this.SMSQInfo.QPath, true);
}
smsQ = new MessageQueue();
smsQ.Path = this.SMSQInfo.QPath;
((XmlMessageFormatter)smsQ.Formatter).TargetTypeNames = 
 new string[] { "System.String,mscorlib" };
Artık oluşturduğumuz MQ üzerine yeni mesajlar ekleyebiliriz. Send edilen bir mesajın reciver kuyruk tarafından alınması için reciver olarak kullanılan makinada MQ servisinin açık olması gerekmektedir. Eğer reciver kapalı ise veya send işleminde sorun cıkarsa mesajınız kaybolmamalıdır. Bu ihtiyaçtan dolayı MQ transaction yapıyı desteklemektedir.
Bir Message nesnesi oluşturalım daha sonra MessageQueue nesnemize transaction ile Send() edelim.
[cs]
MessageQueueTransaction messageTransaction = new MessageQueueTransaction();
Message message = new Message();
message.Formatter = new System.Messaging.XmlMessageFormatter();
message.Label = smsLabel.ToString();
message.Body = smsBody;
messageTransaction.Begin();
try {
 smsQ.Send(message, messageTransaction);
 messageTransaction.Commit();
} catch (MessageQueueException) {
 messageTransaction.Abort();
 throw;
}
smsQ.Close();
return message.Id;
Şimdi bir kuyruğu dinleyelim ve yeni bir mesaj geldiğinde kuyruktan çekelim ve işledikten sonra tekrar bir sonraki mesajı bekleyelim. Böylelikle bir mesajı işlerken bu kuyruğa mesaj gönderen uygulama sonucuyu beklememektedir. Her iki uygulama arasında kurmamız gereken asenkron işlem mantığını sağlamış olduk.
[cs]
#region start stop listen q
public void StartListenQueue() {
 smsQ.ReceiveCompleted += 
  new ReceiveCompletedEventHandler(smsQ_ReceiveCompleted);
 smsQ.BeginReceive();
}
bool _isStopReceive;
void smsQ_ReceiveCompleted(object sender, ReceiveCompletedEventArgs e) {
 Message m = smsQ.EndReceive(e.AsyncResult);
 m.Formatter = new XmlMessageFormatter(
  new string[] { "System.String, mscorlib" });
 if (SMSQReceived != null)
  SMSQReceived(this, m);
 // bir sonrakini bekle
 if (!_isStopReceive) {
  smsQ.BeginReceive(); 
 }
}
public void StopListenQuese() {
 _isStopReceive = true; 
}
#endregion
Bugün: Asenkron programlama için MQ çok basit ve kullanışlı bir yoldur. Mevcut .net 2.0 teknolojisinde asenkron veri iletişiminde çözüm MS Message Queue haberleşmesidir.
Gelecekte: Bu yöntemde programcı tüm iş akışından sorumludur ve akışı adım adım izlemek gibi bir şansı yoktur. Yeni tüm programlar kendi başlarına çalışırlar. .net 3.0 ile hayatımıza girecek olan BPEL ile artık bu tür iş uygulamalarımızda tüm otomasyonu çalıştırmak bir üst programın sorumluluğunda olacaktır. BPEL bir workflow uygulaması tek farkı tüm işlemlerini WCF ile web servisler üzerinde yapmasıdır. WCF ise gene asenkron ve connectless iletişim için MSMQ kullanmaktadır.
İki ayrı sistem arasında MSMQ ile haberleşecekseniz tabii ki bir standart belirlemeniz gerekmektedir. Bir Dispacher nesnesini ve veri tanımlama standartı oluşturmanıza ihtiyacınız var.