TL;DR
- Scenario: JMS Topic broadcasts in application cluster, causing same business to be repeatedly consumed by multiple nodes
- Conclusion: Use ActiveMQ Virtual Topic (or JMS 2.0 Shared Subscription) to implement “inter-group broadcast + intra-group competitive consumption” at middleware layer
- Output: Queue/Topic selection boundary, PERSISTENT/NON_PERSISTENT semantics, cluster deduplication solution and troubleshooting guide
JMS Message Mode
Point-to-Point
- One-to-one communication model based on message queue
- Producer sends message to specific queue, consumer retrieves from queue for processing
- Each message can only be received by one consumer
- Typical scenario: Order processing, async task processing
Publish/Subscribe
- One-to-many broadcast communication based on topic
- Publisher sends message to topic, all subscribers receive message copy
- Supports durable and non-durable subscriptions
- Typical scenario: Real-time notifications, event-driven architecture
Delivery Modes
NON_PERSISTENT
- At most once delivery, no guarantee message will be received
- Message sent directly to consumer, not stored intermediately
- Advantage: Fast transmission, low system overhead
- Risk: Undelivered messages lost permanently when service interrupts
PERSISTENT
- Guarantees message delivery, uses “store-and-forward” mechanism
- Message first persisted to disk or database
- Only deleted from storage after service confirms receipt
- Message retained until recovery when service interrupts
Application Cluster Issues
Problem Description: In Queue mode message consumption is normal (different nodes compete for consumption), but in Topic broadcast mode, same message is repeatedly consumed by different nodes.
Solutions
Solution 1: Create Multiple Identical Queues
- Drawback: Storage resource waste, producer burden increased, poor scalability
Solution 2: Topic Mode + Business Hashing/Distributed Lock
- Drawback: High business intrusion, high system complexity, poor maintainability
Solution 3: Virtual Topic - Recommended
- Producer publishes to VirtualTopic.XXX
- ActiveMQ automatically creates queue Consumer.
.VirtualTopic.XXX for each consumer group - Same consumer group competes for consumption (P2P) within group
- Different consumer groups get full messages (Topic) across groups
Working Principle:
Producer -> VirtualTopic.ORDER
↓
Consumer.GroupA.VirtualTopic.ORDER (queue, intra-group competition)
Consumer.GroupB.VirtualTopic.ORDER (queue, intra-group competition)
Error Quick Reference
| Symptom | Root Cause | Fix |
|---|---|---|
| Topic mode same business executed on multiple applications | Pub/Sub broadcast semantics | Use Virtual Topic or JMS 2.0 Shared Subscription |
| Missing messages after app restart | Default NON_PERSISTENT; non-durable subscription loses offline messages | Change to PERSISTENT; use durable subscription |
| Queue mode duplicate processing | Processing failure triggers redelivery; ACK too early | Check redelivered flag; ACK after business success |
| Message backlog, high latency | Consumer throughput insufficient | Scale out; adjust concurrency and prefetch; set TTL+DLQ |
| DLQ continues growing | Poison messages reach max retries | Increase message schema compatibility; implement degradation/isolation |