消息中间件的简介
常见的MQ的产品
kafka,RababbitMQ,RocketMQ,ActiveMQ和其他的MQ产品
消息中间件
消息中间件是指高效的消息传递机制进行的与平台无关的数据的交流,并基于数据来进行的分布式系统的集成
大致的工作流程是这样子的
发送者把消息发送到消息服务器,消息服务器存放在若干的队列/主题中,在合适的时候,消息服务器会将消息转发到接受者,在这个过程中,发送和接受是异步的,也就是无需等待,而且是发送者和接受者的生命周期也是没有必然的关系的,尤其是发布/订阅模式,也可以完成一对多的通信,即让一个消息有多个接收者
消息中间件的架构及其模式
JMS的编码的架构流程
JMS的传递消息的两大经典模式:队列和主题
消息中间件的入门案例
1.配置好activemq的安装和运行环境,这里就不再多说,控制客户端能够正常访问
2.添加项目所需要的jar包,我这里是maven为例,添加是坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zzuli.activemq</groupId>
<artifactId>activemq-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>4.15</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.11</version>
</dependency>
<!--下面添加一些基础包,比如一些常见的日志包-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
3.写出对应的消息接收者和消息传递者,这里分别以队列和主题进行讲解
队列消息发送者
package com.zzuli.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
/**
* @author liugang
* @version 1.0
* @date 2020/1/30 16:56
*/
public class JmsProduce {
public static final String ACTIVEMQ_URL = "tcp://192.168.229.128:61616";
public static final String QUEUE_NAME = "queue01";
public static void main(String[] args) throws JMSException {
//1.创建连接工厂,按照指定的url地址,采用默认的用户名和密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//2.创建连接对象,并获得连接connection并启动
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
//3.创建session回话
//3.1两个参数,第一是事务,第二个是签收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4.创建目标地(具体是队列还是主题topic)
Queue queue = session.createQueue(QUEUE_NAME);
//5.创建消息的生产者
MessageProducer messageProducer = session.createProducer(queue);
//6.通过使用messageProducer生产3条消息发送到MQ的队列里
for (int i = 1; i <= 6; i++) {
//7.创建消息,好比学生按照指定的要求写面试题一样
TextMessage textMessage = session.createTextMessage("MsgListener--" + i);
//8.通过消息生产者messageProducer发送给mq
messageProducer.send(textMessage);
}
//9.关闭资源
messageProducer.close();
session.close();
connection.close();
System.out.println("**消息发布到MQ完成**");
}
}
队列消息接收者
package com.zzuli.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.springframework.jms.JmsException;
import javax.jms.*;
import java.io.IOException;
/**
* @author liugang
* @version 1.0
* @date 2020/1/30 17:58
*/
public class JmsConsumer {
public static final String ACTIVEMQ_URL = "tcp://192.168.229.128:61616";
public static final String QUEUE_NAME = "queue01";
public static void main(String[] args) throws JMSException, IOException {
System.out.println("我是一号消费者");
//1.创建连接工厂,按照指定的url地址,采用默认的用户名和密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//2.创建连接对象,并获得连接connection并启动
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
//3.创建session回话
//3.1两个参数,第一是事务,第二个是签收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4.创建目标地(具体是队列还是主题topic)
Queue queue = session.createQueue(QUEUE_NAME);
//5.创建消费者
MessageConsumer messageConsumer = session.createConsumer(queue);
/* 同步阻塞方式(receive)
订阅者或者接收者接收消息之前,receive接收得方法保持不变,一直在阻塞
while (true){
//从前面传递的消息类型和要接受的消息的类型一致
TextMessage textMessage = (TextMessage) messageConsumer.receive(8000l);
if (textMessage != null){
System.out.println("消费者接受到消息:"+textMessage.getText());
}else {
break;
}
}
//6.关闭资源
messageConsumer.close();
session.close();
connection.close();*/
//通过监听的方式来监听消息 此时是异步非阻塞的方式来祖测监听器
messageConsumer.setMessageListener(new MessageListener() {
@Override
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();
}
}
}
});
//保证控制台不灭
System.in.read();
//关闭资源
messageConsumer.close();
session.close();
connection.close();
/**
* 当首先开放的是生产者的时候,后面的消费者是谁在前面随先排队
* 当首先是开放的是消费者,后面的生产者的产能被平均分配
*/
}
}
package com.zzuli.activemq.topic;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
/**
* @author liugang
* @version 1.0
* @date 2020/1/30 20:34
*/
public class JmsProduce_topic {
public static final String ACTIVEMQ_URL = "tcp://192.168.229.128:61616";
public static final String TOPIC_NAME = "topic-zzuli";
public static void main(String[] args) throws JMSException {
//1.创建连接工厂,按照指定的url地址,采用默认的用户名和密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//2.创建连接对象,并获得连接connection并启动
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
//3.创建session回话
//3.1两个参数,第一是事务,第二个是签收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4.创建目标地(具体是队列还是主题topic)
Topic topic = session.createTopic(TOPIC_NAME);
//5.创建消息的生产者
MessageProducer messageProducer = session.createProducer(topic);
//6.通过使用messageProducer生产3条消息发送到MQ的队列里
for (int i = 1; i <= 6; i++) {
//7.创建消息,好比学生按照指定的要求写面试题一样
TextMessage textMessage = session.createTextMessage("TOPIC_NAME--" + i);
//8.通过消息生产者messageProducer发送给mq
messageProducer.send(textMessage);
}
//9.关闭资源
messageProducer.close();
session.close();
connection.close();
System.out.println("**TOPIC_NAME消息发布到MQ完成**");
}
}
主题消息接收者,此时我是以3个接收者为例,分别先启动3个消费者进行等待,然后再启动提供者,达到每个接收者都能接收消息,和微信公众号的形式来进行发送
package com.zzuli.activemq.topic;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
import java.io.IOException;
/**
* @author liugang
* @version 1.0
* @date 2020/1/30 20:40
*/
public class JmsConsumer_topic {
public static final String ACTIVEMQ_URL = "tcp://192.168.229.128:61616";
public static final String TOPIC_NAME = "topic-zzuli";
public static void main(String[] args) throws JMSException, IOException {
System.out.println("我是一号消费者");
//1.创建连接工厂,按照指定的url地址,采用默认的用户名和密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//2.创建连接对象,并获得连接connection并启动
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
//3.创建session回话
//3.1两个参数,第一是事务,第二个是签收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4.创建目标地(具体是队列还是主题topic)
Topic topic = session.createTopic(TOPIC_NAME);
//5.创建消费者
MessageConsumer messageConsumer = session.createConsumer(topic);
//通过监听的方式来监听消息
messageConsumer.setMessageListener(new MessageListener() {
@Override
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();
}
}
}
});
//保证控制台不灭
System.in.read();
//关闭资源
messageConsumer.close();
session.close();
connection.close();
}
}
消息中间件的执行流程执行流程及其特点
JMS的开发流程
1.创建一个connection factory
2.通过connection factory创建一个连接
3.启动JMS connection
4.通过connection 创建JMS session
5.创建JMS destiontion
6.创建JMS producer或者创建JMS message并设置desination
7.创建JMS consumer或者是一个JMS message listener
8.发送或者接收JMS message
9.关闭所有资源
点对点消费传递的特点
1.每个消息只能有一个消费者,类似于1对1的关系,好似个人的消息传递给自己的
2.消息的生产者和消费者之间没有时间的相关性
3.消息被消费者队列中不会再存储,所有消费者已经消费的消息
发布/订阅传递性的特点
1.生产者将消息发布到topic中,每个消费者可以属于1:N的关系
2.生产者和消费者有时间的相关性,订阅是一个主题只能订阅其发布的消息
3.生产者生产时,topic不能保存信息,订阅是一个主题无人订阅就去生产,那就是一条废消息,所以一把先启动消费者再启动生产者