ActiveMQ简介
ActiveMQ介绍
MQ是消息中间件,是一种在分布式系统中应用程序借以传递消息的媒介,常用的有ActiveMQ,RabbitMQ,kafka。ActiveMQ是Apache下的开源项目,完全支持JMS1.1和J2EE1.4规范的JMS Provider实现。
特点:
1、支持多种语言编写客户端
2、对spring的支持,很容易和spring整合
3、支持多种传输协议:TCP,SSL,NIO,UDP等
4、支持AJAX
消息形式:
1、点对点(queue)
2、一对多(topic)
作用:
1、削峰
2、异步处理
3、解耦
ActiveMQ生产者实例
注意:消费者和生产者的QUEUE_NAME要一致
package com.at.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class JmsProduce {
// linux 上部署的activemq 的 IP 地址 + activemq 的端口号,如果用自己的需要改动
public static final String ACTIVEMQ_URL = "tcp://192.168.96.134:61616";
// public static final String ACTIVEMQ_URL = "nio://192.168.17.3:61608";
public static final String QUEUE_NAME = "queue";
public static void main(String[] args) throws Exception{
// 1 按照给定的url创建连接工程,这个构造器采用默认的用户名密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
// 设置允许有数据丢失
// activeMQConnectionFactory.setUseAsyncSend(true);
// 2 通过连接工厂连接 connection 和 启动
javax.jms.Connection connection = activeMQConnectionFactory.createConnection();
// 启动
connection.start();
// 3 创建回话 session
// 两个参数,第一个事务, 第二个签收
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
// 4 创建目的地 (两种 : 队列/主题 这里用队列)
Queue queue = session.createQueue(QUEUE_NAME);
// 5 创建消息的生产者
MessageProducer messageProducer = session.createProducer(queue);
// 非持久化消息 和持久化消息演示
messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT); // 持久化 如果开启
// 就会存入文件或数据库中
// 6 通过messageProducer 生产 3 条 消息发送到消息队列中
for (int i = 1; i < 11 ; i++) {
// 7 创建字消息
TextMessage textMessage = session.createTextMessage("msg--" + i);
// 8 通过messageProducer发布消息
messageProducer.send(textMessage);
}
// 9 关闭资源
messageProducer.close();
session.close();
connection.close();
// session.commit();
System.out.println(" **** 消息发送到MQ完成 ****");
}
}
ActiveMQ消费之实例
package com.at.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
// 消息的消费者 也就是回答消息的系统
public class JmsConsumer
{
public static final String ACTIVEMQ_URL = "tcp://192.168.96.134:61616";
// public static final String ACTIVEMQ_URL = "nio://192.168.17.3:61608";
public static final String QUEUE_NAME = "queue";
public static void main(String[] args) throws Exception
{
System.out.println(" 这里是 3 号 消费者 ");
// 1 按照给定的url创建连接工程,这个构造器采用默认的用户名密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
// 2 通过连接工厂连接 connection 和 启动
javax.jms.Connection connection = activeMQConnectionFactory.createConnection();
// 启动
connection.start();
// 3 创建回话 session
// 两个参数,第一个事务, 第二个签收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 4 创建目的地 (两种 : 队列/主题 这里用队列)
Queue queue = session.createQueue(QUEUE_NAME);
// 5 创建消息的消费者
MessageConsumer messageConsumer = session.createConsumer(queue);
// 同步阻塞方式reveive() 空参数的receive方法是阻塞,有参数的为等待时间
// 订阅者或消费者使用MessageConsumer 的receive() 方法接收消息,receive 在接收之前一直阻塞
// while (true)
// {
// // 这里是 TextMessage 是因为消息发送者是 TextMessage , 接受处理的
// // 也应该是这个类型的消息
// TextMessage message = (TextMessage) messageConsumer.receive(4000L); // 4秒
// if (null != message)
// {
// System.out.println("****消费者的消息:" + message.getText());
// }
// else
// {
// break;
// }
// }
// 通过监听的方式来消费消息
// 通过异步非阻塞的方式消费消息
// 通过messageConsumer 的setMessageListener 注册一个监听器,
// 当有消息发送来时,系统自动调用MessageListener 的 onMessage 方法处理消息
messageConsumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
if (null != message && message instanceof TextMessage){
TextMessage textMessage = (TextMessage)message;
try {
System.out.println("****消费者的消息:"+textMessage.getText());
}catch (JMSException e) {
e.printStackTrace();
}
}
}
});
// 保证控制台不灭 不然activemq 还没连上就关掉了连接
System.in.read();
messageConsumer.close();
session.close();
connection.close();
}
}
ActiveMQ消费者分析
在消费者中有两种方法获取生产者中发来的消息:
同步阻塞方法消费信息
// 同步阻塞方式reveive() 空参数的receive方法是阻塞,有参数的为等待时间
// 订阅者或消费者使用MessageConsumer 的receive() 方法接收消息,receive 在接收之前一直阻塞
while (true)
{
// 这里是 TextMessage 是因为消息发送者是 TextMessage , 接受处理的
// 也应该是这个类型的消息
TextMessage message = (TextMessage) messageConsumer.receive(4000L); // 4秒
if (null != message)
{
System.out.println("****消费者的消息:" + message.getText());
}
else
{
break;
}
}
同步阻塞的方法通过一个while循环的方式来获取生产者的产生的消息
异步非阻塞的的方法消费信息
// 通过监听的方式来消费消息
// 通过异步非阻塞的方式消费消息
// 通过messageConsumer 的setMessageListener 注册一个监听器,
// 当有消息发送来时,系统自动调用MessageListener 的 onMessage 方法处理消息
messageConsumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
if (null != message && message instanceof TextMessage){
TextMessage textMessage = (TextMessage)message;
try {
System.out.println("****消费者的消息:"+textMessage.getText());
}catch (JMSException e) {
e.printStackTrace();
}
}
}
});
// 保证控制台不灭 不然activemq 还没连上就关掉了连接
System.in.read();
messageConsumer.close();
session.close();
connection.close();
注意:异步非阻塞是通过监听器的方式获取生产者中的消息。而且需要在关闭连接之前加上System.in.read();,不然还没有消费就直接关闭了连接。但是在同步阻塞的方法中则不需要,
因为在同步阻塞的方法中
messageConsumer.receive(4000L); // 4秒
如果设置了时间则会自动
跳出循环,如果没有设置时间则不会跳出循环。
小总结
如果先启动两个消费者,在启动生产者,那么生产者产生的消息则会默认的被两个消费者进行轮询的方式进行消费。例如我们先启动消费者1和消费者2,然后再启动生产者产生10条消息。代码如下:
消费者1:
****消费者的消息:msg--1
****消费者的消息:msg--3
****消费者的消息:msg--5
****消费者的消息:msg--7
****消费者的消息:msg--9
消费者2:
****消费者的消息:msg--2
****消费者的消息:msg--4
****消费者的消息:msg--6
****消费者的消息:msg--8
****消费者的消息:msg--10
无论是同步阻塞和异步非阻塞都是这种方式。