最近学习java消息相关的内容,整理了下学习内容:
一、问: 什么是 Java 消息服务?
答: Java 消息服务(Java Message Service,JMS) API 是一个用于访问企业消息传递系统的 API。是 Java 2 Platform, Enterprise(J2EE)的一部分。
二、目前流行的消息传送产品有哪些?
答:目前流行的有ActiveMQ、IBM WebSphere MQ、SonicMQ等
三、何时能够用到java消息机制?
答:(1)异构系统集成,整合现有资源,提升资源的利用率
(2)异步请求处理,减轻或消除系统瓶颈,提升用户生产率和系统的总体可伸缩性
(3)组件解偶,增长系统的灵活性
四、消息传送的两种模型
发布/订阅模型
客户端发送消息到一个名为主题(topic)的虚拟通道中,每一个订阅该主题的消费者都会接收到每条消息的一个副本。
点对点模型
客户端经过队列(queue)这个虚拟通道来同步和异步发送、接收消息,发送到队列的消息只能被一个接收者所接收,即便有多个消费者时也只能有一个消费者处理消息
五、JMS包含哪些接口?
JMS API能够分为3个主要部分:公共API、点对点API和发布/订阅API。在JMS1.1中,公共API可被用于向一个队列或一个主题发送消息,或从其中接收消息。点对点API专门用于使用队列的消息传送,而发布/订阅API则专门用于使用主题的消息传送。
在JMS公共API内部,和发送和接收JMS消息有关的JMS API接口主要有7个:
l ConnectionFactory
l Destination
l Connection
l Session
l Message
l MessageProducer
l MessageConsumer
在这些公共接口中,ConnectionFactory和Destination必须使用JNDI(遵守JMS规范要求)从提供者处得到。其余接口则能够 经过工厂方法在不一样的API接口中建立。举例来讲,一旦有了一个ConnectionFactory,就能够建立一个 Connection。一旦有了一个Connection,就能够建立一个Session。而一旦有了一个Session,就能够建立一个 Message、MessageProducer和MessageConsumer。这7个主要的JMS公共API接口之间的关系如图1-5所示。
在JMS中,是Session对象保存着用于消息传送的事务性工做单元(transactional unit),而不是Connection对象。这和JDBC不一样,JDBC中是Connection对象保存事务性工做单元。这就意味着在使用JMS时, 一个应用程序一般只会有一个Connection对象,可是它能够有一个Session对象池。
另外,还有和异常处理、消息优先级及消息持久性有关的其余接口
六、java消息分为哪些部分?
消息头、消息属性、消息自身
七、消息过滤
消息订阅者须要对消息进行过滤,不然订阅者就会接受到主题或队列的每一条消息,浪费了没必要要的资源(CPU、内存等),而使用消息过滤技术,能让订阅者只 接受它须要的消息。(消息过滤对于队列消费尤为重要,由于一个队列消费者消费消息后其余消费者就再也不可用,此时若是不对消息进行过滤处理,这条消息就很可 能被浪费掉)。
消息选择器使用消息属性和消息头做为条件表达式的传送载体(消息体不能做为消息选择器的参考对象)。
消息选择器由标识符、常量和比较运算符组成:
例:
建立一个消息以下:
TextMessage textMessage = Session.createTextMessage();
textMessage.setText(“mytestMsg”);
textMessage.setStringProperty(“city”,”hangzhou”);
textMessage.setStringProperty(“company”,”mycompany”);
这条消息中设置的消息属性名“city”和“company”表明消息选择器的标识符,”hangzhou”和”mycompany”表明常量
在消费端建立一个选择器:
String selector = “city = 'hangzhou' AND company='mycompany'”;
QueueReceiver qReceiver = qSession.createReceiver(testQ,selector);
其中“=”和“AND”为比较运算符,其余经常使用比较运算符还有:
算数比较运算符(=、>、<、<=、<>等)
like运算符、BETWEEN运算符、IN运算符、IS NULL运算符等
java
8 、消息过滤 数据库
消息订阅者须要对消息进行过滤,不然订阅者就会接受到主题或队列的每一条消息,浪费了没必要要的资源( CPU 、内存等),而使用消息过滤技术,能让订阅者只接受它须要的消息。(消息过滤对于队列消费尤为重要,由于一个队列消费者消费消息后其余消费者就再也不可用,此时若是不对消息进行过滤处理,这条消息就极可能被浪费掉)。 服务器
消息选择器使用消息属性和消息头做为条件表达式的传送载体(消息体不能做为消息选择器的参考对象)。 网络
消息选择器由标识符、常量和比较运算符组成: session
例: 异步
建立一个消息以下: 学习
TextMessage textMessage = Session.createTextMessage(); spa
textMessage.setText(“mytestMsg”); orm
textMessage.setStringProperty(“city”,”hangzhou”); 对象
textMessage.setStringProperty(“company”,”alibaba”);
这条消息中设置的消息属性名 “city” 和 “company” 表明消息选择器的标识符, ”hangzhou” 和 ”alibaba” 表明常量
在消费端建立一个选择器:
String selector = “city = 'hangzhou' AND company='alibaba' ”;
QueueReceiver qReceiver = qSession.createReceiver(testQ,selector);
其中 “=” 和 “AND” 为比较运算符,其余经常使用比较运算符还有:
算数比较运算符( = 、 > 、 < 、 <= 、 <> 等)
like 运算符、 BETWEEN 运算符、 IN 运算符、 IS NULL 运算符等
9 、消息传送的可靠性
在消息的传送过程当中因为网络、软硬件故障等都会致使消息的发送失败, jms 为保证消息的传送定义了 3 条法则:
( 1 )消息自主性,消息是自包含的自主性实体,当发送端发出这条消息后这条消息就再也不受发送端的限制,它能够在多个进程间被屡次发送。
( 2 )存储转发,当消息被标记位持久性消息时,就由 jms 提供者利用 “ 保存并转发 ” 机制,将消息保存在可信的介质上,防止发生故障时仍然能够正常恢复
( 3 )消息确认机制,服务器确认已经从发送端收到了消息,消费者则从确认从服务器接收了消息,对消息传送过程的监控,保证了消息的可靠传送。 消息确认的 3 种模式:
1 、 AUTO_ACKNOWLEDGE
从消息生产者角度:发送消息后就开始阻塞,直到从消息服务器收到回复,期间如发生异常则认为消息未被传送
从消息服务器角度:非持久消息在接受到消息后通知生产者,并将消息存入内存,持久性消息在接受道消息后先存入磁盘,而后通知生产者
从消费者角度:接受到消息后就向服务器发送确认信息,若是服务器没有收到确认,会从新发送
2 、 CLIENT_ACKNOWLEDGE
消费者可在处理完业务逻辑后在代码重显示调用 message.acknowledge() 通知 jms 提供者已成功接收道消息
3 、 DUPS_ACKNOWLEDGE
可将一条消息向同一目的地发送两次以上
这里介绍两个概念:
( 1 )持久化消息:消息持久化就是在发送者将消息发送出去后,消息中心首先将消息存储到本地数据文件、内存数据库或者远程数据库等,而后试图将消息发送给接收 者,发送成功则将消息从存储中删除,失败则继续尝试。消息中心启动之后首先要检查制定的存储位置,若是有未发送成功的消息,则须要把消息发送出去。经过在消息头设置来实现:如
MessageProducer producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
(2) 持久订阅者和非持久订阅者:非持久订阅者是指某个订阅者因为某种缘由中止运行,那么在中止运行期间发布到该订阅者所订阅主题的消息就会没法得到,持久订阅者则恰好相反,持久订阅者会接收发送到订阅主题的全部消息,不管订阅者是否正常运行,电子邮件就是相似的一个例子。
持久化消息和持久订阅者在服务器和消费者端之间的消息传送保证机制比较相似, 但在有一种状况下他们仍是存在区别的,对持久订阅者来讲,当消息服务器向发送者发送确认消息以后,并为当前未运行的持久订阅者将消息保存到介质之间若是发 送故障,该消息就会丢失,而持久化消息则是先保存消息道介质,而后才向发送者发送确认消息,因此不存在这个问题,所以严格来讲持久化消息的可靠性会更高。
10 、事务性消息
jms 事务性保证了一组发送的消息或接收的消息要么所有成功要么所有失败,概念上和咱们在java 中使用的jta 类似,但jms 事务是由jms 提供者来管理的,而不是jta 。
使用方法以下:
// 此处用true ,表示使用事务性消息
Session session =connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
// 用来发送的3 个消息
MessageProducer sender = session.createProducer(“queue/testQueue”);
try{
TextMessage message1 = session.createTextMessage(“ 要发送的消息1”);
sender.send(message);
TextMessage message2 = session.createTextMessage(“ 要发送的消息2”);
sender.send(message);
TextMessage message3 = session.createTextMessage(“ 要发送的消息3”);
sender.send(message);
session.commit();
}catch(Exception e){
try{
session.rollback();
}catch(JMSException e){
}
}