在linux上,消息中间件ActiveMQ的入门教程
一、ActiveMQ入门
1.登录到ActiveMQ的官网,下载安装包。http://activemq.apache.org/
![570da9e3c4e3451d8671837e3ba030cf.png](https://i-blog.csdnimg.cn/blog_migrate/9ebf13cb7a076eec10ea45dd4d4f95dd.jpeg)
2.下载linux版本的压缩文件
![49e8bb6c4d40eef8a0ead6930dc40562.png](https://i-blog.csdnimg.cn/blog_migrate/f1a43815b92fa74c60925a835a7bfc0b.jpeg)
3.将下载好的apache-activemq-5.15.10-bin.tar.gz上传到linux目录中,可以自己创建。我的是usr/local/ActiveMQ目录中,解压命令
tar -zxvf apache-activemq-5.15.10-bin.tar.gz
![0085dd008874c06103115be600108014.png](https://i-blog.csdnimg.cn/blog_migrate/e128e1209fdf6cf876eb136a54f3c0cf.png)
为了简化名字,改为activemq。命令:
mv apache-activemq-5.15.10 activemq
最好是将解压的的文件放在一个位置中,推荐/usr/local/activemq
![8034fafbe294ec64736ddb67e40a042d.png](https://i-blog.csdnimg.cn/blog_migrate/8ff194a9097d82a5d4f6d11cb07e5964.png)
![3a3ef6c57a18116f7f118878004a4c8f.png](https://i-blog.csdnimg.cn/blog_migrate/c122332a92d0fad2292b51abe61dd27d.png)
解压文件目录:
![0f7f399cc60337a6aeb33bb111a383f8.png](https://i-blog.csdnimg.cn/blog_migrate/f442734a7c81f3d66cdd3b9bcacb19bd.jpeg)
4.进入到bin目录中,启动ActiveMQ,命令:
./activemq start
可以通过 :
ps aux|grep activemq
查询是否已经ActiveMQ启动了
5.通过浏览器访问:http://IP地址/admin/ ,在这里浏览器会弹出一个用户登录框,默认是用户和密码都是admin。
![0d0238b31788e15c9452704c5716250c.png](https://i-blog.csdnimg.cn/blog_migrate/747ba3d4c64f513e0ff08d19d68251ce.jpeg)
出现如下界面,则ActiveMQ启动成功了。
二、ActiveMQ的术语
1.什么是中间件:
非操作系统软件,非业务应用软件,不是直接给最终用户使用,不能直接给用户带来价值的软件,我们就可以称为中间件(比如Dubbo,Tomcat,Jetty,Jboss都是属于的)。
2.什么是消息中间件? 百度百科解释:消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间的通信。 关键点:关注于数据的发送和接受,利用高效可靠的异步消息机制传递机制集成分布式系统。 先简单的用下面这个图说明:
![97426e4cf3eacbed9e395890c49b2a86.png](https://i-blog.csdnimg.cn/blog_migrate/65d0c7c84767cd45dbea00c521913c4e.jpeg)
3.什么是JMS? Java消息服务(Java Message Service)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。 总结起来说就是:Java对于应用程序之间进行信息交互的API(而且是异步)。
先解释一下同步和异步:
![0062c1330a2d7b9e407ca0da9fb3dd47.png](https://i-blog.csdnimg.cn/blog_migrate/861a72270704b78dd0428aa9d71cb78b.jpeg)
里面有下面的概念需要理解,对后续有帮助:
提供者:实现JMS的消息服务中间件服务器。
客户端:发送或接受消息的应用。
生产者/发布者:创建并发送消息的客户端。
消费者/订阅者:接受并处理消息的客户端。
消息:应用程序之间传递的数据。
消息模式:在客户端之间传递消息的模式,JMS主要是队列模式和主体模式。
队列模式特点: (1)客户端包括生产者和消费者。 (2)队列中的一个消息只能被一个消费者使用。 (3)消费者可以随时取消息。
主体模式特点: (1)客户端包括发布者和订阅者。 (2)主题中的消息可以被所有订阅者消费。 (3)消费者不能消费订阅之前发送的消息。 4.在来了解一下jms中的一些关键接口:
ConnectionFactory:用于创建连接到消息中间件的连接工厂。
Connection:代表了应用程序和服务之间的连接通路。 Destination:指消息发布的地点,包括队列模式和主体模式。 Session:表示一个单线程的上下文,用于发送和接受消息。 MessageConsumer:由会话创建,用于接受发送到目的的消息。 MessageProducer:由会话创建,用于发送消息。 Message:是在消费者和生产者之间传递的对象,消息头,一组消息属性,和一个消息体。
![4dd12e9356f2ad4cf47079049247a09f.png](https://i-blog.csdnimg.cn/blog_migrate/6328f87628c76aace9b079379fbdfa3e.jpeg)
5.通过代码来演示队列模式和主体模式
1.创建一个maven(MQ-producer)工程,为模拟为生产者,添加ActiveMQ的依赖,注意你下载的ActiveMQ的版本:我下载是5.15.10,
<dependencies>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.10</version>
</dependency>
</dependencies>
2.在创建一个maven(MQ-consumer)工程,为模拟消费者,添加ActiveMQ的jar依赖,同上。、
代码示例:
public class MQProducer {
public static void main(String[] args) {
sendHelloWorldActiveMQ("我是ActiveMQ");
}
//创建消息生产者
public static void sendHelloWorldActiveMQ(String msg) {
ConnectionFactory connectionFactory = null;
Connection connection = null;
Session session = null;
Destination destination = null;
MessageProducer messageProducer = null;
Message message = null;
try {
//访问ActiveMQ服务的用户名,用户密码,都是默认为admin,用户名可以通过jetty-ream.properties文件进行修改
//brokerURL:访问地址 协议名://ip地址+端口号
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.171.138:61616");
connection = connectionFactory.createConnection();
//创建连接
connection.start();
//transacted:是否使用事务 true|false true表示使用事务,当设置为true时,当这是次变量值。 Session.SESSION_TRANSACTED
//false :不适用事务,设置次变量 则 acknowledgeMode必须设置
//acknowledgeMode:
/*
* Session.AUTO_ACKNOWLEDGE 自动消息确认机制
* Session.CLIENT_ACKNOWLEDGE 客户端确认消息机制
* Session.DUPS_OK_ACKNOWLEDGE 有副本的客户端确认消息机制
*/
// session = connection.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
//创建目的地,目的地即为队列的名称
destination = session.createQueue("HelloWorld-mq");
//创建消息的生产者
messageProducer = session.createProducer(destination);
//创建文本
message = session.createTextMessage(msg);
//发送消息
messageProducer.send(message);
}catch(Exception e) {
e.printStackTrace();
} finally {
//关闭资源
if(messageProducer != null) {
try {
messageProducer.close();
} catch (JMSException e) {
e.printStackTrace();
} finally {
if(session != null) {
try {
session.close();
} catch (JMSException e) {
e.printStackTrace();
} finally {
if(connection != null) {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
}
}
}
}
}
public class MQConsumer {
public static void main(String[] args) {
ReceiveHelloWorldActiveMQ();
}
//消息消费者
public static void ReceiveHelloWorldActiveMQ() {
ConnectionFactory connectionFactory = null;
Connection connection = null;
Session session = null;
Destination destination = null;
MessageConsumer messageConsumer = null;
Message message = null;
try {
//访问ActiveMQ服务的用户名,用户密码,都是默认为admin,用户名可以通过jetty-ream.properties文件进行修改
//brokerURL:访问地址 协议名://ip地址+端口号
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.171.138:61616");
connection = connectionFactory.createConnection();
//创建连接
connection.start();
//transacted:是否使用事务 true|false true表示使用事务,当设置为true时,当这是次变量值。 Session.SESSION_TRANSACTED
//false :不适用事务,设置次变量 则 acknowledgeMode必须设置
//acknowledgeMode:
/*
* Session.AUTO_ACKNOWLEDGE 自动消息确认机制
* Session.CLIENT_ACKNOWLEDGE 客户端确认消息机制
* Session.DUPS_OK_ACKNOWLEDGE 有副本的客户端确认消息机制
*/
// session = connection.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
//创建目的地,目的地即为队列的名称
destination = session.createQueue("HelloWorld-mq");
//创建消息的消费者
messageConsumer = session.createConsumer(destination);
//创建消息对象
message = messageConsumer.receive();
//处理消息
String text = ((TextMessage)message).getText();
System.out.println("从ActiveMQ中或者的消息: "+ text);
}catch(Exception e) {
e.printStackTrace();
} finally {
//关闭资源
if(messageConsumer != null) {
try {
messageConsumer.close();
} catch (JMSException e) {
e.printStackTrace();
} finally {
if(session != null) {
try {
session.close();
} catch (JMSException e) {
e.printStackTrace();
} finally {
if(connection != null) {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
}
}
}
}
}
先执行生产者代码:在查看消息是否产生成功:
![49e8bb6c4d40eef8a0ead6930dc40562.png](https://i-blog.csdnimg.cn/blog_migrate/f1a43815b92fa74c60925a835a7bfc0b.jpeg)
生成了一条消息。
在执行消费者代码,在查看消息是否被消费
![a3a2cb22037ff1dd91d8a18612afbb22.png](https://i-blog.csdnimg.cn/blog_migrate/f61ee00bca594c3cff68f5a8c0cae0d6.jpeg)
![aadd2893be90ae92b72f451204388220.png](https://i-blog.csdnimg.cn/blog_migrate/90f6f869cf96d0977cbeb9d22a30f321.jpeg)
生产者发送的一条消息被打印。
上面演示的就是消费队列模型,一对一。
下面演示一对多,主题模型,代码跟上面基本一致,只需稍加改动即可。
public class MQProducer4 {
public static void main(String[] args) {
sendHelloWorldActiveMQ("我是ActiveMQ111");
}
//创建消息消费者
public static void sendHelloWorldActiveMQ(String msg) {
ConnectionFactory connectionFactory = null;
Connection connection = null;
Session session = null;
Destination destination = null;
MessageProducer messageProducer = null;
Message message = null;
try {
//访问ActiveMQ服务的用户名,用户密码,都是默认为admin,用户名可以通过jetty-ream.properties文件进行修改
//brokerURL:访问地址 协议名://ip地址+端口号
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.171.138:61616");
connection = connectionFactory.createConnection();
//创建连接
connection.start();
//transacted:是否使用事务 true|false true表示使用事务,当设置为true时,当这是次变量值。 Session.SESSION_TRANSACTED
//false :不适用事务,设置次变量 则 acknowledgeMode必须设置
//acknowledgeMode:
/*
* Session.AUTO_ACKNOWLEDGE 自动消息确认机制
* Session.CLIENT_ACKNOWLEDGE 客户端确认消息机制
* Session.DUPS_OK_ACKNOWLEDGE 有副本的客户端确认消息机制
*/
// session = connection.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
//创建目的地,目的地即为队列的名称
destination = session.createTopic("destination-mq-topic");
//创建消息的生产者
messageProducer = session.createProducer(destination);
//创建文本
message = session.createTextMessage(msg);
//发送消息
messageProducer.send(message);
}catch(Exception e) {
e.printStackTrace();
} finally {
//关闭资源
if(messageProducer != null) {
try {
messageProducer.close();
} catch (JMSException e) {
e.printStackTrace();
} finally {
if(session != null) {
try {
session.close();
} catch (JMSException e) {
e.printStackTrace();
} finally {
if(connection != null) {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
}
}
}
}
}
public class MQConsumerTopic1 implements Runnable {
public static void main(String[] args) {
// ReceiveHelloWorldActiveMQ();
MQConsumerTopic1 consumer4 = new MQConsumerTopic1();
MQConsumerTopic2 consumer42 = new MQConsumerTopic2();
MQConsumerTopic3 consumer43 = new MQConsumerTopic3();
new Thread(consumer4).start();
new Thread(consumer42).start();
new Thread(consumer43).start();
}
//消息消费者
public static void ReceiveHelloWorldActiveMQ() {
ConnectionFactory connectionFactory = null;
Connection connection = null;
Session session = null;
Destination destination = null;
MessageConsumer messageConsumer = null;
Message message = null;
try {
//访问ActiveMQ服务的用户名,用户密码,都是默认为admin,用户名可以通过jetty-ream.properties文件进行修改
//brokerURL:访问地址 协议名://ip地址+端口号
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.171.138:61616");
connection = connectionFactory.createConnection();
//创建连接
connection.start();
//transacted:是否使用事务 true|false true表示使用事务,当设置为true时,当这是次变量值。 Session.SESSION_TRANSACTED
//false :不适用事务,设置次变量 则 acknowledgeMode必须设置
//acknowledgeMode:
/*
* Session.AUTO_ACKNOWLEDGE 自动消息确认机制
* Session.CLIENT_ACKNOWLEDGE 客户端确认消息机制
* Session.DUPS_OK_ACKNOWLEDGE 有副本的客户端确认消息机制
*/
// session = connection.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
//创建目的地,目的地即为队列的名称
destination = session.createTopic("destination-mq-topic");
//创建消息的消费者
messageConsumer = session.createConsumer(destination);
messageConsumer.setMessageListener(new MessageListener() {
//ActiveMQ回调方法,通过该方法将消息传递到messageConsumer
@Override
public void onMessage(Message message) {
//处理消息
try {
String text = ((TextMessage)message).getText();
System.out.println("从ActiveMQ中或者的消息 : ---1"+text);
} catch (JMSException e) {
e.printStackTrace();
}
}
});
}catch(Exception e) {
e.printStackTrace();
}
}
@Override
public void run() {
ReceiveHelloWorldActiveMQ();
}
}
其余两个消费者代码,不展示,跟上面的一样,通过多线程来模拟多个消费者。
切记:主题模型,必须先有消费者,否则消息是接受不到的。
![30d1469caa3bb3b0398fc49d3455c8a4.png](https://i-blog.csdnimg.cn/blog_migrate/12fad93185308900eb65e3f3f20d0905.jpeg)
开启三个消费者
![2cc390537f3e3fc29a7ac1d4fe8b587e.png](https://i-blog.csdnimg.cn/blog_migrate/95b9467446b89844793d23934839e8bc.jpeg)
开启一个生产者
![ee594b63de36c79b032a8f086e1709a8.png](https://i-blog.csdnimg.cn/blog_migrate/b2d1b20c784de2374b5d44c667aabfb8.jpeg)