AvtiveMQ ile Uygulama Gelistirme

Büyük projelerde sisteminiz çeşitli alt modüllerden hatta çeşitli alt uygulamalardan oluşacaktır. Eğer projeniz alt modüllerden oluşuyorsa, modüllerin haberleşmesini sağlamak göreceli olarak daha kolaydır. En basitinden bir Observer Pattern ile modüllerinizin haberleşmesini sağlayabilirsiniz. Fakat projeniz alt modüllerden değilde alt uygulamalardan oluşursa Observer pattern gibi yapılar sizi kurtarmayacaktır. Bu gibi durumlar için çeşitli çözümler üretilmiştir. Bu tip çözümler yazılım alanında prosesler araşı haberleşme (Inter process communication) başlığı altında incelenmektedir. Mesajlaşma kuyruğu ise bu çözümlerin bir tanesidir.

Genel olarak her şirket prosesler arası haberleşme için kendi çözümünü kullanmaktadır. Kimi bellek alanları üzerinden haberleşme yaparken kimi kolaya kaçıp veritabanı ya da dosyalar üzerinden bu haberleşmeyi sağlamaktadır. Kimi de Mesaj kuyrukları kullanmaktadır. Java içerisinde mesajlaşma ile haberleşme için JMS API’ı geliştirilmiştir. JMS API’ı, JSR 914 standardı baz alınarak hazırlanmıştır.

[pullquote3 quotes=”true” align=”left”]ActiveMQ JSR 914 standardı baz alınarak oluşturulmuş bir JMS kütüphanesidir. [/pullquote3]

ActiveMQ bu standart baz alınarak oluşturulmuş bir JMS kütüphanesidir. Genel olarak sistemden ayrı şekilde kurulmu yapılarak kullanılır. Yani nasıl veritabanını ayrı bir sunucuda ya da aynı makinede bile olsa ayrı bir proses içerisinde ayağa kalkıyorsa aynı şekilde ActiveMQ’nunda ayrı bir proses ile ayağa kaldırılması gerekir. Tabi bu bahsettiğim yoğun şekilde ActiveMQ kullanıldığı yani bir çok prosesin farklı ya da aynı kuyruklar üzerinden haberleştiği durumlar için geçerli. Benimse bu yazıda bahsetmek istediğim, daha ufak projelerde ActiveMQ’nun uygulamanıza nasıl gömebileceğiniz.

ActiveMQ‘yu projeniz içerisine nasıl gömebileceğinize geçmeden önce, biraz Mesajlaşma kuyruklarının mantığından bahsetmek istiyorum. Öncelikle alışık oludğunuz Client-Server mantığını bir kenera bırakmanızı öneririm. Evet, ayrı bir sunucu üzerinde koşuyorsa sanki esas nokta sunucu, bu sunucuya bağlanan diğer proseslerde istemci gibi görünüyor fakat mantığı tam olarak bu şekilde çalışmıyor.  Mesajlaşma kuyruklarında üç farklı katılımcıdan bahsetmek daha doğru olur.

  • Broker – Server olarak düşündüğünüz kısma karşılık geliyor. Tüm mesajlaşma kuyrukları bu broker denen yapılar üzerine kuruluyor. Eğer bir mesaj gönderecekseniz ya da alacaksanız borkerlar üzerinden yapıyorsunuz.
  • Provider – Mesaj sağlayıcısı olarak düşünebilirsiniz. Borker içerisindeki bir mesaj kuyruğuna mesaj bırakan proseslerdir.
  • Consumer – Mesajları kullanan proseslerdir.

Tabi her proses sadece Provider ya da Consumer olmak durumunda değil. Her ikisi birden olabilir ya da farklı mesaj kuyruklarında farklı görevler üstlenebilirler. ActiveMQ‘yu ayrı bir proses olarak kurduğunuzda, otomatik olarak Broker görevini üstlenmeye başlıyor. Benim bu yazımda anlatacağım, ActiveMQ’nun uygulamanıza gömülü olarak kullanılması ise, Borker’ın uygulama tarafından ayağa kaldırılması olacaktır. Örnekteki gibi ille gömülü bir broker kullanmanız gerekmiyor. İsterseniz sadece Provider ve Consumer kısımlarını kullanı

Gömülü ActiveMQ

Gömülü ActiveMQ derken Borker’ın uygulama içerisinde ayağa kaldırılacağını söyledikten sonra artık uygulamamızı geliştirmeye geçebiliriz. Örneği basit olması açısından tek bir proje olarak geliştireceğim. Fakat proje içerisinde farklı uygulamalar yani main foksiyonları ile çalışacağımızdan tüm etkiyi yaratmış olacağız. Ben örneği gerçeklerken Maven, Eclipse Indigo ve ActiveMQ kullanacağım.

Giris

Öncelikle Maven projemizi yaratalım ve bağımlılıklarımızı projemize ekleyelim. Maven’in quickstart archetype’ını kullanarak aşağıdaki özelliklerle projenizi oluşturunuz.

  • Group ID: com.bahadirakin
  • Artifact ID: activemq-test
  • Paket Adı: com.bahadirakin.jms

Şimdi ise pom.xml dosyanızı aşağıdaki gibi, ActiveMQ bağımlılıklarını içerecek şekilde güncelleyiniz.

pom.xml
Şimdi doğal olarka aklınıza bu kadar exclusion’ın neden olduğu sorusu gelecektir. Peşinen söyleyeyim, activemq kuyrukları tutumak için farklı farklı yapılar kullanmaktadır. Bu farklı kuyruklar mesajların işlenişi ve mesajların kaybolmayışı açısından farklılıklar yaratmaktadır. Bunlar biraz daha ileri konular olduğundan burada değerlendirmeyeceğim. Fakat yazıyı okuyup, ActiveMQ ile bir örneği başarıyla yapıp, temel yapısını anladıktan sonra projenizde kullanmadan önce farklı mesaj kuyruğu yapılarını incelemenizi öneririm. Yine aynı şekilde Sprin ile entegre halde gelmektedir. Eğer gömülü olarak kullanacaksanız ve ayarlarınızı spring üzerinden yapmayacaksanız hiç bir şekilde ihtiyacınız olmayacaktır. Bana kalırsa sadece ayar yapmak için Spring kullanmakta çok mantıklı gelmiyor. Ne kadar olmasada bir CDI yapısının uygulamayı yavaşlatacağını düşünüyorum. Burada kullanacağım sınıfları doğrudan ActiveMQ sitesinden aldım. Benim tek yaptığım bunları gömülü bir broker sınıf ile çalıştırmak oldu. Şimdi sırayla Consumer, Producer ve Broker sınıflarımızı oluşturalım.

Consumer

Projemizde Borker ve Consumer’ı bir uygulamadan ayağa kaldıracağım.  Bunun için öncelikle Consumer sınıfını hazırlayalım.  İleride Borker sınıfını yazdığımda, önce borker sınıfını ayağa kaldırıp ardından consumer’ı ayağa kaldıracağım. Consumer sınıfı durmadan belirli bir kuyruğu dinleyip gelen mesajı ekrana basacak. Yani basit bir Hello World uygulması hazırlanacak. ActiveMQ sitesindeki örnekten faydalanarak hazırladığım Consumer sınıfı aşağıdaki gibidir.

HelloWorldConsumer.java

Burada öncelikle değinmek istediğim noktalar var. ActiveMQ kullanarak bağlantı oluştururken, adres olarak “vm://localhost” kullanıyorum. Bu şu anlama geliyor kullanacağım Broker aynı JVM’de çalışıyor ve Borker’ın adı localhost. Consumer sınıfı yazarkende belirttiğim gibi broker ve consumer sınıfları aynı uygulama içerisinden ayağa kalkacaklar. Bura da bunu zorunlu kılmış oluyor. Eğer aynı JVM içerisinden ayağa kalkmazlar’sa bağlantı hatası alacağız. Tabi bağlanmanız için aynı sanal makinede olması gerekmiyor. TCP üzerinden bağlantıda mümkün. Bunun bir örneğini birazdan Producer sınıfında göreceğiz. Ama TCP bağlantıları kullanılacaksa Broker sınıfına TCP bağlantısının eklenmesi gerekecektir.

[pullquote3 quotes=”true” align=”right”]Eğer isterseniz Producer ve Consumer sınıflarını, bağlantı adreslerini değiştirerek, gömülü olmayan ActiveMQ sistemlerinde de kullanabilirsiniz.[/pullquote3]

Diğer değinmek istediğim kısım ise kuyruk adı. Biz kuyruk adı olarak TEST.FOO adını kullandık. Buraya gelecek her metin mesajını dinliyoruz. ActiveMQ’nun güzel yanı kuyrukları istek doğrultusunda yaratmasıdır. Bazı JMS çözümleri broker sınıfınızı oluştururken kuyruklarınızı belirtmenizi istemektedir, fakat ActiveMQ’da böyle bir zorunluluğunuz yok. Tabi isterseniz baştan da oluştrabilirsiniz. ActiveMQ TEST.FOO kuyruğunun olup olmadığına bakar eğer yoksa yeni bir kuyruk açar.

Producer

Consumer sınıfından hemen sonra Producer sınıfını açıklamamın iki temel sebebi var. Birincisi consumer ve producer sınıflarının bir birine çok benzemesi. Yani burdaki “çok benzeme” kısmından kastettiğim InputStream ile OutputStream ne kadar benziyorsa okadar benzediği.

Producer sınıfımız metin mesajları üretmektedir. Consumer sınıfının aksine bir tek metin mesajı üreterek işlemini sonlandırmaktadır. JMS kullanmanın bir güzelliği ise sadece Metin mesajları üretmek zorunda değilsiniz. İstediğiniz bir POJO sınıfını mesaj olarak gönderebilirsiniz. Buradaki tek kısıtlama göndereceğin POJO sınıfının Consumer tarafında da bulunmasıdır.

HelloWorldProducer.java
Burada gördüğünüz üzere bağlantı kurarken TCP protokolünü kullandık. Yine consumer sınıfının bağlı olduğu kuyruğa mesajlarımızı koyuyoruz. Aksi halde mesajlar consumer sınıfına iletilmeyecekir. Şimdi hem Producer hem de Consumer sınıflarımızı hazırladığımıza göre broker sınıfımızı yazmaya geçebiliriz.

Broker

Broker sınıfımız basit ve ufak bir sınıf olacak. Burada yapmamız gereken borker adını vermek, bağlantı araçlarını belirlemek, mesajların ne şekilde okunacağını belirlemek yani kısaca broker ayarlarımızı yapmak olacaktır. Ardından borker’ımızı çalıştıracağız ve herşeyin işleyişini göreceğiz. Broker.java
Burda broker’ımızı ayarladık. Borker’ımıza isim olarak localhost verdik, ki Consumer sınıfımız bu isim üzerinden bağlantı yapacak, ayrıca TCP için bağlantı portu ekledik, ki Producer sınıfımızda bu port üzerinden iletişim kuracaktır. Ayrıca Consumer sınıfımızı da borker’ı başlatır başlatmaz çalışacak şekilde ayarladık. Artık geriye kalan tek şey programımızı başlatmak olacak.

Program Akısı

Şimdi adım adım program akışının nasıl olacağını görelim. Bildiğiniz üzere iki farklı programımız var bunlardan biri Broker + Consumer diğeri Producer olarak çalışıyor.

  1. Broker uygulaması çalıştırılır.
  2. Borker ayarları yapıldıktan sonra ayağa kalkar.
  3. Borker ayağa kalkar kalkmaz bir tane Consumer sınıfı yaratılır.
  4. Yaratılan bu Consumer nesnesi ayrı bir Thread üzerinde çalıştırılır.
  5. Consumer sınıfı 5 saaniye timeout ile mesaj bekler.
  6. Eğer mesaj gelmezse “Waiting For message” yazısı ile tekrardan beklemye başlar. Bu her 5 saniyede bir tekrarlanır.
  7. Eğer mesaj gelirse, gelen mesajı alır. Eğer mesaj Metin mesajı ise, gelen mesajı ekrana basar ve beklemeye devam eder.

Bu akış sonsuz bir döngü içerisinde böyle sürüp gitmektedir. Producer sınıfı ise ayağa kalkar ve Hello World mesajı gönderirir. Mesaj içerisinde ayrıca thread id bilgisinide göndermektedir. Böylelikle mesajın ayrı bir uygulamadan geldiği netleşmiş olur.

Son

Umarım JMS ve ActiveMQ üzerinde biraz da olsa fikir sahibi olmanıza yardımcı olabilmişimdir. Tahmin edeceğiniz gibi tek JMS çözümü ActiveMQ değil. OpenMQ gibi ya da JBossMQ gibi başka JMS çözümleride mevcut. Fakat en çok tavsite edilecen çözümlerin başında ActiveMQ geliyor. Özellikle Enterprise Integration Patterns ile çalışmalar yapacaksınız ActiveMQ ve Camel ikilisini tavsiye ederim.

End Of Line