初识ActiveMQ
消息中间件的初步认识
什么是消息中间件?
消息中间件是利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,可以在分布式架构下扩展进程之间的通信。
消息中间件能做什么?
消息中间件主要解决的就是分布式系统之间消息传递的问题,它能够屏蔽各种平台以及协议之间的特性,实现应用程序之间的协同。举个非常简单的例子,就拿一个电商平台的注册功能来简单分析下,用户注册这一个服务,不单单只是 insert 一条数据到数据库里面就完事了,还需要发送激活邮件、发送新人红包或者积分、发送营销短信等一系列操作。假如说这里面的每一个操作,都需要消耗 1s,那么整个注册过程就需要耗时 4s 才能响应给用户。
ActiveMQ 简介
ActiveMQ 是完全基于 JMS 规范实现的一个消息中间件产品。是 Apache 开源基金会研发的消息中间件。ActiveMQ主要应用在分布式系统架构中,帮助构建高可用、高性能、可伸缩的企业级面向消息服务的系统ActiveMQ 特性
1. 多语言和协议编写客户端
语言:java/C/C++/C#/Ruby/Perl/Python/PHP
应用协议 :
openwire/stomp/REST/ws/notification/XMPP/AMQP
2. 完全支持 jms1.1 和 J2ee1.4 规范
3. 对 spring 的支持,ActiveMQ 可以很容易内嵌到 spring模块中
ActiveMQ 安装
1. 登录到 http://activemq.apache.org/components/classic/download/,找到 ActiveMQ 的下载地址
我这里用的是apache-activemq-5.15.10-bin.tar.gz ,jdk是1.8.0_161
2. 直 接 copy 到 服 务 器 上 通 过 tar -zxvf apache-activeMQ.tar.gz
3. 启动运行
a) 普通启动:到 bin 目录下, sh activemq start
b) 启 动 并 指 定 日 志 文 件 sh activemq start > /tmp/activemqlog
4. 检查是否已启动
ActiveMQ默认采用 61616 端口提供 JMS服务,使用 8161端口提供管理控制台服务,执行以下命令可以检查是否成功启动 ActiveMQ 服务
netstat -an|grep 61616
可以通过./activemq console来查看日志。
5. 通过 http://192.168.11.156:8161 访问 activeMQ 管理页面 ,默认帐号密码 admin/admin
6. 关闭 ActiveMQ; sh activemq stop
下面来看一下ActiveMQ的简单应用:
消息的发布:
public static void main(String[] args) {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.254.135:61616");
Connection connection = null;
try {
connection = connectionFactory.createConnection();
connection.start();
// 延迟确认
Session session = connection.createSession(Boolean.TRUE, Session.DUPS_OK_ACKNOWLEDGE);
// 创建目的地
Destination destination = session.createQueue("myQueue");
// 创建消费者
MessageProducer producer = session.createProducer(destination);
TextMessage message = session.createTextMessage("Hello World");
producer.send(message);
// 表示消息被自动确认
session.commit();
session.close();
} catch (JMSException e) {
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
对应的客户端消费:
public static void main(String[] args) {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.254.135:61616");
Connection connection = null;
try {
connection = connectionFactory.createConnection();
connection.start();
// 延迟确认
Session session = connection.createSession(Boolean.TRUE, Session.DUPS_OK_ACKNOWLEDGE);
// 创建目的地
Destination destination = session.createQueue("myQueue");
// 创建消费者
MessageConsumer consumer = session.createConsumer(destination);
TextMessage textMessage = (TextMessage) consumer.receive();
System.out.println(textMessage.getText());
// 表示消息被自动确认
session.commit();
session.close();
} catch (JMSException e) {
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
如果需要做到消息监听的话:
public static void main(String[] args) {
ConnectionFactory connectionFactory=
new ActiveMQConnectionFactory
("tcp://192.168.1.101:61616");
Connection connection=null;
try {
connection=connectionFactory.createConnection();
connection.start();
Session session=connection.createSession
(Boolean.TRUE,Session.AUTO_ACKNOWLEDGE);
//创建目的地
Destination destination=session.createQueue("myQueue");
//创建发送者
MessageConsumer consumer=session.createConsumer(destination);
MessageListener messageListener=new MessageListener() {
@Override
public void onMessage(Message message) {
try {
System.out.println(((TextMessage)message).getText());
session.commit();
} catch (JMSException e) {
e.printStackTrace();
}
}
};
consumer.setMessageListener(messageListener);
System.in.read();
} catch (JMSException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(connection!=null){
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
基于订阅发布的消息发送:
public static void main(String[] args) {
ConnectionFactory connectionFactory=
new ActiveMQConnectionFactory
("tcp://192.168.254.135:61616");
Connection connection=null;
try {
connection=connectionFactory.createConnection();
connection.start();
Session session=connection.createSession(Boolean.TRUE,Session.AUTO_ACKNOWLEDGE);
//创建目的地
Destination destination=session.createTopic("myTopic");
//创建发送者
MessageProducer producer=session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
//创建需要发送的消息
TextMessage message=session.createTextMessage("topic -message");
//Text Map Bytes Stream Object
producer.send(message);
session.commit();
// session.rollback();
session.close();
} catch (JMSException e) {
e.printStackTrace();
}finally {
if(connection!=null){
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
基于订阅发布的消息消费:这里需要先启动消费者
public static void main(String[] args) {
ConnectionFactory connectionFactory=
new ActiveMQConnectionFactory
("tcp://192.168.254.135:61616");
Connection connection=null;
try {
connection=connectionFactory.createConnection();
connection.setClientID("wuzz");
connection.start();
Session session=connection.createSession
(Boolean.TRUE,Session.AUTO_ACKNOWLEDGE);
//创建目的地
Topic destination=session.createTopic("myTopic");
//创建发送者
MessageConsumer consumer=session.createDurableSubscriber(destination,"wuzz");
TextMessage textMessage=(TextMessage) consumer.receive();
System.out.println(textMessage.getText());
session.commit(); //消息被确认
session.close();
} catch (JMSException e) {
e.printStackTrace();
}finally {
if(connection!=null){
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
明白了ActiveMQ的基本使用,下面从源码的层面去学习一下ActIiveMQ的原理
springboot整合ActiveMQ:
1.pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions><!-- 去掉springboot默认配置 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency> <dependency> <!-- 引入log4j2依赖 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency> <dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.</version>
</dependency> <dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
2.application.yml:
server:
port: spring:
activemq:
broker-url: tcp://192.168.1.101:61616
user: admin
password: admin
pool:
enabled: true
packages:
trust-all: true # 如果使用ObjectMessage传输对象,必须要加上这个信任包,否则会报ClassNotFound异常
jms:
pub-sub-domain: true # 启动主题消息
3.ActiveMqConfig 配置类:
/**
* User: Wuzhenzhao
* Date: 2019/12/9
* Time: 17:05
* Description:
* ClassPath:com.wuzz.demo.integratedway1.config.ActiveMqConfig
*/
@Configuration
public class ActiveMqConfig {
// queue模式的ListenerContainer
@Bean
public JmsListenerContainerFactory<?> jmsListenerContainerQueue(ConnectionFactory activeMQConnectionFactory) {
DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
bean.setConnectionFactory(activeMQConnectionFactory);
return bean;
}
// topic模式的ListenerContainer
@Bean
public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ConnectionFactory activeMQConnectionFactory) {
DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
bean.setPubSubDomain(true);
bean.setConnectionFactory(activeMQConnectionFactory);
return bean;
}
}
4. MqProducer 生产者:
@Service
public class MqProducer { @Autowired
private JmsMessagingTemplate jmsMessagingTemplate; /**
* 发送字符串消息队列
*
* @param queueName 队列名称
* @param message 字符串
*/
public void sendStringQueue(String queueName, String message) {
this.jmsMessagingTemplate.convertAndSend(new ActiveMQQueue(queueName), message);
} /**
* 发送字符串集合消息队列
*
* @param queueName 队列名称
* @param list 字符串集合
*/
public void sendStringListQueue(String queueName, List<String> list) {
this.jmsMessagingTemplate.convertAndSend(new ActiveMQQueue(queueName), list);
} /**
* 发送对象消息队列
*
* @param queueName 队列名称
* @param obj 对象
*/
public void sendObjQueue(String queueName, Serializable obj) {
this.jmsMessagingTemplate.convertAndSend(new ActiveMQQueue(queueName), obj);
} /**
* 发送对象集合消息队列
*
* @param queueName 队列名称
* @param objList 对象集合
*/
public void sendObjListQueue(String queueName, List<Serializable> objList) {
this.jmsMessagingTemplate.convertAndSend(new ActiveMQQueue(queueName), objList);
} /**
* 发送字符串消息主题
*
* @param topicName 主题名称
* @param message 字符串
*/
public void sendStringTopic(String topicName, String message) {
this.jmsMessagingTemplate.convertAndSend(new ActiveMQTopic(topicName), message);
} /**
* 发送字符串集合消息主题
*
* @param topicName 主题名称
* @param list 字符串集合
*/
public void sendStringListTopic(String topicName, List<String> list) {
this.jmsMessagingTemplate.convertAndSend(new ActiveMQTopic(topicName), list);
} /**
* 发送对象消息主题
*
* @param topicName 主题名称
* @param obj 对象
*/
public void sendObjTopic(String topicName, Serializable obj) {
this.jmsMessagingTemplate.convertAndSend(new ActiveMQTopic(topicName), obj);
} /**
* 发送对象集合消息主题
*
* @param topicName 主题名称
* @param objList 对象集合
*/
public void sendObjListTopic(String topicName, List<Serializable> objList) {
this.jmsMessagingTemplate.convertAndSend(new ActiveMQTopic(topicName), objList);
}
}
4.队列消费者 QueueConsumer:
@Component
public class QueueConsumer { @JmsListener(destination = "stringQueue", containerFactory = "jmsListenerContainerQueue")
public void receiveStringQueue(String msg) {
System.out.println("接收到消息...." + msg);
}
// @JmsListener(destination = "stringListQueue", containerFactory = "jmsListenerContainerQueue")
// public void receiveStringListQueue(List<String> list) {
// System.out.println("接收到集合队列消息...." + list);
// }
//
//
// @JmsListener(destination = "objQueue", containerFactory = "jmsListenerContainerQueue")
// public void receiveObjQueue(ObjectMessage objectMessage) throws Exception {
// System.out.println("接收到对象队列消息...." + objectMessage.getObject());
// }
//
//
// @JmsListener(destination = "objListQueue", containerFactory = "jmsListenerContainerQueue")
// public void receiveObjListQueue(ObjectMessage objectMessage) throws Exception {
// System.out.println("接收到的对象队列消息..." + objectMessage.getObject());
// } }
5.主题消费者A ,这里为了测试topic消息,我们使用两个消费者去订阅。ATopicConsumer:
@Component
public class ATopicConsumer { @JmsListener(destination = "stringTopic", containerFactory = "jmsListenerContainerTopic")
public void receiveStringTopic(String msg) {
System.out.println("ATopicConsumer接收到消息...." + msg);
} // @JmsListener(destination = "stringListTopic", containerFactory = "jmsListenerContainerTopic")
// public void receiveStringListTopic(List<String> list) {
// System.out.println("ATopicConsumer接收到集合主题消息...." + list);
// }
//
//
// @JmsListener(destination = "objTopic", containerFactory = "jmsListenerContainerTopic")
// public void receiveObjTopic(ObjectMessage objectMessage) throws Exception {
// System.out.println("ATopicConsumer接收到对象主题消息...." + objectMessage.getObject());
// }
//
//
// @JmsListener(destination = "objListTopic", containerFactory = "jmsListenerContainerTopic")
// public void receiveObjListTopic(ObjectMessage objectMessage) throws Exception {
// System.out.println("ATopicConsumer接收到的对象集合主题消息..." + objectMessage.getObject());
// } }
BTopicConsumer:
@Component
public class BTopicConsumer { @JmsListener(destination = "stringTopic", containerFactory = "jmsListenerContainerTopic")
public void receiveStringTopic(String msg) {
System.out.println("BTopicConsumer接收到消息...." + msg);
} // @JmsListener(destination = "stringListTopic", containerFactory = "jmsListenerContainerTopic")
// public void receiveStringListTopic(List<String> list) {
// System.out.println("BTopicConsumer接收到集合主题消息...." + list);
// }
//
//
// @JmsListener(destination = "objTopic", containerFactory = "jmsListenerContainerTopic")
// public void receiveObjTopic(ObjectMessage objectMessage) throws Exception {
// System.out.println("BTopicConsumer接收到对象主题消息...." + objectMessage.getObject());
// }
//
//
// @JmsListener(destination = "objListTopic", containerFactory = "jmsListenerContainerTopic")
// public void receiveObjListTopic(ObjectMessage objectMessage) throws Exception {
// System.out.println("BTopicConsumer接收到的对象集合主题消息..." + objectMessage.getObject());
// }
}
6.实体类 User:
public class User implements Serializable {
private String id;
private String name;
private Integer age;
public User() {
}
public User(String id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
//省略get set 跟 toString
}
7.测试类:
@RestController
public class TestController { @Autowired
private MqProducer mqProducer; @RequestMapping(value = "/testStringQueue.json", method = {RequestMethod.GET})
public void testStringQueue() { for (int i = ; i <= ; i++) {
System.out.println("第" + i + "次发送字符串队列消息");
mqProducer.sendStringQueue("stringQueue", "消息:" + i);
}
} // @RequestMapping(value = "/testStringListQueue.json", method = {RequestMethod.GET})
// public void testStringListQueue() {
//
// List<String> idList = new ArrayList<>();
// idList.add("id1");
// idList.add("id2");
// idList.add("id3");
//
// System.out.println("正在发送集合队列消息ing......");
// mqProducer.sendStringListQueue("stringListQueue", idList);
// }
//
//
// @RequestMapping(value = "/testObjQueue.json", method = {RequestMethod.GET})
// public void testObjQueue() {
//
// System.out.println("正在发送对象队列消息......");
// mqProducer.sendObjQueue("objQueue", new User("1", "小明", 20));
// }
//
//
// @RequestMapping(value = "/testObjListQueue.json", method = {RequestMethod.GET})
// public void testObjListQueue() {
//
// System.out.println("正在发送对象集合队列消息......");
//
// List<Serializable> userList = new ArrayList<>();
// userList.add(new User("1", "小明", 21));
// userList.add(new User("2", "小雪", 22));
// userList.add(new User("3", "小花", 23));
//
// mqProducer.sendObjListQueue("objListQueue", userList);
// } @RequestMapping(value = "/testStringTopic.json", method = {RequestMethod.GET})
public void testStringTopic() { for (int i = ; i <= ; i++) {
System.out.println("第" + i + "次发送字符串主题消息");
mqProducer.sendStringTopic("stringTopic", "消息:" + i);
}
} // @RequestMapping(value = "/testStringListTopic.json", method = {RequestMethod.GET})
// public void testStringListTopic() {
//
// List<String> idList = new ArrayList<>();
// idList.add("id1");
// idList.add("id2");
// idList.add("id3");
//
// System.out.println("正在发送集合主题消息ing......");
// mqProducer.sendStringListTopic("stringListTopic", idList);
// }
//
//
// @RequestMapping(value = "/testObjTopic.json", method = {RequestMethod.GET})
// public void testObjTopic() {
//
// System.out.println("正在发送对象主题消息......");
// mqProducer.sendObjTopic("objTopic", new User("1", "小明", 20));
// }
//
//
// @RequestMapping(value = "/testObjListTopic.json", method = {RequestMethod.GET})
// public void testObjListTopic() {
//
// System.out.println("正在发送对象集合主题消息......");
//
// List<Serializable> userList = new ArrayList<>();
// userList.add(new User("1", "小明", 21));
// userList.add(new User("2", "小雪", 22));
// userList.add(new User("3", "小花", 23));
//
// mqProducer.sendObjListTopic("objListTopic", userList);
// }
}
启动后访问对应接口就可以。
初识ActiveMQ的更多相关文章
- [ActiveMQ]初识ActiveMQ
初识ActiveMQ ActiveMQ介绍 官方网站:http://activemq.apache.org/ 最新版本:ActiveMQ 5.14.1(2016-10-28) 最新版本下载链接:htt ...
- 初识 ActiveMQ
其实算不上初识了,工作一年来一直都有接触 mq 相关的东西.但是,从来都是粘贴复制别人的配置代码,却从未认真系统的学习过它,现在线上用 mq 的项目出问题了,老板在后面拿枪指着呢,不得不好好研究下了. ...
- ActiveMQ (一) 初识ActiveMQ
了解JMS JMS即Java消息服务(Java Message Service)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进 ...
- ActiveMQ(1)---初识ActiveMQ
消息中间件的初步认识 什么是消息中间件? 消息中间件是值利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成.通过提供消息传递和消息排队模型,可以在分布式架构下扩展进 ...
- ActiveMQ学习笔记(1)----初识ActiveMQ
1. 什么是ActiveMQ? ActiveMQ是Apache推出的,一款开源的,完全支持JMS1.1和j2ee1.4规范的JMS Provider实现的消息中间件(Message Oriented ...
- SpringBoot第二十篇:初识ActiveMQ
本文是作者之前写的关于 ActiveMQ 的一篇文章.此处为了保证该系列文章的完整性,故此处重新引入. 一.消息中间件的介绍 介绍 消息队列 是指利用 高效可靠 的 消息传递机制 进行与平台无关的 数 ...
- ActiveMQ 学习第二弹
经历了昨天的初识 ActiveMQ,正好今天下班有点事耽搁了还没法回家,那就再学习会 ActiveMQ 吧!现在官网的文档没啥好看的了,毕竟是入门学习,太深奥的东西也理解不了.然后看官网上有推荐书籍& ...
- ActiveMQ消息的消费原理
消费端消费消息: 在 初识ActiveMQ 中我提到过,两种方法可以接收消息,一种是使用同步阻塞的ActiveMQMessageConsumer#receive方法.另一种是使用消息监听器Messag ...
- ActiveMQ(2) ActiveMQ创建HelloWorld
启动ActiveMQ: 请参见:ActiveMQ(1) 初识ActiveMQ 创建Maven工程: pom文件: <project xmlns="http://maven.apache ...
随机推荐
- [ASP.net教程]IIS服务器 远程发布(Web Deploy)配置
asp.net 网站有三种常用的发布方式:分别是拷贝开发机上发布好的文件到服务器硬盘上.打包成安装程序到服务器上安装.通过Visual Studio 开发平台远程发布到服务器. 在asp.net网站的 ...
- vue通俗易懂的子组件向父组件传值
不多BB直接上图: 如上图:为子组件绑定点击事件 如上图:send方法触发父组件绑定的事件 如上图:为父组件绑定触发事件@myEvent="aa" aa方法接受子组件传过来的值
- ASP.NET MVC - 处理Html数据
HtmlAgilityPack 使用HtmlAgilityPack可以以面向对象的方式通过查找Html节点来获取页面元素.参考:http://html-agility-pack.net HtmlDoc ...
- html转成pdf,下载(html2canvas 和 jsPDF)
参考链接:https://github.com/linwalker/render-html-to-pdf
- Light oj 1281 - New Traffic System 多状态最短路
题目大意:有向图,新计划的地铁,有k个计划新路,利用现有的铁路.k条新路和限定只能用d条新路,找出从0到n-1的最短路径 题目思路:用dist[u][use],储存使用use条新路,到达节点u的最短路 ...
- 【转载】奇异值分解(SVD)计算过程示例
原文链接:奇异值分解(SVD)的计算方法 奇异值分解是线性代数中一种重要的矩阵分解方法,这篇文章通过一个具体的例子来说明如何对一个矩阵A进行奇异值分解. 首先,对于一个m*n的矩阵,如果存在正交矩阵U ...
- ppp 完全理解(二)【转】
转自:https://blog.csdn.net/tianruxishui/article/details/44057717 ppp 完全理解(二) pppd 协议及代码分析 作者:李圳均 日期:20 ...
- vc++基础班[25]---系统信息的获取
--------------------------------------------------------------------------- VC 驿站 WwW.CcTry.CoM 多抽出一 ...
- aix安装nmon
aix5310以上都系统自带了nmon,其他低版本需要手动安装 软件包下载地址https://www.ibm.com/developerworks/community/wikis/home?lang= ...
- Unity3D RTS游戏中帧同步实现
帧同步技术是早期RTS游戏常用的一种同步技术,本篇文章要给大家介绍的是RTX游戏中帧同步实现,帧同步是一种前后端数据同步的方式,一般应用于对实时性要求很高的网络游戏,想要了解更多帧同步的知识,继续往下 ...