下載ActiveMQ 安裝包
- 下載地址:http://activemq.apache.org/components/classic/download/
2. 解壓
tar -zxvf apache-activemq-5.15.10-bin.tar.gz
- 啓動/stop(./activemq stop)
cd apache-activemq-5.15.10/bin
./activemq start
- 檢查啓動是否完成
netstat -anp | grep 61616
- 登陸界面
ip:8161/admin
- 修改賬號密碼
修改控制檯密碼:
conf/jetty-realm.properties
- 新增賬號密碼
activema.xml 新增賬號密碼(broker 標籤下添加)
- MQS 消息流程
生產者/消費者模式
- 依賴:
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-activemq -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
- 創建生產者
private static void pointToPoint() throws Exception {
// 第一步:建立connectionFactory 工廠對象,需要用戶名,密碼,連接地址,均可採取默認
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_USER, ActiveMQConnectionFactory.DEFAULT_PASSWORD, "tcp://192.168.203.132:61616");
// 第二步: 通過connectionfactory 對象創建一個連接,並且調用connectionfactory 的start 方法
Connection connection = connectionFactory.createConnection();
connection.start();
// 第三步: 通過connection對象創建session 會話,(上下文環境對象),用於接受消息,參數配置1 爲是否啓用事務,參數配置2 爲簽收模式,
// 一般爲自動簽收
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
// 第四步: 通過session 創建destination 對象,一個客戶端來指定生產消息目標和消費信息來源的對象
// 在PTP模式中,Destination被稱作Queue即隊列;在Pub/Sub模式,Destination被稱作Topic即主題。
// 在程序中可以使用多個Queue和Topic
Queue queue1 = session.createQueue("queue1");
// Topic topic = session.createTopic("topic");
// session.createDurableConsumer(topic);
// 第五步 通過session 對象創建消息發送和接收對象(生產者,消費者)
MessageProducer producer = session.createProducer(queue1);
// 第六步 通過producer 的setDeliveryMode 方法設置持久化特性 和費持久化特性(DeliveryMode)
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// 第七步 使用KMS 規範的TextMessage 形式創建數據(通過session對象),
// 通過producer 的send 方法發送數據,recevice 接收消息 關流
for (int i = 0; i < 100; i++) {
TextMessage textMessage = session.createTextMessage();
textMessage.setText("消息有效級別 queue-----:" + i);
producer.send(textMessage);
System.err.println("生產者---" + i);
}
Thread.sleep(100000);
if (null != connection) {
connection.close();
}
}
- 創建消費者
public void consumerMessage() throws Exception {
// 第一步:建立connectionFactory 工廠對象,需要用戶名,密碼,連接地址,均可採取默認
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_USER, ActiveMQConnectionFactory.DEFAULT_PASSWORD, "tcp://192.168.203.132:61616");
// 第二步: 通過connectionfactory 對象創建一個連接,並且調用connectionfactory 的start 方法
Connection connection = connectionFactory.createConnection();
connection.start();
// 第三步: 通過connection對象創建session 會話,(上下文環境對象),用於接受消息,參數配置1 爲是否啓用事務,參數配置2 爲簽收模式,
// 一般爲自動簽收
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
// 第四步: 通過session 創建destination 對象,一個客戶端來指定生產消息目標和消費信息來源的對象
// 在PTP模式中,Destination被稱作Queue即隊列;在Pub/Sub模式,Destination被稱作Topic即主題。
// 在程序中可以使用多個Queue和Topic
Queue queue1 = session.createQueue("queue1");
// 第五步 創建消費者
MessageConsumer consumer = session.createConsumer(queue1);
while (true) {
TextMessage receive = (TextMessage) consumer.receive();
if (null == receive) {
break;
}
System.out.println(receive.getText() + ">>>>>>>>" + number);
}
if (null != connection) {
connection.close();
}
}
- Springboot 模板創建消費者,生產者
配置文件:
spring:
#config:
# location: classpath:spring-beans.xml
activemq:
broker-url: tcp://192.168.203.132:61616
user: admin
password: admin
pool:
enabled: false
queueName: queue1
- 生產者/消費者代碼
@Service
public class ProducerService {
@Resource
private JmsMessagingTemplate jmsMessagingTemplate;
@Value("${spring.activemq.queueName}")
private String destinationName;
// 生產者
public void sendMess(String message) throws Exception{
System.out.println("send message>>>>>");
Destination activeMQQueue = new ActiveMQQueue(destinationName);
jmsMessagingTemplate.convertAndSend(activeMQQueue,message);
}
// 消費者
@JmsListener(destination = "queue1")
public void consumerMsg(String text){
System.out.println("query text:???"+text);
}
}
生產/消費模式下,消息發出後會存放在隊列中,等待消費者消費。一個消費只能被消費一次.
發佈/訂閱模式
- 發佈話題
private static void submationPubsubtion() throws Exception {
// 第一步:建立connectionFactory 工廠對象,需要用戶名,密碼,連接地址,均可採取默認
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_USER, ActiveMQConnectionFactory.DEFAULT_PASSWORD, "tcp://192.168.203.132:61616");
// 第二步: 通過connectionfactory 對象創建一個連接,並且調用connectionfactory 的start 方法
Connection connection = connectionFactory.createConnection();
connection.start();
// 第三步: 通過connection對象創建session 會話,(上下文環境對象),用於接受消息,參數配置1 爲是否啓用事務,參數配置2 爲簽收模式,
// 一般爲自動簽收
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
// 第四步: 通過session 創建destination 對象,一個客戶端來指定生產消息目標和消費信息來源的對象
// 在PTP模式中,Destination被稱作Queue即隊列;在Pub/Sub模式,Destination被稱作Topic即主題。
// 在程序中可以使用多個Queue和Topic
Topic topic = session.createTopic("你是哪個");
// 第五步 通過session 對象創建消息發送和接收對象(生產者,消費者)
MessageProducer producer = session.createProducer(topic);
// 第六步 通過producer 的setDeliveryMode 方法設置持久化特性 和費持久化特性(DeliveryMode)
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// 第七步 使用KMS 規範的TextMessage 形式創建數據(通過session對象),
// 通過producer 的send 方法發送數據,recevice 接收消息 關流
for (int i = 0; i < 100; i++) {
TextMessage textMessage = session.createTextMessage();
textMessage.setText("消息有效級別 topic-----:" + i);
producer.send(textMessage);
System.err.println("生產者---" + i);
}
Thread.sleep(100000);
if (null != connection) {
connection.close();
}
}
- 訂閱話題
public void consumerMessageTopic() throws Exception {
// 第一步:建立connectionFactory 工廠對象,需要用戶名,密碼,連接地址,均可採取默認
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_USER, ActiveMQConnectionFactory.DEFAULT_PASSWORD, "tcp://192.168.203.132:61616");
// 第二步: 通過connectionfactory 對象創建一個連接,並且調用connectionfactory 的start 方法
Connection connection = connectionFactory.createConnection();
connection.start();
// 第三步: 通過connection對象創建session 會話,(上下文環境對象),用於接受消息,參數配置1 爲是否啓用事務,參數配置2 爲簽收模式,
// 一般爲自動簽收
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
// 第四步: 通過session 創建destination 對象,一個客戶端來指定生產消息目標和消費信息來源的對象
// 在PTP模式中,Destination被稱作Queue即隊列;在Pub/Sub模式,Destination被稱作Topic即主題。
// 在程序中可以使用多個Queue和Topic
Topic topic = session.createTopic("你是哪個");
// 第五步 創建消費者
MessageConsumer consumer = session.createConsumer(topic);
while (true) {
TextMessage receive = (TextMessage) consumer.receive();
if (null == receive) {
break;
}
System.out.println(receive.getText() + ">>>>>>>>" + number);
}
if (null != connection) {
connection.close();
}
}
- Springboot 發佈訂閱模式
/ 發佈訂閱模式, 發佈者
public void publish(String message)
{
Destination destination = new ActiveMQTopic(destinationName);
jmsMessagingTemplate.convertAndSend(destinationName,message);
}
@JmsListener(destination = "topic.name",containerFactory ="jmsListenerContainerFactory" )
public void consumer(String text)
{
System.out.println("<<<<<"+text);
}
// 發佈訂閱需要對containerFactory 進行配置
@Bean(name = "jmsListenerContainerFactory")
JmsListenerContainerFactory jmsListenerContainerFactory(ConnectionFactory connectionFactory){
SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setPubSubDomain(true);
return factory;
}
有多個消息接收者時,生產/消費模式下多個消費者會輪流消費隊列中的消息,消息會存儲在隊列中,等待被消費。而pub/sub模式下所有訂閱者都會得到所有的消息。並且訂閱需要在發佈之前,否則不能消費到訂閱之前發佈者發佈的消息
權限設置,認證與授權
在配置文件中加activema.xml 新增賬號密碼(broker 標籤下添加)
具體的權限配置: http://activemq.apache.org/security.html
<broker>
..
<plugins>
..
<authorizationPlugin>
<map>
<authorizationMap>
<authorizationEntries>
<authorizationEntry queue="TEST.Q" read="users" write="users" admin="users" />
<authorizationEntry topic="ActiveMQ.Advisory.>" read="all" write="all" admin="all"/>
</authorizationEntries>
<tempDestinationAuthorizationEntry>
<tempDestinationAuthorizationEntry read="admin" write="admin" admin="admin"/>
</tempDestinationAuthorizationEntry>
</authorizationMap>
</map>
</authorizationPlugin>
..
</plugins>
..
</broker>
每個authorizationEntry配置都有read、write和admin屬性,分別對應讀取、寫入和管理。read、write和admin的值爲在認證中用戶對應的groups屬性中的值
消息有兩種queue和topic,其中read、write、admin用戶指定用戶組,其中conf/groups.properties中文件
admins=admin
users=user,publisher,consumer,guest
等號前時候組名,等號後是用戶列表,多個用戶之間用","分割
<authorizationEntry queue="TEST.Q" read="users" write="users" admin="users" />
對應以TEST.Q開頭的消息隊列
修改配置文件,每次請求過來都會自動更新配置文件:
**設置reload=true **
vim login.config
activemq {
org.apache.activemq.jaas.PropertiesLoginModule required
org.apache.activemq.jaas.properties.user="users.properties"
org.apache.activemq.jaas.properties.group="groups.properties" reload=true;
};
2.1 將用戶名、密碼 寫入activemq.xml 文件
<simpleAuthenticationPlugin>
<users>
<authenticationUser username="admin" password="password"
groups="admins,publishers,consumers"/>
<authenticationUser username="publisher" password="password"
groups="publishers,consumers"/>
<authenticationUser username="consumer" password="password"
groups="consumers"/>
<authenticationUser username="guest" password="password"
groups="guests"/>
</users>
</simpleAuthenticationPlugin>
2.2 使用 redentials.properties存儲明文憑證,plugins 讀取配置。
<plugins>
<simpleAuthenticationPlugin>
<users>
<authenticationUser username="${activemq.username}" password="${activemq.password}" groups="users, admins" />
</users>
</simpleAuthenticationPlugin>
</plugins>
修改配置
vim credentials.properties
我們可以使用變量的方式引用該文件內部的屬性 groups=“users, admins” 表示定義用戶所屬的用戶組, activemq按照用戶組分配權限,注意不能刪除groups屬性,可以置空。
1、 優先級高於,如果配置了 那麼用戶的驗證授權信息將從user.properties和group.properties文件中進行加載;如果只配置那麼用戶的驗證與授權信息直接從子節點authenticationUser中進行定義,此時用戶的信息也可以存放在conf/credentials.properties文件中,通過${}進行加載即可。
2、如果配置那麼conf/login.config中節點名稱一定要爲activemq-domain,否則在發送或是接收消息時會拋出
Caused by: javax.security.auth.login.LoginException: No LoginModules configured for activemq-domain