Apache ActiveMQ 是最流行的開源 JMS 提供者,支持多種協議、集群、持久化、Spring 整合。本文記錄 Linux 下安裝啟動、Web 控制台使用、Maven 依賴、生產者/消費者完整代碼(含事務、線程局部變量優化)、多線程壓測驗證及核心特性選型指南。
wget https://archive.apache.org/dist/activemq/5.15.15/apache-activemq-5.15.15-bin.tar.gz
tar -zxvf apache-activemq-5.15.15-bin.tar.gz
cd apache-activemq-5.15.15
| 目錄 | 用途 |
|---|---|
| bin | 啟動/關閉腳本 |
| conf | 核心配置 activemq.xml、jetty.xml、用戶權限 |
| data | 日志、KahaDB 持久化文件 |
| lib | 運行依賴 JAR |
| webapps | Web 控制台 WAR |
./bin/activemq start # 後台啟動
# 或前台調試
./bin/activemq console
61616 (OpenWire)、8161 (Web Console/Jetty)。https://host:8161/admin/,默認用戶/密碼 admin/admin。
org.apache.activemq
activemq-client
5.15.15
org.apache.activemq
activemq-pool
5.15.15
org.springframework
spring-jms
5.3.x
public class Producer {
private static final String URL = "tcp://localhost:61616";
private static final String USER = "admin";
private static final String PASS = "admin";
private ConnectionFactory factory;
private Connection conn;
private Session session;
private final ThreadLocal producerLocal = new ThreadLocal<>();
private final AtomicInteger counter = new AtomicInteger();
public void init() throws JMSException {
factory = new ActiveMQConnectionFactory(USER, PASS, URL);
conn = factory.createConnection();
conn.start();
// 事務會話:手動 commit/rollback
session = conn.createSession(true, Session.SESSION_TRANSACTED);
}
public void send(String queueName) {
try {
Queue queue = session.createQueue(queueName);
MessageProducer producer = producerLocal.get();
if (producer == null) {
producer = session.createProducer(queue);
producerLocal.set(producer);
}
while (true) {
Thread.sleep(1000);
int num = counter.getAndIncrement();
TextMessage msg = session.createTextMessage(
Thread.currentThread().getName() + " 生產消息 count:" + num);
producer.send(msg);
session.commit(); // 事務提交
System.out.println("已發送: " + msg.getText());
}
} catch (Exception e) {
try { session.rollback(); } catch (JMSException ignored) {}
e.printStackTrace();
}
}
public void close() {
try {
if (session != null) session.close();
if (conn != null) conn.close();
} catch (JMSException e) { e.printStackTrace(); }
}
}
public class Consumer {
private static final String URL = "tcp://localhost:61616";
private static final String USER = "admin";
private static final String PASS = "admin";
private ConnectionFactory factory;
private Connection conn;
private Session session;
private final ThreadLocal consumerLocal = new ThreadLocal<>();
private final AtomicInteger counter = new AtomicInteger();
public void init() throws JMSException {
factory = new ActiveMQConnectionFactory(USER, PASS, URL);
conn = factory.createConnection();
conn.start();
// 自動確認模式:消息處理完成自動 ACK
session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
}
public void receive(String queueName) {
try {
Queue queue = session.createQueue(queueName);
MessageConsumer consumer = consumerLocal.get();
if (consumer == null) {
consumer = session.createConsumer(queue);
consumerLocal.set(consumer);
}
while (true) {
Thread.sleep(1000);
TextMessage msg = (TextMessage) consumer.receive(1000); // 1s 超時
if (msg != null) {
System.out.println(Thread.currentThread().getName()
+ " 消費: " + msg.getText() + " ---> " + counter.getAndIncrement());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void close() {
try {
if (session != null) session.close();
if (conn != null) conn.close();
} catch (JMSException e) { e.printStackTrace(); }
}
}
public class ProducerTest {
public static void main(String[] args) throws Exception {
Producer p = new Producer();
p.init();
Thread.sleep(1000);
for (int i = 0; i < 5; i++) {
new Thread(p::send, "P-" + i).start();
}
}
}
輸出片段:
P-0 生產消息 count:0
P-1 生產消息 count:1
P-2 生產消息 count:2
...
public class ConsumerTest {
public static void main(String[] args) throws Exception {
Consumer c = new Consumer();
c.init();
for (int i = 0; i < 4; i++) {
new Thread(() -> c.receive("Jaycekon-MQ"), "C-" + i).start();
}
}
}
輸出片段:
C-0 消費: P-2 生產消息 count:4 ---> 0
C-1 消費: P-0 生產消息 count:5 ---> 1
...
訪問 https://localhost:8161/admin/queues.jsp 查看:
Jaycekon-MQ 消息數、入隊/出隊速率。| 特性 | 說明 |
|---|---|
| 多協議 | OpenWire, STOMP, REST, WS, XMPP, AMQP, MQTT |
| JMS 1.1 完全支持 | 持久化、XA 事務、優先級、選擇器 |
| Spring 深度整合 | JmsTemplate、MessageListenerContainer、XML/注解配置 |
| 高性能持久化 | KahaDB (默認)、JDBC、LevelDB、Replicated LevelDB |
| 集群與高可用 | Network of Brokers、Master-Slave (Shared DB/LevelDB/ZooKeeper) |
| 輕量級嵌入 | 單元測試、微服務側車模式 BrokerService 嵌入啟動 |
JMS 基礎模型(P2P/發布訂閱、Connection/Session/Producer/Consumer/Listener)詳見拙作:Java消息隊列--JMS概述