一,背景
近期需要用到ActiveMQ接收Oozie执行作业之后的返回结果。Oozie作为消息的生产者,将消息发送给ActiveMQ,然后Client可以异步去ActiveMQ取消息。
ActiveMQ作为基于 JMS 开源的Apache Message Provider,故记录下JMS相关基础知识。
二,基础知识&基本概念
1)面向消息的中间件
Message-oriented middleware (MOM) is best described as a category of software for communication in an loosely-coupled, reliable, scalable and secure manner amongst distributed applications or systems
面向消息的中间件主要就是为了降低各个应用程序之间的耦合。
以前的软件之间的通信如下:
都是各个终端(应用程序)直接与主机通信(mainframe)。
而MOM的理念则是,在消息发送者与消息的接收者之间有一个message mediator 。This mediation provides a whole new level of loose coupling for enterprise messaging.
引入MOM的好处:
①This is the mechanism that allows for loose coupling between senders and receivers as there is no requirement for each to be connected to the MOM for sending and receiving messages.
可以做到 不必要求发送者和接收者同时“在线”(actived)才能进行消息通信。发送者只管把消息发给MOM,然后可以“离开”,接收者可以在随后任何时间去取(取决于何种通信模式)
即,发送者不需要知道接收者的存在,且可进行异步通信。
②MOMs added many additional features to enterprise messaging that weren't previously possible when systems were tightly coupled.
MOM还可以提供一些额外的功能:比如,消息的持久化(message persistence)、消息的转化、消息之间的路由……而这些在未引入MOM系统中很难实现的。
③ MOMs on the market today provide support for a diverse set of protocols for connectivity
支持各种各样的连接协议,即Client可以通过如HTTP/TCP....协议连接MOM。
④Furthermore, it's typical for a MOM to provide an API for sending and receiving messages and otherwise interacting with the MOM.
提供了相应的API发送及接收消息。
举个不恰当的例子来说:对于用户登陆(QQ或者淘宝的登陆),用户登陆后需要获得一系列的状态信息(好友动态、离线消息、订阅公众号的消息...)。这些信息都是由不同的系统(好友动态系统、离线消息系统、订阅公众号消息系统...)产生的 ,那么登陆系统需要直接与这些系统交互,即通过“服务调用”的方式让其他系统感知到登陆事件发生了。如果还需要其他额外的功能,比如登陆之后向用户发送短信、为了验证安全向 安全验证系统 发送登陆的时间及IP地址……这意味着登陆系统会变得异常复杂。
于是,就可以用下面讲到的“发布订阅”模型来实现系统之间解耦。如图Figure2.7,Producer是登陆系统,用户登陆后产生Topic,每个Subscriber都是依赖登陆事件的各种其他系统。
2)为什么有JMS?
1)中介绍了MOM的好处,正因为现实中存在许许多多的MOM厂商,他们开发出不同的MOM产品,如Apache的ActiveMQ,如WebSphereMQ....每家的MOM产品都有一套自己的发送、接收消息的API,因此,不同产品之间兼容性,和操作的统一性就出了问题。从而就出现了JMS。
The Java Message Service (JMS) moved beyond vender-centric MOM APIs to provide an API for enterprise messaging. JMS aims to provide a standardized API to send and receive messages using the Java programming language in a vendor-neutral manner.
The JMS API lowers the barrier to the creation of enterprise messaging applications among different JMS providers. It also eases the portability to other JMS providers.
从上图看出:JMS 客户端通过JMS 规定的API 访问 各种各样的基于JMS协议的消息中间件产品。这与Client 访问 数据库的方式十分相似。
每一家JMS都有自己的产品,如Apache ActiveMQ,每家公司都遵守JMS协议来为自己的产品开发出接口。而用户只需要与统一的JMS API打交道。
在数据库领域,有MySQL、Oracle、SQLSERVER……,但用户程序只需要通过JDBC就可以来访问各种数据库。
JMS clients utilize the JMS API for interacting with the JMS provider. Similar in concept to the using the JDBC API to access data in relational databases, JMS clients use the JMS API for standardized access to the messaging service.
关于JMS的一些基本概念
JMS Producer - A client application that creates and sends JMS messages.
JMS Consumer - A client application that receives and processes JMS messages.
JMS Domains - The two styles of messaging that include point-to-point and publish/subscribe.---点对点模型和发布订阅模型
JMS Provider - The implementation of the JMS interfaces which is ideally written in 100% pure Java.相当于各个开发出JMS产品的厂商
Administered Objects - Preconfigured JMS objects that contain provider-specific configuration data for use by clients. These objects are typically accessible by clients via JNDI.
Connection Factory - Clients use a connection factory to create connections to the JMS provider
Destination - An object to which messages are addressed and sent and from which messages are received.
JMS Message
一个JMS消息由三部分组成:Headers、Properties、Payload
Headers包含该消息的属性:如,消息要发送到哪里去?由JMSDestination字段来表示;
消息的传递模式,由 JMSDeliveryMode表示,传输模式有两种:
1)Persistent:Advises the JMS provider to persist the message so it's not lost if the provider fails. A JMS provider must deliver a persistent message once-and-only-once. In other words, if the JMS provider fails, the message will not be lost and will not be delivered more than once.
在该模式下,provider宕机了,消息不会丢失,且消息只会传递一次。
2)Non-Persistent:Instructs the JMS provider not to persist the message. A JMS provider must deliver a non-persistent message at-most-once. In other words, if the JMS provider fails, the message may be lost, but it will not be delivered twice.
......//还有许多其他的头部属性
Properties与Headers有点类似。
Payload:存储JMS实际消息的地方。可以以text形式、二进制形式存储消息。
JMS Selector
Consider the fact that there are times when a JMS client is subscribed to a given destination, but it may want to filter the types of messages it receives. This is exactly where headers and properties can be used.
Message selectors allow a JMS client to specify which messages it wants to receive from a destination based on values in message headers.
Message Selector允许用户只接收自己感兴趣的消息。
JMS Domain---消息传输模型
The point-to-point (PTP) messaging domain uses destinations known as queues.
点对点模型传输的目的地是队列。
Each message received on the queue is delivered to once-and-only-once consumer.
点对点嘛,消息只能发送给唯一的一个consumer。
Consumers receive messages from the queue either synchronously using the MessageConsumer.receive() method or asynchronously by registering a MessageListener implementation using the MessageConsumer.setMessageListener() method.
它支持同步通信和异步通信,同步通信使用MessageConsumer.receive()来接收消息。异步通信需要MessageListener监听器的支持。
发布-订阅模型
The publish/subscribe (pub/sub) messaging domain uses destinations known as topics
发布-订阅模型传输的目的地是Topics。
Any messages sent to the topic are delivered to all subscribers via a push model, as messages are automatically delivered to the subscriber.
JMS采用Push方式,即主动地把消息推送给订阅者。
发布-订阅模型中有两种订阅方式,一种是持久订阅(Durable subscriptions),另一种是非持久订阅。
非持久订阅:只有当 Client与JMS Provider(如,ActiveMQ)保持连接状态才能收到发送到某个Topic的消息。若Client处于离线,这个时间段发送到Topic的消息会丢失。
持久订阅:Using a durable subscription, when a subscriber disconnects from the JMS provider, it is the responsibility of the JMS provider to store messages for the subscriber
Message Durability 与 Message Persistence 的区别
Message Durability针对 Pub/Sub Domain而言的,它是指接收者以何种方式去接收消息,如果采用非持久订阅,接收者在消息发布到消息服务器的时候 没有连接到消息服务器,则它将收不到这个消息。
而Message Persistence与Domain无关,点对点模型中也存在Message Persistence问题。因为它是针对消息服务器而言的,描述的是消息的可靠性,即当消息服务器宕机后,消息是否丢失。
Message persistence is independent of the message domain. It is used to indicate the JMS application's ability to handle missing messages in the event of a JMS provider failure.
this quality of service is specified on the producer using the JMSDeliveryMode property using either the persistent or non-persistent property.
参考书籍:《ActiveMQ in Action》第二章