消息中间件的初步认识

什么是消息中间件?

  消息中间件是利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,可以在分布式架构下扩展进程之间的通信。

消息中间件能做什么?

  消息中间件主要解决的就是分布式系统之间消息传递的问题,它能够屏蔽各种平台以及协议之间的特性,实现应用程序之间的协同。举个非常简单的例子,就拿一个电商平台的注册功能来简单分析下,用户注册这一个服务,不单单只是 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的更多相关文章

  1. [ActiveMQ]初识ActiveMQ

    初识ActiveMQ ActiveMQ介绍 官方网站:http://activemq.apache.org/ 最新版本:ActiveMQ 5.14.1(2016-10-28) 最新版本下载链接:htt ...

  2. 初识 ActiveMQ

    其实算不上初识了,工作一年来一直都有接触 mq 相关的东西.但是,从来都是粘贴复制别人的配置代码,却从未认真系统的学习过它,现在线上用 mq 的项目出问题了,老板在后面拿枪指着呢,不得不好好研究下了. ...

  3. ActiveMQ (一) 初识ActiveMQ

    了解JMS JMS即Java消息服务(Java Message Service)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进 ...

  4. ActiveMQ(1)---初识ActiveMQ

    消息中间件的初步认识 什么是消息中间件? 消息中间件是值利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成.通过提供消息传递和消息排队模型,可以在分布式架构下扩展进 ...

  5. ActiveMQ学习笔记(1)----初识ActiveMQ

    1. 什么是ActiveMQ? ActiveMQ是Apache推出的,一款开源的,完全支持JMS1.1和j2ee1.4规范的JMS Provider实现的消息中间件(Message Oriented ...

  6. SpringBoot第二十篇:初识ActiveMQ

    本文是作者之前写的关于 ActiveMQ 的一篇文章.此处为了保证该系列文章的完整性,故此处重新引入. 一.消息中间件的介绍 介绍 消息队列 是指利用 高效可靠 的 消息传递机制 进行与平台无关的 数 ...

  7. ActiveMQ 学习第二弹

    经历了昨天的初识 ActiveMQ,正好今天下班有点事耽搁了还没法回家,那就再学习会 ActiveMQ 吧!现在官网的文档没啥好看的了,毕竟是入门学习,太深奥的东西也理解不了.然后看官网上有推荐书籍& ...

  8. ActiveMQ消息的消费原理

    消费端消费消息: 在 初识ActiveMQ 中我提到过,两种方法可以接收消息,一种是使用同步阻塞的ActiveMQMessageConsumer#receive方法.另一种是使用消息监听器Messag ...

  9. ActiveMQ(2) ActiveMQ创建HelloWorld

    启动ActiveMQ: 请参见:ActiveMQ(1) 初识ActiveMQ 创建Maven工程: pom文件: <project xmlns="http://maven.apache ...

随机推荐

  1. 将本地时间转换成 UTC 时间,0时区时间

    // 将时间戳转换成日期格式: function timestampToTime(timestamp) { var date = new Date(timestamp);//时间戳为10位需*1000 ...

  2. webpack设置热更新

    首先需要在package.json中配置一个脚本参数 --hot "dev": "webpack-dev-server --mode development --hot& ...

  3. Mybatis(二)入门程序-通过id查找用户、模糊查找用户、添加用户、删除用户

    根据下图myBatis的架构,创建一个使用MyBatis的工程.       一.配置MyBatis 环境(如图) 1.sqlMapConfig.xml 首先,导入jar包(上图右边)并加载路径,然后 ...

  4. 《Effective Java中文版(第2版).pdf》-笔记

    1.第6页 ---- Java中Properties类的操作 - bakari - 博客园http://www.cnblogs.com/bakari/p/3562244.html 公有的静态方法返回的 ...

  5. Css - 精灵图

    Css - 精灵图css sprite 一个页面文档上总是会有N多的图标小图片,它们都是以背景图的方式嵌入文档,每个小图片需要一个url的css属性,每个url都指向一个服务器地址的链接,每个链接都代 ...

  6. Fragment和FragmentActivity的使用方法

    认识:首先我们知道Fragment是我们在单个Activity上要切换多个UI界面,显示不同内容.模块化这些UI面板以便提供给其他Acitivity使用便利.同时我们显示的Fragment也会受到当前 ...

  7. 记一次手动SQL注入

    1.检测到可能存在注入漏洞的url 最常用的 ' ,and 1=1 ,and 1=2 http://www.xxx.com/subcat.php?id=1 2.判断字段个数 http://www.xx ...

  8. python3+selenium入门16-窗口截图

    有时候需要把一些浏览器当前窗口截图下来,比如操作抱错的时候.WebDriver类下.get_screenshot_as_file()方法可窗口截图,需要传入一个截图文件名的路径.window要用\\当 ...

  9. Json的序列化与反序列化以及乱入的k_BackingField

    0.Newtonsoft.json 最简单的最强大的基于c#的json解析库是Newtonsoft.json 在NuGet程序包管理器中在线搜索“json”,选择JSon.Net,并安装.   使用到 ...

  10. VC使一个对话框不显示

    //add  this void CbkDlg::OnNcPaint() {     ShowWindow(SW_HIDE);     CDialog::OnNcPaint(); }     初始化时 ...