一、引言
1.实验目的
1、理解消息中间件编程,并选择一个中间件平台(ActiveMQ),介绍其基本原理,编程方法(介绍案例),并进行应用开发(最好与spring开发结合起来)。
2、应用开发:模拟多个10000个节点的消息传递和订阅关系。
选择生产者和订阅者的数量,分别为n1和n2;
指定n1和n2的订阅关系S;【多对多的关系,且可根据规则进行内容的筛选】
模拟n1产生内容的情形。调整n1,n2,以及S,分析整个系统的运行效率。
2.环境配置
- 操作系统:Windows 10 X64
- 编程工具:Intellij IDEA 2019.2×64
二、ActiveMQ介绍
1.概述
ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。在介绍activemq之前,先简单介绍JMS,它是J2EE的13个规范之一,提供的是消息中间件的规范。
(1)JMS简介
JMS包括以下基本构件:
1、连接工厂:是客户用来创建连接的对象,ActiveMQ提供的是ActiveMQConnectionFactory;
2、连接connection;
3、会话session,是发送和接收消息的上下文,用于创建消息生产者,消息消费者,相比rocketMQ会话session是提供事务性的;
4、目的地destination,指定生产消息的目的地和消费消息的来源对象;
5、生产者,由会话创建的对象。
6、消费者,由会话创建的对象。
(2)消息通信机制
1、点对点模式,每个消息只有1个消费者,它的目的地称为queue队列;
2、发布/订阅模式,每个消息可以有多个消费者,而且订阅一个主题的消费者,只能消费自它订阅之后发布的消息。
3、消息确认机制
(1)Session.AUTO_ACKNOWLEDGE,直接使用receive方法。Session.CLIENT_ACKNOWLEDGE,通过消息的acknowledge 方法确认消息。
(2)Session.DUPS_ACKNOWLEDGE,该选择只是会话迟钝第确认消息的提交。如果JMS provider 失败,那么可能会导致一些重复的消息。如果是重复的消息,那么JMS provider 必须把消息头的JMSRedelivered 字段设置为true。
2.安装
(1)在清华镜像下载
下载地址:https://mirrors.tuna.tsinghua.edu.cn/apache/activemq/5.15.12/
win10可以下载第三个,5.15.12版本:
(2)下载完解压完目录如下
(3)启动ActiveMQ服务
在解压目录下的bin/win64,右键以管理员身份运行activemq.bat
(4)登录,验证是否启动成功
(5)进入管理页面
用户名和密码都是admin
管理页面如下:
3.案例实现(点对点模式)
(1)导入pom依赖
<dependencies>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.12</version>
</dependency>
</dependencies>
(2)创建生产者
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
/**
* @Author Administrator
* @Description: IntelliJ IDEA
* @create 2020/5/1218:17
*/
public class MqQueueProduct {
private static final String url="tcp://127.0.0.1:61616";//服务地址,端口默认61616
private static final String queueName="queue-test";//要创建的消息名称
public static void main(String[] args) throws JMSException {
//1.创建ConnectiongFactory,绑定地址
ConnectionFactory factory=new ActiveMQConnectionFactory(url);
//2.创建Connection
Connection connection= factory.createConnection();
//3.启动连接
connection.start();
//4.创建会话
Session session=connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//5.创建一个目标
Destination destination=session.createQueue(queueName);
//6.创建一个生产者
MessageProducer producer=session.createProducer(destination);
for (int i = 0; i < 20; i++) {
//7.创建消息
TextMessage textMessage=session.createTextMessage("我是消息生产者:"+i);
//8.发送消息
producer.send(textMessage);
System.out.println("发送消息:"+i);
}
connection.close();
}
}
运行:
在ActiveMQ的Queues中查看,消息队列中有了20个消息:
(3)创建消费者
import javax.jms.*;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
* @Author Administrator
* @Description: IntelliJ IDEA
* @create 2020/5/1218:29
*/
public class MqQueueConsumer {
private static final String url="tcp://127.0.0.1:61616";//端口默认
private static final String queueName="queue-test";//要消费的消息名称
public static void main(String[] args) throws JMSException {
//1.创建ConnectiongFactory,绑定地址
ConnectionFactory factory=new ActiveMQConnectionFactory(url);
//2.创建Connection
Connection connection= factory.createConnection();
//3.启动连接
connection.start();
//4.创建会话
Session session=connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//5.创建一个目标
Destination destination=session.createQueue(queueName);
//6.创建一个消费者
MessageConsumer consumer=session.createConsumer(destination);
//7.创建一个监听器
consumer.setMessageListener(new MessageListener() {
public void onMessage(Message arg0) {
TextMessage textMessage=(TextMessage)arg0;
try {
System.out.println("接收消息:"+textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
}
}
运行:
查看ActiveMQ的queues,可以看到生产者的消息被消费者接收了:
三、应用开发(和Spring结合)
模拟多个10000个节点的消息传递和订阅关系。(发布/订阅模式)
Subscriber只有在订阅了主题Topic后,才能接收到Publisher发送的消息。这种关系如下图所示:
(1)创建生产者
import javax.jms.*;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
* @Author Administrator
* @Description: IntelliJ IDEA
* @create 2020/5/1313:20
*/
public class MqTopicProduct {
private static final String url="tcp://127.0.0.1:61616";//服务地址,端口默认61616
private static final String topicName="topic-test";//要创建的消息名称
public static void main(String[] args) throws JMSException {
//1.创建ConnectiongFactory,绑定地址
ConnectionFactory factory=new ActiveMQConnectionFactory(url);
//2.创建Connection
Connection connection= factory.createConnection();
//3.启动连接
connection.start();
//4.创建会话
Session session=connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//5.创建一个目标
Destination destination=session.createTopic(topicName);
//6.创建一个生产者
MessageProducer producer=session.createProducer(destination);
for (int i = 0; i < 10000; i++) {
//7.创建消息
TextMessage textMessage=session.createTextMessage("我是消息生产者:"+i);
//8.发送消息
producer.send(textMessage);
System.out.println("发送消息:"+i);
}
connection.close();
}
}
运行:
查看ActiveMQ的Topics,可以看到消息队列中有10000条消息:
(2)创建消费者
import javax.jms.*;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
* @Author Administrator
* @Description: IntelliJ IDEA
* @create 2020/5/1313:18
*/
public class MqTopicConsumer {
private static final String url="tcp://127.0.0.1:61616";//端口默认
private static final String topicName="topic-test";//要消费的消息名称
public static void main(String[] args) throws JMSException {
//1.创建ConnectiongFactory,绑定地址
ConnectionFactory factory=new ActiveMQConnectionFactory(url);
//2.创建Connection
Connection connection= factory.createConnection();
//3.启动连接
connection.start();
//4.创建会话
Session session=connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//5.创建一个目标
Destination destination=session.createTopic(topicName);
//6.创建一个消费者
MessageConsumer consumer=session.createConsumer(destination);
//7.创建一个监听器
consumer.setMessageListener(new MessageListener() {
public void onMessage(Message arg0) {
TextMessage textMessage=(TextMessage)arg0;
try {
System.out.println("接收消息:"+textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
}
}
运行:
查看ActiveMQ的Topics,可以看到发布者发布的消息被接收(订阅)了:
四、ActiveMQ与其他平台的差异介绍
1、开发语言方面:ActiveMQ和RocketMQ主要为java,RabbitMQ是Erlang,Kafka用的是Scala
2、资料文档方面:ActiveMQ和RabbitMQ参考资料多,Kafka中等,RocketMQ参考资料较少
3、支持的协议方面:ActiveMQ:OpenWire、STOMP、REST、XMPP、AMQP;Kafka:自己定义的一套,基于TCP;RabbitMQ:AMQP;RocketMQ:自己定义的一套
4、数据存储方面:ActiveMQ:内存、磁盘、数据库。支持少量堆积。Kafka:内存、磁盘、数据库。支持大量堆积。RabbitMQ:内存、磁盘。支持少量堆积。RocketMQ:磁盘。支持大量堆积。
5、总体上看:ActiveMQ基于java开发,是已经很完备消息队列,非常稳定,大多数的解决方案网上都能找到,缺点是吞吐量相比RocketMQ,Kafka还不够大,并且版本现在更新的很慢了,社区不活跃,RabbitMQ用的Erlang开发,并发超强,但不好定制化。
五、总结
1、在做应用开发(发布/订阅模式)的时候,这个模式和点对点模式不同,它需要先运行消费者再运行生产者,消费者才能接受到消息。
2、队列模式(点对点)的消费者在运行后也能收到之前的消息,不过属于轮流进行消费,每个消费者接收不到完整的消息。
3、主题模式(发布/订阅)的消费者在运行后只能收到之后的消息,运行之前生产的消息接收不到;并且每个消费者都能接收全部的消息。