本篇博客主要来自慕课网的课程:Java消息中间件
文章目录
中间件介绍
一、什么是中间件
非底层操作系统软件,非业务应用软件,不是直接给最终用户使用的,不能直接给客户带来价值的软件统称为中间件。
二、什么是消息中间件
关注于数据的发送和接受,利用高效可靠的异步消息传递机制集成分布式系统。
三、什么是JMS
Java 消息服务(Java Message Service)即JMS,是一个 Java 平台中关于面向消息中间件的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
四、什么是AMQP
AMQP(advanced message queuing protocol)是一个提供统一消息服务的应用层标准协议,基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制。
JMS规范 | AMQP协议 | |
---|---|---|
定义 | Java api | Wire-protocol |
跨语言 | 否 | 是 |
消息类型 | 提供两种消息模型: p2p,pub/sub | 提供了五种消息模型: direct,fanout,topic,headers,system |
消息类型 | TextMessage,MapMessage,BytesMessage,StreamMessage,ObjectMessage,Message | byte[] |
综合评价 | JMS 定义了 Java API 层面的标准;在 Java 体系中,多个 client 均可以通过JMS进行交互,不需要应用修改代码,但是其对跨平台的支持较差 | AMQP 的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全 |
五、常见消息中间件对比
ActiveMQ | RabbitMQ | Kafka | |
---|---|---|---|
跨语言 | 支持(Java优先) | 语言无关 | 支持(Java优先) |
支持协议 | OpenWire,Stomp,XMPP,AMQP | AMQP | |
优点 | 遵循JMS规范 安装部署方便 | 继承Erlang天生的并发性 最初用于金融行业,稳定性安全性有保障 | 依赖zk,可动态扩展节点 高性能、高吞吐量、无限扩容、消息可指定追溯 |
缺点 | 根据其他用户反馈,会莫名丢失消息。目前重心在下代产品apolle上,目前社区不活跃,对5.X维护较少(这是17年的了,现在不知道怎样) | Erlang语言难度较大,不支持动态扩展 | 严格的顺序机制,不支持消息优先级,不支持标准的消息协议,不利于平台迁移 |
综合评价 | 适合中小企业级消息应用场景,不适合上千个队列的应用场景 | 适合对稳定性要求搞的企业级应用 | 一般应用在大数据日志处理或对实时性(少量延迟),可靠性(少量丢数据)要求稍低的场景使用。 |
JMS规范
- 提供者:实现JMS规范的消息中间件服务器
- 客户端:发送或接受消息的应用程序
- 生产者/发布者:创建并发送消息的客户端
- 消费者/订阅者:接受并处理消息的客户端
- 消息:应用程序之间传递的数据内容
- 消息模式:在客户端之间传递消息的方式,JMS中定义了主题和队列两种模式
一、消息模式
1. 队列模式
2. 主题模式
二、JMS编码接口
- ConnectionFactory 用于创建连接到消息中间件的连接工厂
- Connectin 代表了应用程序和消息服务器之间的通信链路
- Destination 指消息发布和接收的地点,包括队列或主题
- Session 标一个单线程的上下文,用于发送和接收消息
- MessageConsumer 由会话创建, 用于接收发送到目标的消息
- MessageProducer 由会话创建,于发送消感到目标
- Message 是在消费和生产者之间传送的对象,消息头,一组消息属性,一个消息体
代码DEMO
启动ActiveMQ
- http://activemq.apache.org/components/classic/download/去官网下载压缩包
- 解压后到任意指定目录
- 到 bin 目录,选择对应的系统,再双击
activemq.bat
文件启动即可。
代码DEMO
- 新建一个空白的 maven 项目
- 添加 ActiveMQ 的依赖
<dependencies>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.14.0</version>
</dependency>
</dependencies>
- ActiveMQ中 8161 是管理端口,61616 是消息的接收/发送端口
1. 队列模式
生产者
package com.imooc.jms.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class AppProducer {
private static final String url = "tcp://127.0.0.1:61616";
private static final String queueName = "queue-test";
public static void main(String[] args) throws JMSException {
//1. 创建ConnectionFactory
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
//2. 创建Connection
Connection connection = connectionFactory.createConnection();
//3. 启动链接
connection.start();
//4. 创建会话
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//5. 创建一个目的地
Destination destination = session.createQueue(queueName);
//6. 创建一个生产者
MessageProducer producer = session.createProducer(destination);
for (int i = 0; i < 100; i++) {
//7. 创建消息
TextMessage textMessage = session.createTextMessage("test" + i);
//8. 发布消息
producer.send(textMessage);
System.out.println("发送消息" + textMessage.getText());
}
//9. 关闭连接
connection.close();
}
}
消费者
package com.imooc.jms.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class AppConsumer {
private static final String url = "tcp://127.0.0.1:61616";
private static final String queueName="queue-test";
public static void main(String[] args) throws JMSException {
//1. 创建ConnectionFactory
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
//2. 创建Connection
Connection connection = connectionFactory.createConnection();
//3. 启动链接
connection.start();
//4. 创建会话
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//5. 创建一个目的地
Destination destination = session.createQueue(queueName);
//6. 创建一个消费者
MessageConsumer consumer = session.createConsumer(destination);
//7. 创建一个监听器
consumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("接受消息"+textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
//8. 关闭连接
// connection.close();
//异步过程 ,没有接受到就关闭了
//两个消费者, 一人一个, 平均消费
}
}
2. 主题模式
发布者
package com.imooc.jms.topic;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class AppProducer {
private static final String url = "tcp://127.0.0.1:61616";
private static final String topicName="topic-test";
public static void main(String[] args) throws JMSException {
//1. 创建ConnectionFactory
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
//2. 创建Connection
Connection connection = connectionFactory.createConnection();
//3. 启动链接
connection.start();
//4. 创建会话
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//5. 创建一个目的地
Destination destination = session.createTopic(topicName);
//6. 创建一个生产者
MessageProducer producer = session.createProducer(destination);
for (int i = 0; i < 100; i++) {
//7. 创建消息
TextMessage textMessage = session.createTextMessage("test"+i);
//8. 发布消息
producer.send(textMessage);
System.out.println("发送消息"+textMessage.getText());
}
//9. 关闭连接
connection.close();
}
}
订阅者
package com.imooc.jms.topic;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class AppConsumer {
private static final String url = "tcp://127.0.0.1:61616";
private static final String topicName="topic-test";
public static void main(String[] args) throws JMSException {
//1. 创建ConnectionFactory
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
//2. 创建Connection
Connection connection = connectionFactory.createConnection();
//3. 启动链接
connection.start();
//4. 创建会话
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//5. 创建一个目的地
Destination destination = session.createTopic(topicName);
//6. 创建一个消费者
MessageConsumer consumer = session.createConsumer(destination);
//7. 创建一个监听器
consumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("接受消息"+textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
//主题模式 消费者只接受启动后生产者发送的消息 每个消费者都会受到一条消息
//8. 关闭连接
// connection.close();
//异步过程 ,没有接受到就关闭了
}
}