标签:
如果手机只能进行实时通话,没有留言和短信功能会怎么样?一个电话打过来,正好没有来得及接上,那么这个电话要传递的信息肯定就收不到了。为什么不能先将信息存下来,当用户需要查看信息的时候再去获得信息呢?伴随着这个疑惑,短信和留言应运而生,无论手机是否开机、是否及时接到,我们都能得到其中的信息。JMS提供了类似这样的功能。
Java消息服务(JMS)是用于访问企业消息系统的开发商中立的API。企业消息系统可以协助应用软件通过网络进行消息交互。JMS在其中扮演的角色与JDBC很相似,正如JDBC提供了一套用于访问各种不同关系数据库的公共API,JMS也提供了独立于特定厂商的企业消息系统访问方式。
在JMS之前,每一家消息中间件厂商都用专有API为应用程序提供对其产品的访问,通常可用于许多种语言,但标准不统一。JMS为Java程序提供一种访问企业消息系统的方法。
企业消息系统,即面向消息的中间件(MOM),提供了以松散耦合的灵活方式集成应用程序的一种机制。它们提供了基于存储和转发的应用程序之间的异步数据发送,即应用程序彼此不直接通信,而是与作为中介的消息中间件通信。消息中间件提供了有保证的消息发送,应用程序开发人员无需了解远程过程调用(PRC)和网络/通信协议的细节。
应用程序A发送一条消息到消息服务器(也就是JMS Provider),然后消息服务器把消息转发给应用程序B。因为应用程序A和应用程序B没有直接的代码关连,所以两者实现了解偶。
应用程序A与应用程序B通过使用MOM的应用程序编程接口(API)发送消息进行通信。MOM将消息路由给应用程序B,这样消息就可以存在于MOM中,MOM负责处理网络通信。如果网络连接不可用,MOM会存储消息,直到连接变得可用时,再将消息转发给应用程序B。
灵活性的另一方面体现在,当应用程序A发送其消息时,应用程序B甚至可以不处于执行状态。MOM将保留这个消息,直到应用程序B开始执行并试着检索消息为止。这还防止了应用程序A因为等待应用程序B检索消息而出现阻塞。
这种异步通信要求应用程序的设计与现在大多数应用程序不同,不过对于时间无关或并行处理,它可能是一个极其有用的方法。
企业消息系统的真正威力在于应用程序的松散耦合。在上面的图中,由应用程序A发送消息指定一个特定目标,如“订单处理”。而现在,是由应用程序B提供订单处理功能。
但是在将来,我们可以用不同的订单处理程序替换应用程序B,应用程序A将不再是明智之选。替换应用程序将继续发送消息完成“订单处理”,而消息也仍将得到处理。
同样,我们也可以替换应用程序A,只要替换应用程序继续发送消息进行“订单处理”,订单处理程序就无需知道是否有一个新的应用程序在发送订单。
1. 将数据从一个应用程序传送到另一个应用程序,或者从软件的一个模块传送到另外一个模块
2. 负责建立网络通信的通道,进行数据的可靠传送
3. 保证数据不重发,不丢失
4. 能够实现跨平台操作,能够为不同操作系统上的软件集成数据传送服务
JMS(JAVA Message Service)是java消息服务,JMS的客户端之间可以通过JMS服务进行异步的消息传输。
JMS是一个消息服务的标准或者说是规范,允许应用程序组件基于JavaEE平台创建、发送、接收和读取消息。它使分布式通信耦合度更低,消息服务更加可靠以及异步性。
JMS是一系列的接口及相关语义的集合,通过这些接口和其中的方法,定义了JMS客户端如何去访问消息系统,完成创建、发送、接收和读取企业消息系统中消息。
JMS通过MOM为Java程序提供了一个发送和接收消息的标准的、便利的方法。用JMS编写的程序可以在任何实现JMS标准的MOM上运行。
JMS可移植性的关键在于:JMS API是由Sun定义的一组接口。提供了JMS功能的产品实现这些接口。开发人员可以通过定义一组消息和一组交换这些消息的应用程序,建立JMS应用程序,实现异步通讯。
JMS的应用程序被称为JMS客户端,处理消息路由与传递的消息服务器被称为JMS Provider,而JMS应用则是由多个JMS客户端和一个JMS Provider构成的业务系统。发送消息的JMS客户端是生产者,而接收消息的JMS客户端是消费者。同一JMS客户端既可以是生产者也可以是消费者。
所有Java应用程序都可以使用JMS中定义的API去完成消息的创建、接收与发送,任何实现了JMS标准的MOM都可以作为消息的中介,完成消息的存储转发。
MOM提供了有保证的消息发送,应用程序开发人员无需了解远程过程调用(PRC)和网络/通信协议的细节,提供了程序的可移植性。
由于MOM的存在,各个应用程序只关心和MOM之间如何进行消息的接收与发送,而无需关注MOM的另一边,其他程序是如何接收和发送的。
JMS提供了两种消息通信模型:
点到点模型(Point-to-Point,P2P)
发布/订阅模型(Publish/Subscribe,Pub/Sub)
在ClientA、C、D之间的消息是点对点模型,使用这种模型,客户端发送消息到队列目的地(Queue),从这个队列里面只有一个消息接收者可以收到那个消息,其他访问同一目的地的接收者不会接收到该消息。如ClientC接收Queue中的Msg1消息,ClientD接收Queue中的Msg2消息。
在ClientB、E、F之间的消息是发布/订阅模型。使用这种广播模型,一个客户端发送消息给主题目的地(Topic),任何数量的消费订阅者可以从这个主题目的地来接收它们。如:ClientE和ClientF都接收这个Msg3这条消息。
每个模型都通过是扩展公用基类来实现的。例如:javax.jms.Queue和Javax.jms.Topic都扩展自javax.jms.Destination类。
每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到他们被消费或超时。
如果你希望发送的每个消息都应该被成功处理的话,那么你需要P2P模式。
这种消息传递模型是传统意义上的拉模型或轮询模型。在此列模型中,消息不会自动推送给客户端,而是要由客户端从队列中请求获得。
如果一条消息被消息者接收,那么其他的消费者就不能得到这条消息了。
当发送者发送了消息之后,不管接收者有没有正在运行,它不会影响到消息被发送到队列。
消费者可以在任意的时刻接收,但有两个前提:1、消息未过期;2、消息没有被其他的用户接收。消费者也可以先运行,当生产者一运行,将消息发送到队列中,消费者即可从队列中获得消息。
收到消息后接收者必须确认消息已被接收,否则JMS服务提供者会认为该消息没有被接收,那么这条消息仍然可以被其他人接收。程序可以自动进行确认,不需要人工干预。
非持久的消息最多只发送一次,消息有可能未被发送,造成未被发送的原因可能有:1、JMS服务提供者出现宕机等情况,造成非持久信息的丢失;2、队列中的消息过期,未被接收
可以将比较重要的消息设置为持久化的消息,持久化后的消息不会因为JMS服务提供者的故障或者其他原因造成消息丢失。
多个发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。
如果你希望发送的消息可以不被处理、或者被一个消息者处理、或者可以被多个消费者处理的话,那么可以采用Pub/Sub模型
这种消息传递模型基本上是一个推模型。在该模型中,消息会自动广播,消费者无须通过主动请求或轮询主题的方法来获得新的消息。
每条消息可以有多个消费者,如果报纸和杂志一样,谁订阅了谁都可以获得。
针对某个主题(Topic),订阅者必须先运行,再等待生产者的发布,并且订阅者必须保持运行的状态。这和点对点类型有所差异。
即订阅者必须保持活动状态等待发布者发布的消息,如果订阅者在发布者发布消息之后才运行,则不能获得先前发布者发布的消息。
为了缓和这样严格的时间相关性,JMS允许订阅者创建一个可持久化的订阅。这样,即使订阅者没有运行,它也能接收到发布者的消息。
一条消息仅能被一个consumer收到。如果在message发送的时候没有可用的consumer,那么它讲被保存一直到能处理该message的consumer可用。如果一个consumer收到一条message后却不响应它,那么这条消息将被转到另外一个consumer那儿。一个Queue可以有很多consumer,并且在多个可用的consumer中负载均衡。
一条消息被publish时,他将发送给所有订阅者,所以零到多个subscriber都将接收到一个消息。
在JMS中,消息的产生和消费是异步的。JMS的消息消费者可以通过两种方式来消费消息。
订阅者或接收者调用receive方法来接收消息,receive方法在能够接收到消息之前(或超时之前)将一直阻塞
订阅者或接收者可以注册为一个消息监听器。当消息到达之后,系统自动调用监听器的onMessage方法。
1. 异步消息接收者创建的网络流量比较小。单向传递消息,并使之通过管道进入消息监听器。管道操作支持将多条消息聚合为一个网络调用。
2. 异步消息接收者使用线程比较少。异步消息接收者在不活动期间不使用线程。同步消息接收者在接收调用期间内使用线程,结果线程可能会长时间保持空闲,尤其是如果该调用中指定了阻塞超时。
3. 对于服务器上运行的应用程序代码,使用异步消息接收者几乎总是最佳选择,尤其是通过消息驱动Bean。使用异步消息接收者可以防止应用程序代码在服务器上执行阻塞操作。而阻塞操作会是服务器端线程空闲,甚至会导致死锁。阻塞操作使用所有线程时则发生死锁。如果没有空余的线程可以处理阻塞操作自身解锁所需的操作,这该操作永远无法停止阻塞。
每条JMS 消息都必须具有消息头。头字段包含用于路由和识别消息的值。可以通过多种方式来设置消息头的值:
a. 由JMS 提供者在生成或传送消息的过程中自动设置
b. 由生产者客户机通过在创建消息生产者时指定的设置进行设置
c. 由生产者客户机逐一对各条消息进行设置
消息可以包含称作属性的可选头字段。他们是以属性名和属性值对的形式制定的。可以将属性是为消息头得扩展,其中可以包括如下信息:创建数据的进程、数据的创建时间以及每条数据的结构。JMS提供者也可以添加影响消息处理的属性,如是否应压缩消息或如何在消息生命周期结束时废弃消息。
包含要发送给接收应用程序的内容。每个消息接口特定于它所支持的内容类型。JMS为不同类型的内容提供了他们各自的消息类型,但是所有消息都派生自Message接口。
StreamMessage 一种主体中包含Java基元值流的消息。其填充和读取均按顺序进行。
MapMessage 一种主体中包含一组键--值对的消息。没有定义条目顺序。
TextMessage 一种主体中包含Java字符串的消息(例如,XML消息)。
ObjectMessage 一种主体中包含序列化Java对象的消息。
BytesMessage 一种主体中包含连续字节流的消息。
创建Connection对象的工厂,针对两种不同的jms消息模型,分别有QueueConnectionFactory和TopicConnectionFactory两种。可以通过JNDI来查找ConnectionFactory对象。
Destination的意思是消息生产者的消息发送目标或者说消息消费者的消息来源。对于消息生产者来说,它的Destination是某个队列(Queue)或某个主题(Topic);对于消息消费者来说,它的Destination也是某个队列或主题(即消息来源)。
所以,Destination实际上就是两种类型的对象:Queue、Topic。可以通过JNDI来查找Destination。
Connection表示在客户端和JMS系统之间建立的链接(对TCP/IP socket的包装)。Connection可以产生一个或多个Session。跟ConnectionFactory一样,Connection也有两种类型:QueueConnection和TopicConnection。
Session是我们操作消息的接口。可以通过session创建生产者、消费者、消息等。Session提供了事务的功能。当我们需要使用session发送/接收多个消息时,可以将这些发送/接收动作放到一个事务中。同样,也分QueueSession和TopicSession。
消息生产者由Session创建,并用于将消息发送到Destination。同样,消息生产者分两种类型:QueueSender和TopicPublisher。可以调用消息生产者的方法(send或publish方法)发送消息。
消息消费者由Session创建,用于接收被发送到Destination的消息。两种类型:QueueReceiver和TopicSubscriber。可分别通过session的createReceiver(Queue)或createSubscriber(Topic)来创建。当然,也可以session的creatDurableSubscriber方法来创建持久化的订阅者。
消息监听器。如果注册了消息监听器,一旦消息到达,将自动调用监听器的onMessage方法。EJB中的MDB(Message-Driven Bean)就是一种MessageListener。
标签:
原文地址:http://www.cnblogs.com/yuexiaohao/p/5567298.html