1 ActiveMQ是啥
ActiveMQ 就是一個訊息中介軟體,市面上現在有很多的訊息中介軟體開源產品,比如,RocketMQ、RabbitMQ、Kafka等。
拿一個簡單的比喻來說,訊息中介軟體就是一箇中轉站,在程式中加的一箇中轉站,有了這樣一個類似快遞的儲存站點,可以大大的減輕物流的壓力,而對應到程式中,也就是減輕了程式的壓力。
另外不得不說的是,ActiveMQ是遵從 JMS 規範的訊息中介軟體,那麼什麼是 JMS 規範呢?
JMS 規範
JMS是java的訊息服務,JMS的客戶端之間可以通過JMS服務進行非同步的訊息傳輸。
訊息模型
- Point-to-Point(P2P),點對點
- P2P模式圖
如上圖,有幾個需要了解的概念,傳送者、接收者、訊息佇列。
在點對點模型中,一般訊息由傳送者將訊息傳送到訊息佇列中,然後,接收者從訊息佇列中消費訊息,訊息被消費者消費之後,訊息就不存在了。
- Publish/Subscribe(Pub/Sub),釋出訂閱模型
- Pub/Sub模式圖
如上圖,有下面幾個概念,主題、釋出者、訂閱者。
在釋出訂閱模型中,釋出者通常將訊息釋出到主題(topic)中,然後,訂閱者通過訂閱主題來消費訊息,與 P2P 模型不同的是,釋出訂閱模型的訊息是可以被多次消費的!
兩種模式的區別
1、P2P
在傳送者和接收者之間沒有時間上的依賴性,也就是說傳送者傳送了訊息之後,不管接收者有沒有執行,不會影響訊息傳送到佇列,而Pub/Sub
模式有時間上的依賴性,消費者必須先訂閱主題,才能夠消費訊息。
2、P2P
模式的每個訊息只能有一個消費者,消費完了訊息就不存在了,Pub/Sub
模式可以有多個消費者。
2 為什麼需要使用訊息中介軟體
到這裡我就不得不講一個小故事了!
小明、小李和小白都是在一個專案組的 Java 開發人員,但是呢,他們的團隊比較小,只有幾個開發人員,而他們正在開發一個專案,這個專案比較龐大,所以,專案負責人就考慮到專案進度,給他們每個人都分一個模組單獨開發,這樣就能夠加快專案的進度了。
然而,萬萬沒有想到的是,當專案開發到一定階段的時候,小明、小李和小白各自負責的模組都需要專案呼叫資料了,但是呢,現在問題來了,每次小白向小明需要資料的時候,小明總是要改介面來滿足小白的需求,而且還會擔心小明的系統會不會出問題,如果出了問題就呼叫不了怎麼辦?這樣就總是耽誤專案的進度,小李那邊也是出現了這種問題!
於是,小明就想了個辦法,如果在各個模組之間再加一個模組,用來處理資料,比如一個佇列來存資料,每次就把資料丟到那個模組中去,這樣就不用擔心那個問題啦。小明是不是很聰明!
其實,小明沒有做足夠的調查,他說的這個模組,就是 ActiveMQ 的作用所在啦。
也就是降低模組與模組之間的耦合度,達到解耦的目的!
然後,他們又遇到了一個問題,他們在開發一個使用者註冊模組的時候,是先註冊,然後寫入資料庫,然後再傳送郵件或者簡訊通知使用者,但是,他們發現這樣的系統速度很慢!
後來,他們發現了訊息中介軟體後,改造了一下,變成了下面的模式。
他們也發現了,這就是訊息中介軟體帶來的非同步執行的優勢!
系統速度槓槓的!
後來,小明、小李和小白開發的系統呢上線了,但是,公司業快速發展,當流量大的時候,系統的資料呼叫總是負荷不了,出現當機的問題,沒辦法,只能再改程式碼了!
他們靈機一動,前面都用了訊息中介軟體了,但是沒有發現另外一個功能,我們可以加入訊息中介軟體,控制每次消費訊息的數量,保證系統不會當機,剩下的訊息在系統流量小的時候再定時執行不就可以了。簡直不要太好!
小明、小李和小白經過這個系統的開發,終於明白了訊息中介軟體的優勢了!
3 安裝使用
3.1 下載
到下面的官網地址下載,包括linux和Windows的不同版本。
3.2 解壓使用
windows使用方法
首先,解壓到一個自己的目錄,ActiveMQ目錄如下;
進入到對應的 bin 目錄;
裡面有一個 activemq 的可執行檔案,開啟 cmd,執行:activemq start
成功啟動了!
關閉;
activemq stop
linux 使用方法
解壓到指定目錄;
sudo tar zxvf activemq-x.x.x-bin.tar.gz
進入到 bin 目錄,執行下面命令;
./activemq start
關閉;
./activemq stop
後臺管理介面
啟動成功之後,可以輸出http://localhost:8161/admin/
檢視 ActiveMQ 的後臺管理介面,使用者名稱和密碼都為 admin
。
ok,到這裡,ActiveMQ的安裝和基本使用應該沒有問題了,接下來,我們使用 ActiveMQ 的 Java API 從一個入門例項開始講起!
4 ActiveMQ入門程式
4.1 前提條件
在開始之前,先申明一下需要的 Java 環境的配置,相關配置自行解決哦!
- Java JDK1.7 以上
- Maven 3.0 以上
- 開發工具 IDEA
4.2 帶你入門
step1:匯入 Maven 相關依賴;
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.3.10.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
</dependencies>
step2:建立傳送端類;
/**
* @ClassName JmsSender
* @Description
* @Author 歐陽思海
* @Date 2019/8/13 16:39
* @Version 1.0
**/
public class JmsSender {
public static void main(String[] args) {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = null;
try {
connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.FALSE, Session.CLIENT_ACKNOWLEDGE);
Destination destination = session.createQueue("queue");
MessageProducer producer = session.createProducer(destination);
TextMessage textMessage = session.createTextMessage("hello activemq");
producer.send(textMessage);
//session.commit();
session.close();
} catch (JMSException e) {
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
}
上面的程式碼建立了一個訊息傳送者,步驟如下:
1、建立ActiveMQ實現的JMS規範的實現類ActiveMQConnectionFactory
的物件connectionFactory
,並且給定引數ActiveMQ的服務地址;
2、由connectionFactory
呼叫方法createConnection
建立連線connection
物件;
3、由connection
物件呼叫createSession
方法建立session
會話物件;
4、有了session
物件之後,就可以傳送者、佇列或者主題了,這裡建立佇列,session.createQueue("queue")
,並給定了佇列名稱為queue
。
5、session
物件通過方法createProducer
建立生產者,並且建立訊息session.createTextMessage("hello activemq")
;
6、生產者呼叫send
的方法傳送訊息,producer.send(textMessage)
;
通過上面的步驟就可以將訊息傳送到佇列中了,接著只要等待消費者消費訊息即可,訊息消費後,訊息就消失了。
通過上面的講解,也將JMS的主要的介面都概括了,包括:ConnectionFactory(連線工廠)、Session(會話)、Connection(連線);
step3:建立消費端類;
/**
* @ClassName JmsReceiver
* @Description
* @Author 歐陽思海
* @Date 2019/8/13 16:47
* @Version 1.0
**/
public class JmsReceiver {
public static void main(String[] args) {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = null;
try {
//建立連線
connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
//建立佇列(如果佇列已經存在則不會建立,queue是佇列名稱)
//destination表示目的地
Destination destination = session.createQueue("queue");
//建立訊息接收者
MessageConsumer consumer = session.createConsumer(destination);
TextMessage textMessage = (TextMessage) consumer.receive();
System.out.println(textMessage.getText());
session.commit();
session.close();
} catch (JMSException e) {
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
}
消費者和生產者的差別不大,前面的建立工廠、建立連線、建立會話物件和生產者一樣,區別在於,session.createConsumer(destination)
通過session
建立消費者,然後,呼叫receive
方法接受訊息。
執行傳送端,檢視後臺管理介面,點選 Queues 選項,發現有一個入隊的訊息,並且沒有出佇列;
執行接收端;
再檢視後臺管理介面,訊息被消費了;
5 ActiveMQ整合Spring
這一部分花了挺多時間琢磨的,首先是應為在實際的開發中,我們整合Spring來開發專案是最多的一種方式,這一塊如果可以學透的話,對於專案開發是非常有好處的,出於這個出發點,儘可能的把相關的知識講解的全面一些。
首先,這一部分分為以下三個部分來講解。
- 不使用 Spring 配置檔案方式
- 使用 Spring 配置檔案方式
- 註解方式(0配置)
5.1 前提條件
- JDK 1.7 以上
- Maven 3.0 以上
- Spring 4.3.1 ,或者以上版本
- ActiveMQ 5.15.9 目前最新穩定版本
專案結構
這次搭建的專案是一個子模組聚合的專案,結構如下;
這個聚合的專案分為生產者(Producer) 和消費者(Consumer)兩個子模組。
匯入 Maven 依賴
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.3.10.RELEASE</spring.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
溫馨提示
由於我這裡使用的是子模組聚合的方式,所以,如果你不是這種方式的專案,直接給出各個依賴的版本在你的專案中即可!
5.2 不使用 Spring 配置檔案方式
這一節的講解中,我們將採用不使用 Spring 的配置檔案的方式,Maven 的相關依賴在上面已經給出,請參考上一節的內容。
生產者(Producer)
首先,我們來看一下生產者端,生產者端主要負責傳送訊息到 Broker
中,傳送的目的地(Destination)
可以分為佇列(Queue)
和主題(Topic)
,下面,我們就看看如何不採用 Spring 配置檔案的方式傳送訊息。
public static void main(String[] args) {
ConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = null;
try {
connection = cf.createConnection();
connection.start();
Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
Queue destination = session.createQueue("queue2");
JmsQueueSenderWithNotXml jmsQueueSender = new JmsQueueSenderWithNotXml();
jmsQueueSender.setConnectionFactory(cf);
jmsQueueSender.setQueue(destination);
jmsQueueSender.simpleSend();
jmsQueueSender.sendWithConversion();
} catch (JMSException e) {
e.printStackTrace();
}
}
private JmsTemplate jmsTemplate;
private Queue queue;
public void setConnectionFactory(ConnectionFactory cf) {
this.jmsTemplate = new JmsTemplate(cf);
}
public void setQueue(Queue queue) {
this.queue = queue;
}
/*
* @Author 歐陽思海
* @Description 傳送簡單訊息
* @Date 15:45 2019/8/16
* @Param []
* @return void
**/
public void simpleSend() {
this.jmsTemplate.send(this.queue, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage("hello queue world");
}
});
System.out.println("傳送成功!");
}
/*
* @Author 歐陽思海
* @Description 傳送map型別的訊息
* @Date 15:46 2019/8/16
* @Param []
* @return void
**/
public void sendWithConversion() {
Map map = new HashMap();
map.put("Name", "sihai");
map.put("Age", new Integer(18));
jmsTemplate.convertAndSend("Queue3", map, new MessagePostProcessor() {
public Message postProcessMessage(Message message) throws JMSException {
message.setIntProperty("num", 189);
message.setJMSCorrelationID("00001");
return message;
}
});
System.out.println("傳送成功!");
}
step1:上面是生產者端的所有程式碼示例,在這個示例中,我們首先通過下面的程式碼設定好ConnectionFactory 和Queue,並且呼叫JmsTemplate
Spring提供的工具類提供兩個傳送訊息的方法 。
private JmsTemplate jmsTemplate;
private Queue queue;
public void setConnectionFactory(ConnectionFactory cf) {
this.jmsTemplate = new JmsTemplate(cf);
}
public void setQueue(Queue queue) {
this.queue = queue;
}
/*
* @Author 歐陽思海
* @Description 傳送簡單訊息
* @Date 15:45 2019/8/16
* @Param []
* @return void
**/
public void simpleSend() {
this.jmsTemplate.send(this.queue, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage("hello queue world");
}
});
System.out.println("傳送成功!");
}
/*
* @Author 歐陽思海
* @Description 傳送map型別的訊息
* @Date 15:46 2019/8/16
* @Param []
* @return void
**/
public void sendWithConversion() {
Map map = new HashMap();
map.put("Name", "sihai");
map.put("Age", new Integer(18));
jmsTemplate.convertAndSend("Queue3", map, new MessagePostProcessor() {
public Message postProcessMessage(Message message) throws JMSException {
message.setIntProperty("num", 189);
message.setJMSCorrelationID("00001");
return message;
}
});
System.out.println("傳送成功!");
}
step2:使用Main方法,設定ConnectionFactory和Queue物件,接著,呼叫傳送方法傳送訊息。
public static void main(String[] args) {
ConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = null;
try {
connection = cf.createConnection();
connection.start();
Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
Queue destination = session.createQueue("queue2");
JmsQueueSenderWithNotXml jmsQueueSender = new JmsQueueSenderWithNotXml();
jmsQueueSender.setConnectionFactory(cf);
jmsQueueSender.setQueue(destination);
jmsQueueSender.simpleSend();
jmsQueueSender.sendWithConversion();
} catch (JMSException e) {
e.printStackTrace();
}
}
step2:接著,我們執行上面的程式碼,輸出下面結果,再看一下ActiveMQ的控制檯,看看有沒有訊息傳送成功。
發現有一條掛起的訊息和入佇列的訊息,說明傳送成功!
消費者(Consumer)
對於消費者,在這一節先不展開講解,可以先參考上面的入門程式的消費端的程式碼消費訊息,接下來的方式再講解消費端的消費訊息。
5.3 使用 Spring 配置檔案方式
上面一節中,講解了不使用 Spring 配置的方式如何傳送訊息,主要是想讓大家瞭解一下其中的原理,這一節中,將使用 Spring 配置的方式講解,這種方式在實際的開發中還是用的比較多的。
生產者(Producer)
既然是配置檔案的方式,那麼,首先,不得不講如何進行xml配置了。
step1:xml配置檔案
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jms https://www.springframework.org/schema/jms/spring-jms.xsd">
<bean id="connectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL">
<value>tcp://localhost:61616</value>
</property>
</bean>
</property>
<property name="maxConnections" value="50"/>
</bean>
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0" value="spring-queue"/>
</bean>
<!--<bean id="destinationTopic" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg index="0" value="spring-topic"/>
</bean>-->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="defaultDestination" ref="destination"/>
<property name="messageConverter">
<bean class="org.springframework.jms.support.converter.SimpleMessageConverter"/>
</property>
</bean>
</beans>
在上面的配置中,首先,需要配置connectionFactory
(對應不使用配置的connectionFactory物件),然後,需要配置destination
(對應不使用配置的destination),在這裡使用的是向佇列傳送訊息,也可以使用主題(Topic),最後,配置 Spring 提供的jmsTemplate
模板類。
step2:使用Main方法執行
public static void main(String[] args) {
ApplicationContext application = new FileSystemXmlApplicationContext("G:\\ideaproject\\activemq\\Producer\\src\\main\\resources\\service-jms.xml");
JmsTemplate jmsTemplate = (JmsTemplate) application.getBean("jmsTemplate");
for (int i = 0; i < 10; i++) {
int finalI = i;
jmsTemplate.send((session) -> {
TextMessage textMessage = session.createTextMessage();
textMessage.setText("first message" + finalI);
return textMessage;
});
}
}
在上面的程式碼中,呼叫了JmsTemplate
的send
方法傳送訊息。執行之後,就成功傳送訊息了,這種方式還是簡潔不少的。
溫馨提示
上面我使用的是FileSystemXmlApplicationContext
獲取xml配置檔案,除此之外,你也可以使用ClassPathXmlApplicationContext
來獲取。
消費者(Consumer)
在上一節中,沒有講解消費者,在這一節中,將重點講解。
step1:首先,我們還是需要配置xml檔案
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms-4.1.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.8.0.xsd">
<!--連線工廠-->
<bean id="connectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL">
<value>tcp://localhost:61616</value>
</property>
</bean>
</property>
<property name="maxConnections" value="50"/>
</bean>
<!--配置佇列-->
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0" value="queue2"/>
</bean>
<!-- 配置主題(topic)-->
<!-- <bean id="destinationTopic" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg index="0" value="spring-topic"/>
</bean>-->
<!--配置spring的jms模板-->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="defaultDestination" ref="destination"/>
<property name="messageConverter">
<bean class="org.springframework.jms.support.converter.SimpleMessageConverter"/>
</property>
</bean>
<!-- 訊息監聽器 -->
<!--<bean id="messageListener" class="com.sihai.activemq.listener.MyMessageListener"/>-->
<bean id="messageListener" class="com.sihai.activemq.listener.MySessionAwareMessageListener"></bean>
<!--jta事務-->
<!--<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>-->
<!-- 訊息監聽器容器 -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="destination"/>
<property name="messageListener" ref="messageListener"/>
<!--配置本地資源事務-->
<!--<property name="sessionTransacted" value="true"/>-->
<!--配置jta事務-->
<!--<property name="transactionManager" ref="transactionManager"/>-->
</bean>
<!--<!– 監聽註解支援 –>
<jms:annotation-driven />-->
</beans>
最前面的配置和生產者是一樣的,需要配置connectionFactory
(對應不使用配置的connectionFactory物件),然後,需要配置destination
(對應不使用配置的destination)。
區別在於,消費者端需要配置一個訊息監聽器容器,如下。
<!-- 訊息監聽器 -->
<!--<bean id="messageListener" class="com.sihai.activemq.listener.MyMessageListener"/>-->
<bean id="messageListener" class="com.sihai.activemq.listener.MySessionAwareMessageListener"></bean>
<!--jta事務-->
<!--<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>-->
<!-- 訊息監聽器容器 -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="destination"/>
<property name="messageListener" ref="messageListener"/>
<!--配置本地資源事務-->
<!--<property name="sessionTransacted" value="true"/>-->
<!--配置jta事務-->
<!--<property name="transactionManager" ref="transactionManager"/>-->
</bean>
那麼這個怎麼配置呢?請接著看。
step2:訊息監聽器容器配置
首先,我們需要寫一個類,實現MessageListener
介面,然後實現一個名為onMessage
的方法,通過這個方法就可以監聽是否有訊息,有訊息就消費。
/**
* @ClassName MyMessageListener
* @Description 訊息消費監聽器實現
* @Author 歐陽思海
* @Date 2019/8/13 20:39
* @Version 1.0
**/
@Component
public class MyMessageListener implements MessageListener {
@Override
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
System.out.println(((TextMessage) message).getText());
}
catch (JMSException ex) {
throw new RuntimeException(ex);
}
}
else {
throw new IllegalArgumentException("Message must be of type TextMessage");
}
}
}
如此,配置就完成了。
step3:啟動spring容器,執行。
/*
* @Author 歐陽思海
* @Description xml配置方式獲取訊息
* @Date 18:09 2019/8/16
* @Param []
* @return void
**/
@Test
public void test_01() throws IOException {
ClassPathXmlApplicationContext application = new ClassPathXmlApplicationContext("G:\\ideaproject\\activemq\\Consumer\\src\\main\\resources\\service-jms.xml");
/*JmsTemplate jmsTemplate = (JmsTemplate) application.getBean("jmsTemplate");
String msg = (String) jmsTemplate.receiveAndConvert();
System.out.println(msg);*/
System.in.read();
}
在上面的程式碼中,System.in.read()
,這個作用就是一直等待,有訊息就消費。
step4:開啟訊息監聽器事務
在訊息處理的過程中是可以開啟事務的,如果出現處理失敗的情況,就會回滾。在訊息監聽容器當中可以配置一個屬性是sessionTransacted的本地事務,如果value
為true
,就代表開啟本地事務。具體配置如下:
<!-- 訊息監聽器容器 -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="destination"/>
<property name="messageListener" ref="messageListener"/>
<!--配置本地資源事務-->
<property name="sessionTransacted" value="true"/>
</bean>
訊息監聽器容器
上面的消費者的講解中,其實,最重要的就是訊息監聽器容器配置了,這一部分,我們就詳細的講解一下訊息監聽器容器的配置方法。
1 實現MessageListener介面
這種方式就是上面的例項使用的方式,先看看這個介面。
public interface MessageListener {
void onMessage(Message var1);
}
這個介面很簡單,只有一個方法onMessage
,通過拿到Message
引數讀取訊息,這裡就不再多說了。
2 實現SessionAwareMessageListener介面
這個介面平時很少用到,但是,其實是有這個介面可以實現的,這個介面和上面的MessageListener
介面有點不一樣,這個介面是Spring
提供的。
public interface SessionAwareMessageListener<M extends Message> {
void onMessage(M var1, Session var2) throws JMSException;
}
另外,你可以看到,這個介面提供的是一個泛型介面,可以是M extends Message
這個型別,同時,實現的方式onMessage
,還多了一個Session
引數,可以在獲取訊息的同時處理Session
。
使用例項
/**
* @ClassName MySessionAwareMessageListener
* @Description 實現SessionAwareMessageListener的訊息監聽器
* @Author 歐陽思海
* @Date 2019/8/16 16:02
* @Version 1.0
**/
public class MySessionAwareMessageListener implements SessionAwareMessageListener {
@Override
public void onMessage(Message message, Session session) throws JMSException {
if (message instanceof TextMessage) {
try {
System.out.println(((TextMessage) message).getText());
}
catch (JMSException ex) {
throw new RuntimeException(ex);
}
}
else {
throw new IllegalArgumentException("Message must be of type TextMessage");
}
}
}
5.4 註解方式(0配置)
前面已經介紹了兩種方式,分別是不使用xml配置方式和使用xml配置的方式,但是,由於現在微服務的興起,約定優於配置是現在的一種趨勢,所以,在這一節中,我們使用註解的方式來處理。
生產者(Producer)
由於使用註解的方式,所以,我們不再需要xml配置檔案了,但是,我們可以參照上面的xml的配置方式來配置註解的方式。
step1:首先,我們需要一個 Java 配置類,如下;
/**
* @ClassName ProducerConfig
* @Description 不用xml的配置類
* @Author 歐陽思海
* @Date 2019/8/16 17:41
* @Version 1.0
**/
@Configuration
public class ProducerConfig {
@Bean
//配置ConnectionFactory用於生成connection
public ActiveMQConnectionFactory connectionFactory() {
ActiveMQConnectionFactory activeMQConnectionFactory
= new ActiveMQConnectionFactory("tcp://localhost:61616");
return activeMQConnectionFactory;
}
@Bean
//註冊SingleConnectionFactory,這個spring的一個包裝工廠 用於管理真正的ConnectionFactory
public SingleConnectionFactory singleConnectionFactory(ActiveMQConnectionFactory activeMQconnectionFactory) {
SingleConnectionFactory connectionFactory = new SingleConnectionFactory();
//設定目標工廠
connectionFactory.setTargetConnectionFactory(activeMQconnectionFactory);
return connectionFactory;
}
@Bean
//配置生產者,jmsTemplate
public JmsTemplate jmsTemplate(SingleConnectionFactory connectionFactory) {
JmsTemplate jmsTemplate = new JmsTemplate();
jmsTemplate.setConnectionFactory(connectionFactory);
return jmsTemplate;
}
/**
* 配置佇列目的的: 根據測試需要配置其中一個
* 1.佇列 點對點 queue
* 2.主題 一對多 topic
*/
@Bean //
public ActiveMQQueue queueDestination() {
ActiveMQQueue activeMQQueue = new ActiveMQQueue("queue-anno");
return activeMQQueue;
}
@Bean
public ActiveMQTopic topicDestination() {
ActiveMQTopic activeMQTopic = new ActiveMQTopic("topic-anno");
return activeMQTopic;
}
}
上面的配置的每一個方法就對應xml配置的每一個節點,對應起來配置會比較簡單,每一個方法都使用了@Bean
這個註解,類上使用Configuration
,將這些配置加入到 spring 容器中。
step2:啟動 spring 容器,傳送訊息;
/**
* @ClassName JmsSenderWithAnnotation
* @Description 註解傳送方式
* @Author 歐陽思海
* @Date 2019/8/16 18:04
* @Version 1.0
**/
public class JmsSenderWithAnnotation {
/*
* @Author 歐陽思海
* @Description 測試點對點
* @Date 18:05 2019/8/16
* @Param []
* @return void
**/
@Test
public void testActiveMqAnnotation() {
AnnotationConfigApplicationContext aContext =
new AnnotationConfigApplicationContext(ProducerConfig.class);
//獲得傳送者的模板物件
JmsTemplate jmsTemplate = aContext.getBean(JmsTemplate.class);
Destination bean = (Destination) aContext.getBean("queueDestination");
//傳送訊息
jmsTemplate.send(bean, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
TextMessage message = session.createTextMessage();
message.setText("activemq message for queue");
return message;
}
});
}
/*
* @Author 歐陽思海
* @Description 測試topic傳送
* @Date 18:06 2019/8/16
* @Param []
* @return void
**/
@Test
public void testActiveMqAnnotation2() {
AnnotationConfigApplicationContext aContext =
new AnnotationConfigApplicationContext(ProducerConfig.class);
//獲得傳送者的模板物件
JmsTemplate jmsTemplate = aContext.getBean(JmsTemplate.class);
Destination bean = (Destination) aContext.getBean("topicDestination");
//傳送訊息
jmsTemplate.send(bean, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
TextMessage message = session.createTextMessage();
message.setText("activemq message for topic");
return message;
}
});
}
}
分別執行這兩個測試,檢視ActiveMQ控制檯,發現Queue和Topic都有一條訊息傳送成功;
消費者(Consumer)
消費者的大概也差不多,跟xml的配置一樣,多的也是訊息監聽容器的配置,來看看;
step1:首先,Java 配置類
**
* @ClassName ConsumerConfig
* @Description 不用xml的配置類
* @Author 歐陽思海
* @Date 2019/8/16 17:44
* @Version 1.0
**/
@ComponentScan(basePackages = {"com.sihai"})
@EnableJms
@Configuration
public class ConsumerConfig {
@Bean
//配置ConnectionFactory用於生成connection
public ActiveMQConnectionFactory connectionFactory() {
ActiveMQConnectionFactory activeMQConnectionFactory
= new ActiveMQConnectionFactory("tcp://localhost:61616");
return activeMQConnectionFactory;
}
@Bean
//註冊SingleConnectionFactory,這個spring的一個包裝工廠 用於管理真正的ConnectionFactory
public SingleConnectionFactory singleConnectionFactory(ActiveMQConnectionFactory activeMQconnectionFactory) {
SingleConnectionFactory connectionFactory = new SingleConnectionFactory();
//設定目標工廠
connectionFactory.setTargetConnectionFactory(activeMQconnectionFactory);
return connectionFactory;
}
/*在xml當中的如下配置 效果相同
* <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
* <property name="connectionFactory" ref="connectionFactory" />
* <property name="destination" ref="topicDestination" />
* <property name="messageListener" ref="itemListenerMessage" />
* </bean>
**/
@Bean
public DefaultMessageListenerContainer jmsListenerContainerFactory(SingleConnectionFactory singleConnectionFactory, MyMessageListener myMessageListener, Destination destination) {
//建立容器
DefaultMessageListenerContainer jmsContainer = new DefaultMessageListenerContainer();
//設定監聽器
jmsContainer.setMessageListener(myMessageListener);
//設定連線工廠
jmsContainer.setConnectionFactory(singleConnectionFactory);
//設定監聽目的地的名字/也可以直接設定物件目的地
jmsContainer.setDestination(destination);
return jmsContainer;
}
/**
* 1.佇列 點對點 queue
* 2.主題 一對多 topic
*/
@Bean
public ActiveMQQueue queueDestination() {
ActiveMQQueue activeMQQueue = new ActiveMQQueue("queue-anno");
return activeMQQueue;
}
/*@Bean
public ActiveMQTopic topicDestination() {
ActiveMQTopic activeMQTopic = new ActiveMQTopic("topic-anno");
return activeMQTopic;
}*/
}
其中只有一個訊息監聽容器的配置是和生產者的配置不同的,訊息監聽容器的配置需要配置訊息監聽器、連線工廠和目的地(Destination)。
/*在xml當中的如下配置 效果相同
* <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
* <property name="connectionFactory" ref="connectionFactory" />
* <property name="destination" ref="topicDestination" />
* <property name="messageListener" ref="itemListenerMessage" />
* </bean>
**/
@Bean
public DefaultMessageListenerContainer jmsListenerContainerFactory(SingleConnectionFactory singleConnectionFactory, MyMessageListener myMessageListener, Destination destination) {
//建立容器
DefaultMessageListenerContainer jmsContainer = new DefaultMessageListenerContainer();
//設定監聽器
jmsContainer.setMessageListener(myMessageListener);
//設定連線工廠
jmsContainer.setConnectionFactory(singleConnectionFactory);
//設定監聽目的地的名字/也可以直接設定物件目的地
jmsContainer.setDestination(destination);
return jmsContainer;
}
step2:訊息監聽器
/**
* @ClassName MyMessageListener
* @Description 訊息消費監聽器實現
* @Author 歐陽思海
* @Date 2019/8/13 20:39
* @Version 1.0
**/
@Component
public class MyMessageListener implements MessageListener {
@Override
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
System.out.println(((TextMessage) message).getText());
}
catch (JMSException ex) {
throw new RuntimeException(ex);
}
}
else {
throw new IllegalArgumentException("Message must be of type TextMessage");
}
}
}
這個前面已經講過了,這裡就不再累贅了,但是,這裡我需要講的是訊息監聽器註解方式的配置,如下。
step3:訊息監聽器註解方式的配置方法
/**
* @ClassName JmsAnnotation
* @Description 註解方式監聽
* @Author 歐陽思海
* @Date 2019/8/16 17:01
* @Version 1.0
**/
@Component
@EnableJms
public class JmsAnnotation {
@JmsListener(destination = "queue-anno")
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
System.out.println(((TextMessage) message).getText());
}
catch (JMSException ex) {
throw new RuntimeException(ex);
}
}
else {
throw new IllegalArgumentException("Message must be of type TextMessage");
}
}
}
你會發現,在訊息監聽器的類上面需要兩個配置@Component和@EnableJms,用於標記這是一個訊息監聽器,另外,在onMessage
方法上,需要一個@JmsListener(destination = "queue-anno")
註解,可以標記需要哪個destination
。
注意:如果採用註解的訊息監聽,那麼需要修改Java類的訊息監聽的容器的配置,否則會出現問題
step4:訊息監聽容器配置更改
將
/*在xml當中的如下配置 效果相同
* <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
* <property name="connectionFactory" ref="connectionFactory" />
* <property name="destination" ref="topicDestination" />
* <property name="messageListener" ref="itemListenerMessage" />
* </bean>
**/
@Bean
public DefaultMessageListenerContainer jmsListenerContainerFactory(SingleConnectionFactory singleConnectionFactory, MyMessageListener myMessageListener, Destination destination) {
//建立容器
DefaultMessageListenerContainer jmsContainer = new DefaultMessageListenerContainer();
//設定監聽器
jmsContainer.setMessageListener(myMessageListener);
//設定連線工廠
jmsContainer.setConnectionFactory(singleConnectionFactory);
//設定監聽目的地的名字/也可以直接設定物件目的地
jmsContainer.setDestination(destination);
return jmsContainer;
}
改為
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
// factory.setDestinationResolver(destinationResolver());
factory.setSessionTransacted(true);
factory.setConcurrency("3-10");
return factory;
}
上面的修改會發現,實現介面的監聽器使用的是DefaultMessageListenerContainer
,而註解的方式使用的是DefaultJmsListenerContainerFactory
,所以,這裡需要特別注意。
此時,訊息監聽器是註解的方式的Java配置類就是下面這樣的。
/**
* @ClassName ConsumerConfig
* @Description 不用xml的配置類
* @Author 歐陽思海
* @Date 2019/8/16 17:44
* @Version 1.0
**/
@ComponentScan(basePackages = {"com.sihai"})
@EnableJms
@Configuration
public class ConsumerConfig {
@Bean
//配置ConnectionFactory用於生成connection
public ActiveMQConnectionFactory connectionFactory() {
ActiveMQConnectionFactory activeMQConnectionFactory
= new ActiveMQConnectionFactory("tcp://localhost:61616");
return activeMQConnectionFactory;
}
@Bean
//註冊SingleConnectionFactory,這個spring的一個包裝工廠 用於管理真正的ConnectionFactory
public SingleConnectionFactory singleConnectionFactory(ActiveMQConnectionFactory activeMQconnectionFactory) {
SingleConnectionFactory connectionFactory = new SingleConnectionFactory();
//設定目標工廠
connectionFactory.setTargetConnectionFactory(activeMQconnectionFactory);
return connectionFactory;
}
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
// factory.setDestinationResolver(destinationResolver());
factory.setSessionTransacted(true);
factory.setConcurrency("3-10");
return factory;
}
/**
* 1.佇列 點對點 queue
* 2.主題 一對多 topic
*/
@Bean
public ActiveMQQueue queueDestination() {
ActiveMQQueue activeMQQueue = new ActiveMQQueue("queue-anno");
return activeMQQueue;
}
/*@Bean
public ActiveMQTopic topicDestination() {
ActiveMQTopic activeMQTopic = new ActiveMQTopic("topic-anno");
return activeMQTopic;
}*/
}
step5:啟動容器,消費訊息
/**
* @ClassName SpringSender
* @Description
* @Author 歐陽思海
* @Date 2019/8/13 17:22
* @Version 1.0
**/
public class SpringReceiver {
/*
* @Author 歐陽思海
* @Description xml配置方式獲取訊息
* @Date 18:09 2019/8/16
* @Param []
* @return void
**/
@Test
public void test_01() throws IOException {
ApplicationContext application = new FileSystemXmlApplicationContext("G:\\ideaproject\\activemq\\Consumer\\src\\main\\resources\\service-jms.xml");
/*JmsTemplate jmsTemplate = (JmsTemplate) application.getBean("jmsTemplate");
String msg = (String) jmsTemplate.receiveAndConvert();
System.out.println(msg);*/
System.in.read();
}
/*
* @Author 歐陽思海
* @Description 註解方式獲取訊息
* @Date 18:10 2019/8/16
* @Param []
* @return void
**/
@Test
public void test_02() throws IOException {
AnnotationConfigApplicationContext aContext =
new AnnotationConfigApplicationContext(ConsumerConfig.class);
/*JmsTemplate jmsTemplate = (JmsTemplate) application.getBean("jmsTemplate");
String msg = (String) jmsTemplate.receiveAndConvert();
System.out.println(msg);*/
System.in.read();
}
}
終於,到這裡把ActiveMQ整合Spring的全部內容就講述完結了,這一部分講了三個部分,分別是:
- 不使用 Spring 配置檔案方式
- 使用 Spring 配置檔案方式
- 註解方式(0配置)
6 ActiveMQ支援的傳輸協議
6.1 預設協議介紹
在ActiveMQ中支援的協議還是挺多的,這也是ActiveMQ的一個特點之一,例如,預設支援AMQP、MQTT、OpenWire、STOMP、WebSocket,這些預設的協議的配置都是在activemq.xml
配置檔案中的。
<transportConnectors>
<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
注意:上面的每種協議的埠都必須是不一樣的。
6.2 其他協議
除了上面的協議外,還支援這些協議:TCP、UDP 、NIO、SSL、Http(s)、vm
那麼如何使用這些協議呢?
只需要在上面的activemq.xml
配置檔案中的transportConnectors
節點新增就可以,例如,新增 nio協議。
<transportConnectors>
<!-- 新增協議 -->
<transportConnector name="nio" uri="nio://0.0.0.0:61619"/>
<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
其他協議的新增方法也是相似的!
6.3 簡化配置
在ActiveMQ中還有一種更加簡單的配置方法,在uri中可以使用 auto
來簡化配置,ActiveMQ將監聽器埠的訊息自動適配相應的協議。
<transportConnector name="auto" uri="auto://0.0.0.0:61619"/>
如果需要更加安全,還可以在此基礎上新增ssl
協議。
<transportConnector name="auto+ssl" uri="auto+ssl://0.0.0.0:61619"/>
如果還想要提高傳輸的效能,可以配合上面的nio
協議,提高網路效能。
<transportConnector name="auto+nio" uri="auto+nio://0.0.0.0:61619"/>
7 ActiveMQ的持久化儲存機制
持久化的作用是什麼呢?
作用主要是為避免系統以外當機而導致訊息丟失,在ActiveMQ中支援多種持久化機制,比如,JDBC、AMQ、KahaDB、LevelDB,下面簡單介紹一下這幾種機制。
- JDBC:基於資料庫儲存的方式,可以儲存在Mysql等資料庫中,這種機制的效能瓶頸在Mysql等資料庫,所以其效能是不太好的。
配置方法
在activemq.xml
配置檔案中配置,這裡我們使用Mysql進行配置。
step1:修改persistenceAdapter節點
<persistenceAdapter>
<jdbcPersistenceAdapter dataSource="#mysqlDataSource" createTablesOnStartup="true"/>
<!--<kahaDB directory="${activemq.data}/kahadb"/>-->
</persistenceAdapter>
其中,dataSource="#mysqlDataSource"
是資料來源引用。
step2:配置Mysql資料來源
<bean id="mysqlDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
這就是spring的配置方式。
step3:匯入資料庫連線池、驅動等Jar包
在ActiveMQ的目錄中有一個lib目錄,是存放jar包的目錄。
將下面幾個Jar放入。
step4:啟動ActiveMQ,檢視結果
啟動之後,開啟mysql資料庫,發現生成了三張資料表。
這樣就成功了,每次生成訊息之後,就會將訊息的資訊儲存到這三張表中,消費之後,再刪除資訊。
- AMQ:基於檔案儲存,這種方式會把訊息寫入日誌檔案,並且是順序儲存方式,這種方式比JDBC方式要好,缺點是:會為每個Destination建立索引,佔用大量磁碟空間。
配置方法
在activemq.xml
配置檔案中配置,更加詳細引數請參考:https://activemq.apache.org/a...。
<broker brokerName="broker" persistent="true" useShutdownHook="false">
<persistenceAdapter>
<amqPersistenceAdapter directory="資料儲存目錄" maxFileLength="32mb"/>
</persistenceAdapter>
</broker>
- KahaDB:這個5.4版本之後出現的預設的持久化方式,與AMQ很相似,不同的是隻為Destination建立一個索引。
配置方法
在activemq.xml
配置檔案中配置,更加詳細引數請參考:https://activemq.apache.org/k...。
<broker brokerName="broker">
<persistenceAdapter>
<kahaDB directory="資料儲存目錄" journalMaxFileLength="32mb"/>
</persistenceAdapter>
</broker>
- LevelDB:5.6版本後推出的新的持久化方式。這種比KahaDB更快,跟KahaDB類似,但是不是用自定義B數實現。但是需要注意的是,目前官網已經不推薦使用這種方式,而是推薦使用KahaDB。
配置方法
在activemq.xml
配置檔案中配置,更加詳細的引數請參考:https://activemq.apache.org/l...。
<broker brokerName="broker" ... >
...
<persistenceAdapter>
<levelDB directory="資料儲存目錄"/>
</persistenceAdapter>
...
</broker>
8 ActiveMQ網路連線支援
Broker的網路配置主要有三種配置方法,分別是靜態配置、動態配置和主從配置。
8.1 靜態配置
靜態傳輸提供了一種硬編碼機制,可以使用URI列表發現其他連線。使用此發現機制的連線將嘗試連線到列表中的所有URI,直到成功為止。
在activemq.xml配置檔案中配置。
<networkConnectors>
<networkConnector uri="static:(tcp://localhoat:61616)"/>
</networkConnectors>
配置語法
static:(uri1,uri2,uri3,…)?options
舉例
static:(tcp://localhost:61616,tcp://remotehost:61617?trace=false,vm://localbroker)?initialReconnectDelay=100
uri的屬性說明
8.2 動態配置
在activemq.xml配置檔案中配置。
<networkConnectors>
<networkConnector uri="multicast://default"/>
</networkConnectors>
8.3 主從配置
Master-Slave模型是非常常見的,主從模型主要是為了防止一個網路節點出現問題而提出的,提高了穩定性。
在ActiveMQ中也是可配置的,我們可以在activemq.xml配置檔案中進行相關配置。
<networkConnectors>
<networkConnector uri="masterslave:(tcp://host1:61616,tcp://host2:61616,tcp://..)"/>
</networkConnectors>
注意:Master-Slave方式的第一個url需要是master,其他是slave。
另外,NetworkConnector 節點還有其他屬性可以配置,具體詳情可以檢視官網:https://activemq.apache.org/n...。
8.4 容錯的客戶端連線方法
在前面的客戶端連線ActiveMQ的時候只是使用一個簡單的url進行連線。
ActiveMQConnectionFactory activeMQConnectionFactory
= new ActiveMQConnectionFactory("tcp://localhost:61616");
但是,這種方式會出現一個問題,一旦這臺ActiveMQ當機了,就連線不上了,所以,有另外一種容錯的方式,當一臺出現當機,可以連線上其他的機器,這樣就不會出現問題了。
ActiveMQConnectionFactory activeMQConnectionFactory
= new ActiveMQConnectionFactory("failover:(tcp://localhost:61616,tcp://remotehost:61616)");
其他屬性引數請參考:https://activemq.apache.org/f...。