1、ActiveMQ的介绍
ActiveMQ是一种开源的基于JMS(Java Message Servie)规范的一种消息中间件的实现,ActiveMQ的设计目标是提供标准的,面向消息的,能够跨越多语言和多系统的应用集成消息通信中间件
2、ActiveMQ 的作用和应用场景
ActiveMQ常被应用与系统业务的解耦,异步消息的推送,增加系统并发量,提高用户体验。例如以我在工作中的使用,在比较耗时且异步的远程开锁操作时
ActiveMQ的两种消息传递类型
(1)点对点传输:
即一个生产者对应一个消费者,生产者向broke推送数据,数据存储在broke的一个队列中,当消费者接受该条队列里的数据。
(2)基于发布/订阅模式的传输:
即根据订阅话题来接收相应数据,一个生产者可向多个消费者推送数据。
两种消息传递类型的不同,点对点传输消费者可以接收到在连接之前生产者所推送的数据,而基于发布/订阅模式的传输方式消费者只能接收到连接之后生产者推送的数据。
使用
流程:
3、下载、解压、安装、开启、命令、
1.官网下载对应服务器版本
ActiveMQ官方下载地址
可以根据个人情况下载,最好是下载Linux版的,因为我们实际的生产环境是Linux。
2.解压后进入apache-activemq-5.16.0bin目录
解压命令:
tar -zxvf apache-activemq-5.16.0-bin.tar.gz
3.执行./activemq start启动ActiveMQ
在/bin下,命令行执行 ./activemq start
开启ActiveMQ。
可以通过 ./activemq status
查看是否由activemq的服务在进行。
4.登录Activemq的管理web页面
浏览器输入:服务器ip:8161
,我的服务器地址是:192.168.25.134:8161
便可进入activemq的管理界面,点击Manage ActiveMQ broker可以查看消息推送的状态,默认账号密码为admin,admin。
如果在这里无法访问,就是服务器对应的端口开没有打开,activeMQ对应的端口号进行开放。
4、Java的编码
4.1 点对点的消息:
生产者:
package com.example.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class QueueProducer {
public static final String ACTIVE_URL ="tcp://192.168.25.134:61616";
public static final String QUEUE_NAME ="myQueue";
public static void main(String[] args) throws Exception{
// 1.创面连接工厂,按照给定的url地址,采用默认用户名和密码:admin / admin
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVE_URL);
// 2.获取连接
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
// 3.创建会话
// 第一个是是事务,第二个是签收的方式
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 4.创建目的地(具体是队列还是主题topic)
// 该接口Queue是Destination的子接口,
Queue queue = session.createQueue(QUEUE_NAME);
// 5.创建生产者
MessageProducer producer = session.createProducer(queue);
// 6.创建消息并发送
TextMessage textMessage = session.createTextMessage("msg:你能收到吗?");
producer.send(textMessage);
// 8.关闭相关的资源,消息发布就完成了
producer.close();
session.close();
connection.close();
}
}
消费者:
package com.example.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class QueueConsumer {
public static final String ACTIVE_URL ="tcp://192.168.25.134:61616";
public static final String QUEUE_NAME ="myQueue";
public static void main(String[] args)throws Exception {
// 创建连接工厂
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVE_URL);
// 获取连接并开启连接
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
// 创建连接
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建队列Queue
Queue queue = session.createQueue(QUEUE_NAME);
// 创建消费者
MessageConsumer consumer = session.createConsumer(queue);
// 接收消费者获取的消息
TextMessage message = (TextMessage)consumer.receive();
// 输出接收到的消息
System.out.println("接收到的消息"+message.getText());
// 关闭资源
consumer.close();
session.close();
connection.close();
}
}
上面的代码通过MessageConsumer实例的receive()方法来接收消息,该方法是一个阻塞的方法,会一直阻塞,一直等待接收消息。同时我们也可以指定等待的时间,超时就断开连接:
public Message receive(long timeout)
:timeout
指定等待时间,超时断开
除了上面的方式,我们还可以使用监听的形式进行接收消息,也是现在主流在使用的方式,主要的方法是:
void setMessageListener(MessageListener listener)
,MessageListener
:是个函数接口,可以使用Lambda表达式(需要在JDK 8 以上的版本)
package com.example.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class QueueConsumerByListener {
public static final String ACTIVE_URL ="tcp://192.168.25.134:61616";
public static final String QUEUE_NAME ="myQueue";
public static void main(String[] args) throws Exception{
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVE_URL);
Connection connection =activeMQConnectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(QUEUE_NAME);
MessageConsumer consumer = session.createConsumer(queue);
consumer.setMessageListener((message)->{
if(null != message && message instanceof TextMessage){
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("接收到的信息:"+textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
// 通过IO阻塞,防止程序停止,如果进程停止无法接收到信息
System.in.read();
consumer.close();
session.close();
connection.close();
}
}
4.2基于发布/订阅模式的传输
Topic的生产者:
package com.example.activemq.topic;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class TopicProducer {
public static final String ACTIVE_URL ="tcp://192.168.25.134:61616";
public static final String TOPIC_NAME ="myTopic";
public static void main(String[] args)throws Exception {
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVE_URL);
// 获取连接并开启
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
// 创建会话
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic(TOPIC_NAME);
MessageProducer producer = session.createProducer(topic);
// 创建消息并发送
TextMessage textMessage = session.createTextMessage();
textMessage.setText("topic:进行订阅和发布的测试");
producer.send(textMessage);
// 关闭资源
producer.close();
session.close();
connection.close();
}
}
Topic的消费者:
package com.example.activemq.topic;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class TopicConsumerByListener {
public static final String ACTIVE_URL ="tcp://192.168.25.134:61616";
public static final String TOPIC_NAME ="myTopic";
public static void main(String[] args) throws Exception{
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVE_URL);
// 获取连接并开启
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
// 获取会话
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic(TOPIC_NAME);
MessageConsumer consumer = session.createConsumer(topic);
// 通过监听的方式来获取
consumer.setMessageListener((message)->{
if(null != message && message instanceof TextMessage){
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("接收到消息:"+textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
System.in.read();
// 关闭资源
consumer.close();
session.close();
connection.close();
}
}
在该模式下,我们先启动生产者,再启动消费者,会发现消费者是无法接收到之前生产者之前所生产的数据,只有消费者先启动,再让生产者消费才可以正常接收数据。
特点:
-
发布/订阅的主题模式下,需要先订阅,再发布,否则就是一条废消息,与点对点的队列模式的一个明显区别。
-
启动多个消费者,每个消费者都能完整的接收到生产者生产的数据,即每一条数据都被消费了多次(这里的次数和消费者的数量一直),这是发布/订阅的主题模式与点对点的队列模式的另一个明显区别。