ActiveMQ
@Author:hanguixian
@Email:[email protected]
三 JAVA編程實現ActiveMQ通訊
1 JMS編程總體架構
2目的地Destination
- 隊列queue
- 主題topic
- 比較
Topic | Queue | |
---|---|---|
工作模式 | 訂閱發佈模式,如果當前沒有訂閱者,消息將會被丟棄。如果有多個訂閱者,那麼這些訂閱者都會收到消息 | 負載均衡模式,如果當前沒有消費者,消息也不會丟棄如果有多個消費者,那麼-條消息也只會發送給其中-個消費者, 並且要求消費者ack信息 |
有無狀態 | 無狀態 | Queue數據默認會在mq服務器上以文件形式保存,比如Active MQ一般保存在${AMQ_ HOME}\data\kr -store\data下面。也可以配置成DB存儲。 |
傳遞完整性 | 如果沒有訂閱者,消息會被丟棄 | 消息不會丟棄 |
處理效率 | 由於消息要按照訂閱者的數量進行復制,所以處理性能會隨着訂閱者的增加而明顯降低,並且還要結合不同消息協議自身的性能差異 | 由於條消息只發送給一個消費者, 所以就算消費者再多,性能也不會有明顯降低。當然不同消息協議的具體性能也是有差異的 |
3 在點對點的消息傳遞域中,目的地被稱爲隊列(Queue)
- 每個消息只能有一個消費者,類似1對1的關係。好比個人快遞自己領取自己的。
- 消息的生產者和消費者之間沒有時間上的相關性。無論消費者在生產者發送消息的時候是否處於運行狀態,消費者都可以提取消息。好比我們的發送短信,發送者發送後不見得接收者會即收即看。
- 消息被消費後隊列中不會再存儲,所以消費者不會消費到已經被消費掉的消息。
4 在發佈訂閱消息傳遞域中,目的地被稱爲主題(topic)
- 生產者將消息發佈到topic中, 每個消息可以有多個消費者,屬於1: N的關係
- 生產者和消費者之間有時間上的相關性。訂閱某一個主題的消費者只能消費自它訂閱之後發佈的消息。
- 生產者生產時,topic不保存消息它是無狀態的不落地,假如無人訂閱就去生產,那就是一條廢消息,所以,一般先啓動消費者再啓動生產者。
- JMS規範允許客戶創建持久訂閱,這在一定程度上放鬆了時間上的相關性要求。持久訂閱允許消費者消費它在未處於激活狀態時發送的消息。好比微信公衆號訂閱
5 入門代碼
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hgx</groupId>
<artifactId>activemq-start</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.10</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
- 隊列queue生產者
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class FirstQueueProvider {
private static final String url = "tcp://xxx:61616";
public static void main(String[] args) throws JMSException {
//1.創建連接工廠,按照給定的URL地址,使用默認的用戶和密碼
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
//2.通過連接工廠獲取connection並訪問
Connection connection = connectionFactory.createConnection();
connection.start();
//3.創建會話session
//兩個參數,第一參數:事務,第二個參數:簽收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4.創建目的地,具體是隊列Queue還是主題topic
Queue queue01 = session.createQueue("queue01");
//5.創建消息的生產者
MessageProducer messageProducer = session.createProducer(queue01);
//6. 通過消息生產者生產消息到MQ
for (int i = 0; i < 3; i++) {
//6.1 創建消息
//文本消息
TextMessage textMessage = session.createTextMessage("hello activeMQ--msg " + i);
//6.2 發送到MQ
messageProducer.send(textMessage);
}
//7.關閉資源
messageProducer.close();
session.close();
connection.close();
System.out.println("消息發送成功************");
}
}
- 隊列queue消費者
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
import java.io.IOException;
public class FirstQueueConsumer {
private static final String url = "tcp://xxx:61616";
public static void main(String[] args) throws JMSException, IOException {
//1.創建連接工廠,按照給定的URL地址,使用默認的用戶和密碼
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
//2.通過連接工廠獲取connection並訪問
Connection connection = connectionFactory.createConnection();
connection.start();
//3.創建會話session
//兩個參數,第一參數:事務,第二個參數:簽收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4.創建目的地,具體是隊列Queue還是主題topic
Queue queue01 = session.createQueue("queue01");
//5.創建消費者
MessageConsumer messageConsumer = session.createConsumer(queue01);
//消費方式1:同步阻塞方式(receive)訂閱者或接收者調用MessageConsumer的receive方法來接收,receive方法在接收到消息之前或超時之前將一直阻塞
// while (true) {
// Message message = messageConsumer.receive(6000);
// if (message instanceof TextMessage) {
// TextMessage textMessage = (TextMessage) message;
// System.out.println(textMessage.getText());
// } else {
// break;
// }
//
// }
//消費方式2:異步非阻塞方式(監聽器onMessage()方法)訂閱者或接收者通過MessageConsumer的setMessageListener註冊監聽器,當消息到達之後,系統自動調用監聽器MessageListener的onMessage方法
messageConsumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
try {
String text = textMessage.getText();
System.out.println(text);
} catch (JMSException e) {
e.printStackTrace();
}
}
}
});
System.in.read();
//關閉資源
messageConsumer.close();
session.close();
connection.close();
}
}
- 主題topic生產者
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class FirstTopicProvider {
private static final String url = "tcp://xxx:61616";
public static void main(String[] args) throws JMSException {
//1.創建連接工廠,按照給定的URL地址,使用默認的用戶和密碼
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
//2.通過連接工廠獲取connection並訪問
Connection connection = connectionFactory.createConnection();
connection.start();
//3.創建會話session
//兩個參數,第一參數:事務,第二個參數:簽收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4.創建目的地,具體是隊列Queue還是主題topic
Topic topic01 = session.createTopic("topic01");
//5.創建消息的生產者
MessageProducer messageProducer = session.createProducer(topic01);
//6. 通過消息生產者生產消息到MQ
for (int i = 0; i < 3; i++) {
//6.1 創建消息
//文本消息
TextMessage textMessage = session.createTextMessage("hello activeMQ--topic msg " + i);
//6.2 發送到MQ
messageProducer.send(textMessage);
}
//7.關閉資源
messageProducer.close();
session.close();
connection.close();
System.out.println("消息發送成功************");
}
}
- 主題topic消費者
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
import java.io.IOException;
public class FirstTopicConsumer {
private static final String url = "tcp://xxx:61616";
public static void main(String[] args) throws JMSException, IOException {
//1.創建連接工廠,按照給定的URL地址,使用默認的用戶和密碼
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
//2.通過連接工廠獲取connection並訪問
Connection connection = connectionFactory.createConnection();
connection.start();
//3.創建會話session
//兩個參數,第一參數:事務,第二個參數:簽收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4.創建目的地,具體是隊列Queue還是主題topic
Topic topic01 = session.createTopic("topic01");
//5.創建消費者
MessageConsumer messageConsumer = session.createConsumer(topic01);
messageConsumer.setMessageListener(message->{
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
try {
String text = textMessage.getText();
System.out.println(text);
} catch (JMSException e) {
e.printStackTrace();
}
}
});
System.in.read();
//關閉資源
messageConsumer.close();
session.close();
connection.close();
}
}