Java消息服務

**Java 訊息服務**（**Java Message Service**，**JMS**）應用程式介面是一個 Java 平台中關於訊息導向中介軟體（MOM）的 API，用於在兩個應用程式之間，或分散式系統中傳送訊息，進行非同步通信。Java 訊息服務是一個與具體平台無關的 API，絕大多數 MOM 提供商都對 JMS 提供支援。

Java 訊息服務的規範包括兩種訊息模式，對等和發布者／訂閱者。許多提供商支援這一通用框架因此，程式設計師可以在他們的分散式軟體中實現訊息導向的操作，這些操作將具有不同訊息導向中介軟體產品的可移植性。

Java 訊息服務支援同步和非同步的訊息處理，在某些場景下，同步訊息是必要的；在其他場景下，非同步訊息比同步訊息操作更加便利。

Java 訊息服務支援面向事件的方法接收訊息，事件驅動的程式設計現在被廣泛認為是一種富有成效的程式設計範例，程式設計師們都相當熟悉。

在應用系統開發時，Java 訊息服務可以推遲選擇面對訊息中介軟體產品，也可以在不同的面對訊息中介軟體切換。

## 歷史

Java 訊息服務是一個在 Java 標準化組織（JCP）內開發的標準（代號 JSR 914）。2001 年 6 月 25 日，Java 訊息服務發布 JMS 1.0.2b，2002 年 3 月 18 日 Java 訊息服務發布 1.1，統一了訊息域。

## 體系架構

### JMS 元素

JMS 由以下元素組成。

**JMS 提供者**
: 連接訊息導向中介軟體的，JMS 介面的一個實現。提供者可以是 Java 平台的 JMS 實現，也可以是非 Java 平台的訊息導向中介軟體的配接器。

**JMS 客戶**
: 生產或消費訊息的基於 Java 的應用程式或物件。

**JMS 生產者**
: 建立並行送訊息的 JMS 客戶。

**JMS 消費者**
: 接收訊息的 JMS 客戶。

**JMS 訊息**
: 包括可以在 JMS 客戶之間傳遞的資料的物件

**JMS 佇列**
: 一個容納那些被傳送的等待閱讀的訊息的區域。佇列暗示，這些訊息將按照順序傳送。一旦一個訊息被閱讀，該訊息將被從佇列中移走。

**JMS 主題**
: 一種支援傳送訊息給多個訂閱者的機制。

### JMS 模型

Java 訊息服務應用程式結構支援兩種模型：

* 對等或佇列模型
* 發布 / 訂閱模型

在對等或佇列模型下，一個生產者向一個特定的佇列發布訊息，一個消費者從該佇列中讀取訊息。這裡，生產者知道消費者的佇列，並直接將訊息傳送到消費者的佇列。這種模式被概括為：

* 只有一個消費者將獲得訊息
* 生產者不需要在接收者消費該訊息期間處於執行狀態，接收者也同樣不需要在訊息傳送時處於執行狀態。
* 每一個成功處理的訊息都由接收者簽收

發布者／訂閱者模型支援向一個特定的訊息主題發布訊息。0 或多個訂閱者可能對接收來自特定訊息主題的訊息感興趣。在這種模型下，發布者和訂閱者彼此不知道對方。這種模式好比是匿名公告板。這種模式被概括為：

* 多個消費者可以獲得訊息
* 在發布者和訂閱者之間存在時間依賴性。發布者需要建立一個訂閱（subscription），以便客戶能夠訂閱。訂閱者必須保持持續的活動狀態以接收訊息，除非訂閱者建立了持久的訂閱。在那種情況下，在訂閱者未連接時發布的訊息將在訂閱者重新連接時重新發布。

使用 Java 語言，JMS 提供了將應用與提供資料的傳輸層相分離的方式。同一組 Java 類可以通過 JNDI 中關於提供者的資訊，連接不同的 JMS 提供者。這一組類首先使用一個連接工廠以連接到佇列或主題，然後傳送或發布訊息。在接收端，客戶接收或訂閱這些訊息。

## JMS 應用程式介面

Java 訊息服務的 API 在 `javax.jms` 包中提供。

### `ConnectionFactory` 介面（連接工廠）

使用者用來建立到 JMS 提供者的連接的被管物件。JMS 客戶通過可移植的介面存取連接，這樣當下層的實現改變時，代碼不需要進行修改。 管理員在 JNDI 命名空間中組態連接工廠，這樣，JMS 客戶才能夠尋找到它們。根據訊息類型的不同，使用者將使用佇列連接工廠，或者主題連接工廠。

### `Connection` 介面（連接）

連接代表了應用程式和訊息伺服器之間的通信鏈路。在獲得了連接工廠後，就可以建立一個與 JMS 提供者的連接。根據不同的連接類型，連接允許使用者建立對談，以傳送和接收佇列和主題到目標。

### `Destination` 介面（目標）

目標是一個包裝了訊息目標識別碼的被管物件，訊息目標是指訊息發布和接收的地點，或者是佇列，或者是主題。JMS 管理員建立這些物件，然後使用者通過 JNDI 發現它們。和連接工廠一樣，管理員可以建立兩種類型的目標，對等模型的佇列，以及發布者／訂閱者模型的主題。

### `MessageConsumer` 介面（訊息消費者）

由對談建立的物件，用於接收傳送到目標的訊息。消費者可以同步地（阻塞模式），或非同步（非阻塞）接收佇列和主題類型的訊息。

### `MessageProducer` 介面（訊息生產者）

由對談建立的物件，用於傳送訊息到目標。使用者可以建立某個目標的傳送者，也可以建立一個通用的傳送者，在傳送訊息時指定目標。

### `Message` 介面（訊息）

是在消費者和生產者之間傳送的物件，也就是說從一個應用程式創送到另一個應用程式。一個訊息有三個主要部分：

1. 訊息頭（必須）：包含用於辨識和為訊息尋找路由的操作設定。
2. 一組訊息屬性（可選）：包含額外的屬性，支援其他提供者和使用者的相容。可以建立客製化的欄位和過濾器（訊息選擇器）。
3. 一個訊息體（可選）：允許使用者建立五種類型的訊息（文字訊息，對映訊息，位元組訊息，流訊息和物件訊息）。

訊息介面非常靈活，並提供了許多方式來客製化訊息的內容。

### `Session` 介面（對談）

表示一個單執行緒的上下文，用於傳送和接收訊息。由於對談是單執行緒的，所以訊息是連續的，就是說訊息是按照傳送的順序一個一個接收的。對談的好處是它支援事務。如果使用者選擇了事務支援，對談上下文將儲存一組訊息，直到事務被提交才傳送這些訊息。在提交事務之前，使用者可以使用回滾操作取消這些訊息。一個對談允許使用者建立訊息生產者來傳送訊息，建立訊息消費者來接收訊息。

## JMS 提供者實現

要使用 Java 訊息服務，你必須要有一個 JMS 提供者，管理對談和佇列。現在既有開源的提供者也有專有的提供者。

開源的提供者包括：

* Kafka
* Apache ActiveMQ
* JBoss 社區所研發的 HornetQ
* Joram （頁面存檔備份，存於網際網路檔案館）
* Coridan 的 MantaRay （頁面存檔備份，存於網際網路檔案館）
* The OpenJMS Group （頁面存檔備份，存於網際網路檔案館）的 OpenJMS

專有的提供者包括：

* BEA 的 BEA WebLogic Server JMS
* TIBCO 軟體公司的 EMS
* GigaSpaces Technologies （頁面存檔備份，存於網際網路檔案館）的 GigaSpaces
* Softwired 2006 的 iBus
* IONA Technologies 的 IONA JMS
* SeeBeyond （頁面存檔備份，存於網際網路檔案館）的 IQManager（2005 年 8 月被 Sun Microsystems 併購）
* webMethods 的 JMS+ - http://www.webmethods.com （頁面存檔備份，存於網際網路檔案館）
* my-channels （頁面存檔備份，存於網際網路檔案館）的 Nirvana
* Sonic Software 的 SonicMQ
* IBM 的 WebSphere MQ

一個詳盡的 JMS 提供者對比矩陣可以在這裡 （頁面存檔備份，存於網際網路檔案館）看到。

如果你計劃在一個伺服器叢集中執行你的程式，你需要檢查提供者是否實現了對負載均衡和故障恢復的支援。

## 參見

* J2EE 連接器架構
* J2EE
* JDBC
* 訊息導向中介軟體
* 企業應用整合

## 外部連結

* Sun's JMS Overview （頁面存檔備份，存於網際網路檔案館）
* JSR 914 （頁面存檔備份，存於網際網路檔案館） (JMS 1.0 and 1.1)
* GigaSpaces Technologies JavaSpaces approach to JMS