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.
- Broker uygulaması çalıştırılır.
- Borker ayarları yapıldıktan sonra ayağa kalkar.
- Borker ayağa kalkar kalkmaz bir tane Consumer sınıfı yaratılır.
- Yaratılan bu Consumer nesnesi ayrı bir Thread üzerinde çalıştırılır.
- Consumer sınıfı 5 saaniye timeout ile mesaj bekler.
- EÄŸer mesaj gelmezse “Waiting For message” yazısı ile tekrardan beklemye baÅŸlar. Bu her 5 saniyede bir tekrarlanır.
- 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