一男旗、JMS簡介
1.1 JMS是什么
JMS Java Message Service Java消息服務(wù)。是JAVA EE中的一個技術(shù)欣鳖,JMS定義了JAVA中訪問消息中間件的接口察皇。類似JDBC。定義了接口,并不具體實(shí)現(xiàn)什荣。實(shí)現(xiàn)JMS接口消息的中間件稱為JMS Provider.例如:ActiveMQ.
Java消息服務(wù)是一個與具體平臺無關(guān)的API矾缓,絕大多數(shù)MOM提供商都對JMS提供支持(百度百科給出的概述)。我們可以簡單的理解:兩個應(yīng)用程序之間需要進(jìn)行通信稻爬,我們使用一個JMS服務(wù)嗜闻,進(jìn)行中間的轉(zhuǎn)發(fā),通過JMS 的使用桅锄,我們可以解除兩個程序之間的耦合琉雳。
1.2 JMS的優(yōu)勢
Asynchronous(異步)
JMS is asynchronous by default. So to receive a message, the client is not required to send the request. The message will arrive automatically to the client as they become available.(JMS 原本就是一個異步的消息服務(wù),客戶端獲取消息的時候友瘤,不需要主動發(fā)送請求翠肘,消息會自動發(fā)送給可用的客戶端)
Reliable(可靠)
JMS provides the facility of assurance that the message will delivered once and only once. You know that duplicate messages create problems. JMS helps you avoiding such problems.(JMS保證消息只會遞送一次。大家都遇到過重復(fù)創(chuàng)建消息問題辫秧,而JMS能幫你避免該問題束倍。)
1.3 JMS的可靠性機(jī)制
消息確認(rèn)JMS消息只有被確認(rèn)之后,才能認(rèn)為被成功的消費(fèi)了盟戏。一般消息被成功消費(fèi)分三個步驟绪妹,客戶接受消息,處理消息柿究,確認(rèn)消息邮旷。消息何時被確認(rèn)取決于創(chuàng)建會話時的應(yīng)答模式。應(yīng)答模式有三種:?1.Session.AUTO_ACKNOWLEDGE:客戶從receive方法成功返回笛求,或者從MessageListener.onMessage方法成功返回時候廊移,會話自動確認(rèn)客戶收到消息。?2.Session_CLIENT_ACKNOWLEDGE:客戶通過調(diào)用acknowledge方法確認(rèn)消息探入。這個確認(rèn)是會話級別的確認(rèn)狡孔。也就是說只要確認(rèn)一個被消費(fèi)消息,那么這個會話上的所有被消費(fèi)的消息都會被確認(rèn)蜂嗽。?3.Session_DUPS_ACKNOWLEDGE:會話遲鈍的確認(rèn)消息苗膝。選擇這個模式有可能出現(xiàn)重復(fù)的消息。JMSRedelivered會是true.
消息持久性JMS支持兩種消息提交模式:?1.PERSISTENT:持久模式植旧。?2.NON_PERSISTENT:非持久模式辱揭。這個兩種模式上面有介紹。
消息優(yōu)先級消息優(yōu)先級病附,等級從0-9.默認(rèn)為4.數(shù)值越大问窃,優(yōu)先級越高。
消息過期消息過期時間完沪。默認(rèn)為永久不過期域庇。
持久訂閱持久訂閱嵌戈,首先消息的生產(chǎn)者必須使用持久模式提交信息,消費(fèi)者可以通過createDurableSubscriber方法來創(chuàng)建一個持久訂閱听皿。持久訂閱在某一個時刻只能有一個激活的訂閱者熟呛。持久訂閱創(chuàng)建之后會一直保存,直到應(yīng)用程序在會話上調(diào)用unsubcribe方法尉姨。
本地事物JMS session提供了commit與rollback方法來控制事物庵朝。事物提交意味著生產(chǎn)的所有消息被提交,消費(fèi)的所有消息被確認(rèn)又厉【鸥回滾意味著生產(chǎn)的所有消息被銷毀,消費(fèi)的所有消息被恢復(fù)并重新提交覆致,除非它們過期昔逗。
1.4 JMS的API結(jié)構(gòu)
(1)管理對象(Administered objects)-連接工廠(Connection Factories)和目的地(Destination)
(2)連接對象(Connections)
(3)會話(Sessions)
(4)消息生產(chǎn)者(Message Producers)
(5)消息消費(fèi)者(Message Consumers)
(6)消息監(jiān)聽者(Message Listeners)
(1)、Connection Factories
創(chuàng)建Connection對象的工廠篷朵,針對兩種不同的jms消息模型,分別有QueueConnectionFactory和TopicConnectionFactory兩種婆排∩可以通過JNDI來查找ConnectionFactory對象《沃唬客戶端使用一個連接工廠對象連接到JMS服務(wù)提供者腮猖,它創(chuàng)建了JMS服務(wù)提供者和客戶端之間的連接。JMS客戶端(如發(fā)送者或接受者)會在JNDI名字空間中搜索并獲取該連接赞枕。使用該連接澈缺,客戶端能夠與目的地通訊,往隊(duì)列或話題發(fā)送/接收消息炕婶。
QueueConnectionFactory queueConnFactory = (QueueConnectionFactory) initialCtx.lookup ("primaryQCF");
Queue purchaseQueue = (Queue) initialCtx.lookup ("Purchase_Queue");
Queue returnQueue = (Queue) initialCtx.lookup ("Return_Queue");
[if !supportLists](2)[endif]姐赡、Destination
目的地指明消息被發(fā)送的目的地以及客戶端接收消息的來源。JMS使用兩種目的地柠掂,隊(duì)列和話題项滑。如下代碼指定了一個隊(duì)列和話題:
創(chuàng)建一個隊(duì)列Session:
QueueSession ses = con.createQueueSession (false, Session.AUTO_ACKNOWLEDGE); ?//get the Queue object ?
Queue t = (Queue) ctx.lookup ("myQueue"); ?//create QueueReceiver ?
QueueReceiver receiver = ses.createReceiver(t);
(3)、Connection
Connection表示在客戶端和JMS系統(tǒng)之間建立的鏈接(對TCP/IP socket的包裝)涯贞。Connection可以產(chǎn)生一個或多個Session枪狂。跟ConnectionFactory一樣,Connection也有兩種類型:QueueConnection和TopicConnection宋渔。
連接對象封裝了與JMS提供者之間的虛擬連接州疾,如果我們有一個ConnectionFactory對象,可以使用它來創(chuàng)建一個連接皇拣。
Connection connection = connectionFactory.createConnection();
(4)严蓖、Session
Session是我們對消息進(jìn)行操作的接口,可以通過session創(chuàng)建生產(chǎn)者、消費(fèi)者谈飒、消息等岂座。Session 提供了事務(wù)的功能,如果需要使用session發(fā)送/接收多個消息時杭措,可以將這些發(fā)送/接收動作放到一個事務(wù)中费什。
我們可以在連接創(chuàng)建完成之后創(chuàng)建session:
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
這里面提供了參數(shù)兩個參數(shù),第一個參數(shù)是是否支持事務(wù)手素,第二個是事務(wù)的類型
(5)鸳址、Producter
消息生產(chǎn)者由Session創(chuàng)建,用于往目的地發(fā)送消息泉懦。生產(chǎn)者實(shí)現(xiàn)MessageProducer接口稿黍,我們可以為目的地、隊(duì)列或話題創(chuàng)建生產(chǎn)者崩哩;
MessageProducer producer = session.createProducer(dest);
MessageProducer producer = session.createProducer(queue);
MessageProducer producer = session.createProducer(topic);
(6)巡球、Consumer
消息消費(fèi)者由Session創(chuàng)建,用于接收被發(fā)送到Destination的消息邓嘹。
MessageConsumer consumer = session.createConsumer(dest);
MessageConsumer consumer = session.createConsumer(queue);
MessageConsumer consumer = session.createConsumer(topic);
(7)酣栈、MessageListener
消息監(jiān)聽器。如果注冊了消息監(jiān)聽器汹押,一旦消息到達(dá)矿筝,將自動調(diào)用監(jiān)聽器的onMessage方法。EJB中的MDB(Message-Driven Bean)就是一種MessageListener棚贾。
1.5 JMS應(yīng)用的基本步驟
(1)創(chuàng)建Connection Factory
(2)通過factory創(chuàng)建Connection窖维。
(3)啟動Connection
(4)通過Connection創(chuàng)建JMS Session
(5)session創(chuàng)建destination
(6)session創(chuàng)建producer 并設(shè)置destination。
(7)session創(chuàng)建consumer,設(shè)置目的地妙痹≈罚或者注冊一個JMS Message listener.
(8)發(fā)送或者接受Message(s)
(9)關(guān)閉所有JMS資源。
二细诸、JMS基本概念
2.1 JMS Message
JMS Message JMS消息沛贪,JMS消息由三部分組成?(1)消息頭:每個消息頭都有對應(yīng)的setter、getter方法震贵。?(2)消息屬性:如果需要除消息頭以外的值利赋,可以使用消息屬性。(3)消息體:封裝具體的消息數(shù)據(jù)猩系。
2.2 JMS producer
JMS Producer:消息生產(chǎn)者媚送,創(chuàng)建和發(fā)送JMS Message的客戶端應(yīng)用。
2.3 JMS consumer
JMS Consumer:消息消費(fèi)者寇甸,接收和處理JMS Message的客戶端應(yīng)用塘偎。消息的消費(fèi)可以采取以下兩種消費(fèi)方式疗涉。?(1)同步消費(fèi):通過調(diào)用消費(fèi)者的receive方法從目的地中顯示的提取消息,receive方法會一直阻塞吟秩,知道消息到達(dá)咱扣。?
(2)異步消費(fèi):通過為消費(fèi)者注冊一個消息監(jiān)聽器,定義消息到達(dá)時采取的動作涵防。
2.4 JMS domains
JMS domains: 消息傳遞域闹伪。也可以理解為消息傳遞的方式。JMS規(guī)范中定義了兩種消息傳遞的機(jī)制壮池,點(diǎn)對點(diǎn)(point-to-point, 簡寫PTP)和發(fā)布/訂閱(publish/subscribe,簡寫pub/sub).?1.PTP的特點(diǎn)如下:?(1)每個消息只能有一個消費(fèi)者偏瓤。PTP目的地被稱為隊(duì)列(Queue)。?(2)消費(fèi)者和生產(chǎn)者之間沒有時間相關(guān)性椰憋。也就是說消息生產(chǎn)者不管消費(fèi)者是否處于運(yùn)行狀態(tài)都可以發(fā)送消息厅克,而消費(fèi)者也可以不管生產(chǎn)者是否在線都可以接收消息。?
2.pub/sub特點(diǎn)橙依。?(1)每個消息可以有多個消費(fèi)者证舟。生產(chǎn)者把消息發(fā)布到一個“主題”上。?(2)生產(chǎn)者和消費(fèi)者之間有時間相關(guān)性窗骑。也就是說褪储,消費(fèi)者只能消費(fèi)它訂閱的主題之后,主題發(fā)布的消息慧域。而且如果沒有進(jìn)行持久訂閱,那么消費(fèi)者只能消費(fèi)在線時生產(chǎn)者發(fā)布的消息浪读。JMS規(guī)范允許進(jìn)行持久訂閱昔榴。一定程度上減少了時間的相關(guān)性。pub/sub目的地被稱為主題(Topic)?
2.5 Connection Factory
connection factory:連接工廠碘橘,用來創(chuàng)建連接到JMS Provider連接對象互订。
2.6 JMS Connection
connection:連接對象。封裝了客戶與JMS Provider的一個虛擬連接痘拆。
2.7 JMS Session
session:生產(chǎn)和消費(fèi)消息的一個單線程上下文仰禽。會話用于創(chuàng)建生產(chǎn)者、消費(fèi)者纺蛆、目的地吐葵、消息等,會話提供了一個事物性的上下文桥氏,在會話中温峭,一組發(fā)送和接收消息被組合到一個操作中。
2.8 Destination
destination:消息發(fā)送和接收的目的地字支。
2.9 JMS Client
client:用來接收消息的應(yīng)用凤藏。
2.10 JMS消息結(jié)構(gòu)
JMS Message由消息頭奸忽,消息屬性,消息體三部分組成揖庄。
2.11 JMS消息頭
消息頭包含消息的識別信息和路由信息栗菜,消息頭的一些標(biāo)準(zhǔn)屬性如下:1.JMSDestination:消息發(fā)送目的地,由Send方法設(shè)置蹄梢,主要指點(diǎn)對點(diǎn)中的Queue與pub/sub中的Topic,自動分配疙筹。?2.JMSDeliveryMode:傳送模式,傳送模式分為如下兩種:?(1)持久模式:一條持久性的消息應(yīng)該被傳送“一次僅僅一次”。一次就是這個消息一定會被傳遞一次检号。例如JMS提供者出現(xiàn)故障腌歉,那么在恢復(fù)之后這條消息不會丟失,會再次被傳遞齐苛,直到成功翘盖。僅僅一次,就只要傳遞成功就不會再次被傳遞凹蜂。?(2)非持久模式:一條非持久的消息“最多被傳送一次“馍驯。最多一次意味著這條消息有可能丟失。如服務(wù)器故障玛痊,恢復(fù)后次消息會被丟失汰瘫。?3.JMSExpiration:由Send方法設(shè)置。消息過期時間擂煞。默認(rèn)為永久不過期混弥。?4.JMSPriority:消息優(yōu)先級,等級從0-9.默認(rèn)為4.數(shù)值越大对省,優(yōu)先級越高蝗拿。?5.JMSMessageID:唯一識別每個消息的標(biāo)志。由JMS Provider產(chǎn)生蒿涎,自動分配哀托。?6.JMSTimestamp:JMS Provider調(diào)用Send方法時候自動設(shè)置,是消息被返送和消息被消費(fèi)之間的實(shí)際時間差劳秋。?7.JMSCorrelationID:用來連接到另外一個消息仓手。典型的應(yīng)用就是在回復(fù)消息中連接到原消息。JMSCorrelationID可以由開發(fā)者設(shè)置稱為任何值玻淑。?8.JMSReplyTo: 提供本消息回復(fù)消息的目的地地址嗽冒。由開發(fā)者設(shè)置。?9.JMSType: 消息類型識別符补履,由開發(fā)者設(shè)置辛慰。?10.JMSRedelivered:這個有兩個值,true或者false干像。如果為true說明這條消息被客戶端收到過帅腌,但是因?yàn)槟撤N原因沒有被簽收驰弄。
2.12 JMS消息屬性
消息屬性包含三種類型:(1)應(yīng)用程序添加的屬性。如:message.setStringProperty(“userName”,”張三”);?(2)JMS定義的屬性速客。使用”JMSX”作為屬性的前綴名戚篙。?(3)JMS供應(yīng)商定義的屬性。
2.13 JMS消息體
- JMS API定義了5中形式的消息體溺职,也可以理解為5中消息類型岔擂。TextMessage、MapMessage浪耘、BytesMessage乱灵、StreamMessage、ObjectMessage.
三七冲、JMS的消息模型
3.1 JMS具有兩種通信模式
1痛倚、Point-to-Point Messaging Domain (點(diǎn)對點(diǎn))
2、Publish/Subscribe Messaging Domain (發(fā)布/訂閱模式)
在JMS API出現(xiàn)之前澜躺,大部分產(chǎn)品使用“點(diǎn)對點(diǎn)”和“發(fā)布/訂閱”中的任一方式來進(jìn)行消息通訊蝉稳。JMS定義了這兩種消息發(fā)送模型的規(guī)范,它們相互獨(dú)立掘鄙。任何JMS的提供者可以實(shí)現(xiàn)其中的一種或兩種模型耘戚,這是它們自己的選擇。JMS規(guī)范提供了通用接口保證我們基于JMS API編寫的程序適用于任何一種模型操漠。
3.2 JMS模式
JMS為發(fā)開者提供了很多的要素收津,看一下比較重要的幾個:
3.3 JMS點(diǎn)對點(diǎn)通信模型
Point-to-Point Messaging Domain(點(diǎn)對點(diǎn)通信模型)
涉及到的概念:在點(diǎn)對點(diǎn)通信模式中,應(yīng)用程序由消息隊(duì)列浊伙,發(fā)送方朋截,接收方組成。每個消息都被發(fā)送到一個特定的隊(duì)列吧黄,接收者從隊(duì)列中獲取消息。隊(duì)列保留著消息唆姐,直到他們被消費(fèi)或超時拗慨。
特點(diǎn):
(1)每個消息只要一個消費(fèi)者
(2)發(fā)送者和接收者在時間上是沒有時間的約束,也就是說發(fā)送者在發(fā)送完消息之后奉芦,不管接收者有沒有接受消息赵抢,都不會影響發(fā)送方發(fā)送消息到消息隊(duì)列中。
(3)發(fā)送方不管是否在發(fā)送消息声功,接收方都可以從消息隊(duì)列中去到消息(The receiver can fetch message whether it is running or not when the sender sends the message)
(4)接收方在接收完消息之后烦却,需要向消息隊(duì)列應(yīng)答成功
3.4 JMS發(fā)布/訂閱通信模型
Publish/Subscribe Messaging Domain(發(fā)布/訂閱通信模型)
涉及到的概念:在發(fā)布/訂閱消息模型中,發(fā)布者發(fā)布一個消息先巴,該消息通過topic傳遞給所有的客戶端其爵。該模式下冒冬,發(fā)布者與訂閱者都是匿名的,即發(fā)布者與訂閱者都不知道對方是誰摩渺。并且可以動態(tài)的發(fā)布與訂閱Topic简烤。Topic主要用于保存和傳遞消息,且會一直保存消息直到消息被傳遞給客戶端摇幻。
特點(diǎn):
(1)一個消息可以傳遞個多個訂閱者(即:一個消息可以有多個接受方)
(2)發(fā)布者與訂閱者具有時間約束横侦,針對某個主題(Topic)的訂閱者,它必須創(chuàng)建一個訂閱者之后绰姻,才能消費(fèi)發(fā)布者的消息枉侧,而且為了消費(fèi)消息,訂閱者必須保持運(yùn)行的狀態(tài)狂芋。
(3)為了緩和這樣嚴(yán)格的時間相關(guān)性榨馁,JMS允許訂閱者創(chuàng)建一個可持久化的訂閱。這樣银酗,即使訂閱者沒有被激活(運(yùn)行)辆影,它也能接收到發(fā)布者的消息。