JMS (Java Message Service) định nghĩa 2 messaging domain (mô hình truyền tin):
1. Point-to-Point (PTP) – Queue
- Đối tượng:
Queue(java.jms.Queue / jakarta.jms.Queue). - Mối quan hệ: 1 Sender → 1 Receiver (One-to-One).
- Cơ chế: Sender gửi message vào Queue. Receiver (consumer) nhận message từ Queue. Message bị xóa sau khi được consume thành công (acknowledged).
- Load balancing: Nhiều consumer trên cùng Queue → competing consumers (chỉ 1 nhận được 1 message).
- Timing: Không phụ thuộc thời gian. Sender và Receiver không cần online cùng lúc. Message lưu trong queue cho đến khi được lấy.
- Acknowledgment: Bắt buộc (AUTO_ACKNOWLEDGE, CLIENT_ACKNOWLEDGE, DUPS_OK_ACKNOWLEDGE).
2. Publish/Subscribe (Pub/Sub) – Topic
- Đối tượng:
Topic(java.jms.Topic / jakarta.jms.Topic). - Mối quan hệ: 1 Publisher → Nhiều Subscribers (One-to-Many / Broadcast).
- Cơ chế: Publisher gửi message vào Topic. Tất cả active subscribers nhận bản sao message.
- Durable Subscription: Subscriber đăng ký durable → nhận được message ngay cả khi offline (message được lưu cho subscriber đó).
- Timing: Phụ thuộc thời gian. Subscriber phải online (hoặc durable) tại thời điểm publish mới nhận được.
- Acknowledgment: Tùy chọn (có thể không ack).
Bảng so sánh
| Tiêu chí | Point-to-Point (Queue) | Publish/Subscribe (Topic) |
|---|---|---|
| Messaging style | 1-1 (Queue) | 1-N (Broadcast) |
| Message consumption | Một consumer nhận 1 message | Tất cả subscribers nhận bản sao |
| Message persistence | Lưu cho đến khi consume | Chỉ lưu cho durable subscribers |
| Timing dependency | Không (asynchronous) | Có (subscriber phải active) |
| Load balancing | Competing consumers (tự nhiên) | Không (mỗi sub nhận tất cả) |
| Acknowledgment | Bắt buộc | Tùy chọn |
| Pull/Push | Pull (consumer receive()) hoặc Push (MessageListener) | Push (MessageListener) chủ yếu |
| Use case | Task queue, workload distribution, commands | Event notification, broadcasting, fan-out |
Ví dụ code JMS (Jakarta JMS 3.0+)
// Point-to-Point
@Resource(lookup = "java:/jms/queue/MyQueue")
Queue queue;
JMSContext context = connectionFactory.createContext();
context.createProducer().send(queue, "Task data");
String msg = context.createConsumer(queue).receiveBody(String.class);
// Publish/Subscribe
@Resource(lookup = "java:/jms/topic/MyTopic")
Topic topic;
context.createProducer().send(topic, "Event notification");
// Subscriber 1
context.createConsumer(topic).setMessageListener(m -> System.out.println("Sub1: " + m.getBody(String.class)));
// Subscriber 2 (durable)
context.createDurableConsumer(topic, "sub2").setMessageListener(...);
Lưu ý quan trọng
- JMS 2.0+ (Jakarta JMS 3.0) đơn giản hóa API:
JMSContext,JMSProducer,JMSConsumerthay vì Connection/Session/Producer/Consumer riêng rẽ. - ActiveMQ, RabbitMQ (via plugin), IBM MQ, WebLogic JMS implement cả Queue và Topic.
- Kafka không tuân thủ JMS spec, nhưng có thể bridge qua Kafka Connect JMS Source/Sink.