JMS(java消息服务)
java消息服务指的是两个应用程序之间进行异步通信的API,它为标准消息协议和消息服务提供了一组通用接口,包括创建、发送、读取消息等,用于支持java应用程序开发。在javaEE中,当两个应用程序通过JMS进行通信时,它们之间并不是直接相连的,而是通过一个共同的消息收发组件关联起来以达到解耦/异步消峰的效果。
消息队列的详细比较
JMS组成结构和特点
- JMS provider
实现JMS接口和规范的中间件,也就是我们的MQ服务器
- JMS producer
消息生产者,创建和生产jms消息的客户端应用
- JMS consumer
消息消费者,接受和消费jms消息的客户端应用
- JMS message
消息头
1.JMSDestination----消息发送的目的地,主要是指Queue和Topic
2.JMSDeliveryMode—持久和非持久模式
3.JMSExpiration—可以设定消息在一定时间后过期,默认是永不过期
4.JMSPriority—消息优先级,从0-9十个级别,0-4是普通消息,5-9是加急消息
5.JMSMessageID— 唯一识别每一个消息的标识,由MQ产生
消息属性
-----是封装具体的消息数据
-----5种消息格式
1.TextMessage(普通字符串消息,包含一个string)
2.MapMessage(一个Map类型消息,key为string类型,值为java基本类型
3.BytesMessage(二进制数组消息,包含一个byte[])
4.StreamMessage(java数据流消息,用标准流操作来顺序的填充和读取)
5.ObjectMessage(对象消息,包含一个序列化的java对象)
-----发送和接受的消息体类型必须一致对应
消息体
如果需要除消息头字段以外的值,那么可以使用消息属性
识别/去重/重点标注等操作非常有空的方法
setxxxproperty/getxxxproperty
JMS的可靠性
持久性
持久化消息是队列的默认传送模式,此模式保证这些消息只被传送一次和成功使用一次。对于这些消息,可靠性是优先考虑的因素。另一个重要方面是确保持久性消息传送目标后,消息服务在向消费者传送它们之前不会丢失这些消息。
持久化:当服务器宕机,消息依然存在messageProducer.setDeliveryMode(DeliveryMode.PRESISTENT)
非持久化:当服务器宕机,消息不存在
messageProducer.setDeliveryMode(DeliveryMode.NON_PRESISTENT)
topic的持久化:
topic消息持久化,只要消费者向MQ服务器注册过,所有生产者发布成功的消息,该消费者都能收到,不管是MQ服务器宕机还是消费者不在线后上线。
// 持久化topic 的消息消费者
public class JmsConsummer_persistence {
public static final String ACTIVEMQ_URL = "tcp://192.168.10.100:61616";
public static final String TOPIC_NAME = "topic01";
public static void main(String[] args) throws Exception{
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
Connection connection = activeMQConnectionFactory.createConnection();
// 设置客户端ID。向MQ服务器注册自己的名称
connection.setClientID("z3");
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic(TOPIC_NAME);
// 创建一个topic订阅者对象。一参是topic,二参是订阅者名称
TopicSubscriber topicSubscriber = session.createDurableSubscriber(topic,"remark...");
// 之后再开启连接
connection.start();
Message message = topicSubscriber.receive();
while (null != message){
TextMessage textMessage = (TextMessage)message;
System.out.println(" 收到的持久化 topic :"+textMessage.getText());
message = topicSubscriber.receive();
}
session.close();
connection.close();
}
}
事务
事务开启的意义在于,如果对于多条必须同批次传输的消息,可以使用事务,如果一条传输失败,可以将事务回滚,再次传输,保证数据的完整性。
对于消息消费者来说,开启事务的话,可以避免消息被多次消费,以及后台和服务器数据的不一致性。例如:如果消息消费的createSession设置为ture,但是没有commit,此时就会造成非常严重的后果,那就是在后台看来消息已经被消费,但是对于服务器来说并没有接收到消息被消费,此时就有可能被多次消费。
签收
- 自动签收(Session.AUTO_ACKNOWLEDGE):该方式是默认的。该种方式,无需我们程序做任何操作,框架会帮我们自动签收收到的消息。
- 手动签收(Session.CLIENT_ACKNOWLEDGE):手动签收。该种方式,需要我们手动调用Message.acknowledge(),来签收消息。如果不签收消息,该消息会被我们反复消费,直到被签收。
- 允许重复消息(Session.DUPS_OK_ACKNOWLEDGE):多线程或多个消费者同时消费到一个消息,因为线程不安全,可能会重复消费。该种方式很少使用到。
事务和签收的关系
在事务性会话中,当一个事务被成功提交,则消息被自动签收,如果事务回滚,则消息会被再次传送
非事务性会话中,消息何时被确认却决于创建会话时的应答模式
JMS的点对点总结
点对点模型是基于队列的,生产者发消息到队列,消费者从队列接收消息,队列的存在使得消息的异步传输成为可能。类似于发短信
1.如果在Session关闭时有部分消息已被收到但还没有签收,那当消费者再次连到相同的队列时,这些消息还会被再次接收
2.队列可以长久保存消息直到消费者收到消息。消费者不需要因为担心消息消失而时刻保持和队列的激活状态,充分体现了异步传输模式的优势。
JMS发布订阅总结
非持久化订阅:要先订阅注册才能接收到发布,只给订阅者发送消息
持久化订阅:客户端首先向MQ注册一个自己的识别ID号,当这个客户端处于离线状态,生产者会为这个ID保存所有发送到主题的消息,当客户再次连接到MQ时会根据消费者的ID得到所有当自己处于离线时的消息
非持久订阅状态下,不能恢复或重新派送一个未签收的消息。
持久订阅才能恢复或重新派送一个未签收的消息。
broker
相当于一个ActiveMQ服务器实例
broker就是实现了以代码的形式启动ActiveMQ将MQ嵌入到java代码中,以便随时用随时启动,在用的时候再去启动这样就能节省了资源,也保证了可靠性。
pom文件引入