Gereksinimler ve Ön Hazırlık
JMS ile çalışmaya başlamadan önce geliştirme ortamınızı doğru yapılandırmanız gerekir. JMS bir API olduğu için arka planda bir mesaj broker'ına ihtiyaç duyar.
- JDK 21 veya üzeri bir sürüm.
- Apache ActiveMQ Artemis veya benzeri bir JMS uyumlu broker.
- Maven veya Gradle tabanlı bir Java projesi.
- Bağımlılık yönetimi için
jakarta.jms-apive ilgili broker istemci kütüphaneleri.
Projenizin pom.xml dosyasına aşağıdaki bağımlılığı ekleyerek işe başlayabilirsiniz:
jakarta.jms
jakarta.jms-api
3.1.0
org.apache.activemq
artemis-jms-client
2.35.0
JMS Mimarisi ve Temel Kavramlar
JMS, iki ana iletişim modeli sunar: Point-to-Point (PTP) ve Publish/Subscribe (Pub/Sub). PTP modelinde bir mesaj tek bir alıcıya giderken, Pub/Sub modelinde bir konu (topic) üzerinden birden fazla aboneye iletilir.
| Kavram | Açıklama | Kullanım Amacı |
|---|---|---|
| Queue | Noktadan noktaya mesaj kuyruğu | İş yükü dağıtımı (Load Balancing) |
| Topic | Yayınla/Abone ol modeli | Olay tabanlı bildirimler (Event Notification) |
| ConnectionFactory | Broker bağlantısı oluşturma aracı | Güvenli bağlantı yönetimi |
| Session | Mesaj gönderim/alım bağlamı | İşlem (Transaction) yönetimi |
Adım Adım Mesaj Gönderici (Producer) Oluşturma
Mesaj gönderici, bir mesajı belirli bir kuyruğa (Queue) ileten bileşendir. Öncelikle bir ConnectionFactory oluşturmalı ve ardından oturumu başlatmalısınız.
import jakarta.jms.*;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
public class MesajGonderici {
public void mesajGonder(String metin) throws Exception {
ConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:61616");
try (Connection connection = cf.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) {
Queue queue = session.createQueue("testKuyrugu");
MessageProducer producer = session.createProducer(queue);
TextMessage message = session.createTextMessage(metin);
producer.send(message);
System.out.println("Mesaj gönderildi: " + metin);
}
}
}
Yukarıdaki kodda try-with-resources yapısı kullanılarak bağlantıların otomatik kapatılması sağlanmıştır. Bu, kaynak sızıntılarını (memory leak) önlemek için kritik bir uygulamadır.
Adım Adım Mesaj Alıcı (Consumer) Oluşturma
Mesaj alıcı, kuyruktaki mesajları dinler ve işler. Mesajları senkron veya asenkron olarak alabilirsiniz. Aşağıdaki örnekte asenkron bir dinleyici yapısı gösterilmiştir.
public class MesajAlici implements MessageListener {
public void dinlemeyeBasla() throws Exception {
ConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = cf.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue("testKuyrugu");
MessageConsumer consumer = session.createConsumer(queue);
consumer.setMessageListener(this);
connection.start();
}
@Override
public void onMessage(Message message) {
try {
if (message instanceof TextMessage textMessage) {
System.out.println("Alınan mesaj: " + textMessage.getText());
}
} catch (JMSException e) {
e.printStackTrace();
}
}
}
MessageListener arayüzü, mesaj geldiğinde tetiklenen onMessage metodunu zorunlu kılar. Bu yöntem, uygulamanızın sürekli olarak mesajları beklemesini ve geldiklerinde işlem yapmasını sağlar.
JMS Mesajlaşmada İşlem (Transaction) Yönetimi
Mesajların kaybolmaması veya mükerrer işlenmemesi için işlemler (transactions) kullanılır. Bir mesajın başarıyla işlenmesi için session.commit() çağrılmalıdır.
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
try {
// Mesaj işlemleri
producer.send(message);
session.commit();
} catch (Exception e) {
session.rollback();
}
İşlem yönetimi, hata durumunda mesajın kuyruğa geri dönmesini sağlar. Bu, veri tutarlılığı için vazgeçilmez bir mekanizmadır.
Kritik Güvenlik Uyarısı: Üretim ortamlarında (production) mesaj broker'ına bağlantı kurarken mutlaka kullanıcı adı ve şifre kimlik doğrulaması kullanın. Asla varsayılan (default) kimlik bilgilerini değiştirmeden kullanmayın ve bağlantılarınızı SSL/TLS ile şifreleyin.
Sıkça Sorulan Sorular
JMS ile AMQP arasındaki fark nedir?
JMS, Java dünyasına özel bir API standardıdır. AMQP (Advanced Message Queuing Protocol) ise dil bağımsız, ağ seviyesinde bir protokoldür. JMS, AMQP destekleyen broker'lar ile de çalışabilir.
Mesaj kuyruğu dolarsa ne olur?
Kuyruk dolduğunda broker'ın yapılandırmasına bağlı olarak mesajlar reddedilebilir (producer block) veya en eski mesajlar silinerek yer açılabilir. Bu durumu izlemek için broker metriklerini takip etmelisiniz.
Asenkron mesajlaşmanın avantajı nedir?
Sistemler arasındaki bağımlılığı (coupling) azaltır. Gönderici, alıcının o an müsait olup olmadığını bilmek zorunda değildir; mesaj broker'da güvenle saklanır.
JMS yerine neden Kafka kullanmalıyım?
Kafka, çok yüksek hacimli veriler ve olay akışı (event streaming) için optimize edilmiştir. JMS ise daha çok kurumsal iş süreçleri ve geleneksel mesajlaşma ihtiyaçları için idealdir.
Mesaj kaybını nasıl önlerim?
Mesajları "Persistent" (kalıcı) olarak işaretleyin ve işlem yönetimini (transaction) düzgün bir şekilde yapılandırın.
JMS Uygulamalarında Performans Optimizasyonu
Mesaj kuyruğu tabanlı sistemlerde yüksek trafik altında performans darboğazları yaşanabilir. JMS uygulamalarınızın ölçeklenebilirliğini artırmak için aşağıdaki stratejileri göz önünde bulundurmalısınız:
- Connection Pooling: Bağlantı nesneleri (Connection) oluşturmak maliyetli bir işlemdir.
PooledConnectionFactorykullanarak bağlantıları yeniden kullanın. - Batch Processing: Çok sayıda küçük mesaj göndermek yerine, bunları gruplandırarak tek bir işlem (transaction) içerisinde göndermek ağ trafiğini azaltır.
- Asenkron Gönderim:
CompletionListenerkullanarak mesajın kuyruğa ulaşıp ulaşmadığını ana iş parçacığını (main thread) bloke etmeden takip edin.
Performans İçin Asenkron Gönderim Örneği
MessageProducer producer = session.createProducer(destination);
TextMessage message = session.createTextMessage("Yüksek performanslı veri");
producer.send(message, new CompletionListener() {
@Override
public void onCompletion(Message message) {
System.out.println("Mesaj başarıyla iletildi.");
}
@Override
public void onException(Message message, Exception e) {
System.err.println("Mesaj iletim hatası: " + e.getMessage());
}
});
JMS Uygulamalarında Hata Ayıklama ve İzlenebilirlik
Dağıtık sistemlerde bir mesajın kaybolması veya işlenememesi durumunda sorunun kaynağını bulmak zordur. İzlenebilirlik (observability) sağlamak için şu yöntemleri uygulayın:
- Message ID ve Correlation ID: Her mesaj için benzersiz bir
JMSCorrelationIDatayın. Bu, bir isteğin hangi yanıtla eşleştiğini takip etmenizi sağlar. - Dead Letter Queue (DLQ): İşlenemeyen mesajları otomatik olarak bir "Ölü Mektup Kuyruğu"na yönlendirin. Bu, ana kuyruğun tıkanmasını engeller.
- Logging: Mesajın kuyruğa giriş ve çıkış anlarını, işlem süresiyle birlikte loglayın.
DLQ Yapılandırması ve İzleme
Çoğu JMS sağlayıcısı (ActiveMQ, Artemis vb.), hata alan mesajları belirli bir deneme sayısından sonra DLQ'ya taşır. Kod tarafında bu mesajları analiz etmek için şu yapıyı kullanabilirsiniz:
// Hatalı mesajları dinleyen özel bir Consumer
MessageConsumer dlqConsumer = session.createConsumer(session.createQueue("DLQ.MainQueue"));
dlqConsumer.setMessageListener(message -> {
try {
String originalId = message.getStringProperty("OriginalMessageID");
System.err.println("İşlenemeyen mesaj tespit edildi. ID: " + originalId);
// Burada veritabanına loglama veya manuel müdahale mekanizması tetiklenebilir
} catch (JMSException e) {
e.printStackTrace();
}
});
İpucu: Üretim ortamında mesajlarınızı her zaman JMSDeliveryMode.PERSISTENT modunda gönderin. Bu, mesajın broker çöktüğünde diskte saklanmasını ve kaybolmamasını garanti eder.
Sonuç
Java ile JMS kullanarak mesaj kuyruğu tabanlı iletişim kurmak, sistemlerinizin esnekliğini ve dayanıklılığını artırır. Bu rehberde, bağlantı kurma, mesaj gönderme, alma ve işlem yönetimi gibi temel adımları inceledik. Bir sonraki adım olarak, Spring Boot ile JMS entegrasyonu (JmsTemplate kullanımı) konusunu inceleyerek kodunuzu çok daha sade ve yönetilebilir hale getirebilirsiniz. Unutmayın, mesaj tabanlı mimarilerde hata yönetimi ve izlenebilirlik, kodun kendisi kadar önemlidir.
Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Üretim ortamına almadan önce kendi güvenlik protokollerinizi ve hata yönetimi stratejilerinizi uyguladığınızdan emin olun.

Yorumlar (0)
Yorum Yaz