WebSphere MQ 訊息在傳遞和排隊期間的格式變化
轉自;http://www.ibm.com/developerworks/cn/websphere/library/techarticles/1001_xiao/1001_xiao.html
IBM® WebSphere® MQ 是 IBM 提供的用於商業訊息和佇列傳遞的出色中介軟體。訊息佇列是一種程式到程式的通訊方法,其中應用程式通過佇列傳送和檢索特定於應用程式的資料,無需建立私有的、專用的邏輯連線。一條訊息僅是對使用它的應用程式有意義的一串位元組,而佇列則是訊息的容器。
本文描述 WebSphere MQ 訊息格式的演變以及在訊息排隊過程中由 WebSphere MQ 自動對訊息進行的更改。您需要對基於 WebSphere MQ 的應用程式開發有一定程度的瞭解。
WebSphere MQ 訊息具有典型的 “頭-主體(header-body)” 格式。在 WebSphere MQ 的不同版本中,頭和主體隨內容和概念而有所不同。不過,從第一版到 WebSphere MQ V6(此後簡稱為 V6),訊息格式出現小小的變化。在 WebSphere MQ V7(此後簡稱為 V7)中,為了增加與 Java™ Message Service (JMS) 應用程式的相容性,訊息格式發生了顯著的變化。
在 V6 及之前版本中,WebSphere MQ 訊息的兩個組成部分是:
- 訊息描述符(訊息頭)
- 應用程式資料(訊息體)
圖 1 顯示了 V6 及之前版本的訊息格式:
訊息描述符與佇列管理器內駐留在佇列上的每個訊息相關。它標識訊息且包含控制資訊,比如訊息型別和由傳送應用程式分配的優先順序。應用程式資料部分包含所有實際訊息資料(有效負載)和任何附加頭,比如傳輸頭或 IMS 資訊頭。除最大長度之外,WebSphere MQ 不對應用程式資料施加任何限制,根據 WebSphere MQ 版本的不同,最大長度的變化範圍是 4 到 100MB。對佇列管理器、通道和單個佇列也可定義最大訊息長度。
V6 及之前版本的訊息具有相同的組成結構,但是存在以下一些差異:
- 從 V5 開始訊息描述符的屬性開始改變 — 詳細資訊參見以下內容。
- 訊息資料前面的附加頭的型別更加豐富化。例如,從 V5 開始新增了訊息描述符擴充套件(MQMDE),從 V6 開始新增了嵌入式 PCF 頭(MQEPH)。
1. 訊息描述符
訊息描述符由一種 MQMD 結構定義,這種結構包含大量提供訊息資訊的欄位。下面內容詳細描述了這些屬性中的其中兩個。
-
版本
訊息描述符有兩個版本。自 V5 以來,可以對訊息分段或分組。對於該新功能,需要在訊息描述符中附加欄位來保留分段和分組資訊。 這種擴充套件結構即為訊息描述符的當前版本 V2。V2 訊息描述符與 V1 相同,但是它具有由 MQMDE 結構定義的附加欄位:GroupId、MsgSeqNumber、Offset、MsgFlags 和 OriginalLength。
不支援這些功能的其他佇列管理器(稱作 V1 佇列管理器)將附加資訊看作資料。一個 V2 訊息描述符一般相當於使用一個 V1 訊息描述符並使用 MQMDE 結構為訊息資料新增字首。支援訊息分段和分組的佇列管理器被稱作 V2 佇列管理器。圖 2 顯示了 V1 與 V2 MQMD 之間的關係:
圖 2. V1 與 V2 MQMD 之間的關係
-
格式
格式是訊息傳送者使用的名稱,用於向接收者表明訊息中資料的性質。佇列管理器含有大量以 MQ 字首命名的內建格式,比如 MQFMT_STRING。格式還可用於表示附加頭(擴充套件)的存在。例如,如果訊息描述符中 Format 欄位的值是 MQFMT_CICS,它表示訊息資料以 CICS 資訊頭 MQCIH 開始,後面是負載資料。負載資料的性質由 MQCIH 頭的 Format 欄位表明。圖 3 顯示了對 Format 的使用:
圖 3. 使用 Format 表示訊息中資料的性質
2. 應用程式資料
應用程式資料部分包含從一個程式傳送到另一程式的真實資料,且其內容和結構由使用它的應用程式定義。一般地,應用程式資料僅包含對應用程式有意義的資訊,因為訊息描述符中的控制資訊就已經足夠了。不過在某些環境下需要更多控制資訊並將其以附加頭的形式作為負載資料的字首,如上面圖 1 所示。附加頭可由應用程式針對特殊用途新增,比如傳送訊息到 IMS 網橋時新增 IMS 資訊頭(MQIIH)到應用程式資料。訊息頭有時也由 WebSphere MQ 新增,如下描述。
表 1 列出了由 WebSphere MQ 定義的可用作應用程式資料字首的訊息頭及其格式名稱。
訊息頭 | 訊息頭描述 | 格式名稱 |
---|---|---|
MQCIH | CICS 資訊頭 | MQFMT_CICS |
MQDLH | 死信頭 | MQFMT_DEAD_LETTER_HEADER |
MQDH | 分佈列表(Distribution-list)頭 | MQFMT_DIST_HEADER |
MQEPH | 嵌入式 PCF 頭 | MQFMT_××DED_PCF |
MQIIH | IMS 資訊頭 | MQFMT_IMS |
MQMDE | 訊息描述符擴充套件 | MQFMT_MD_EXTENSION |
MQCFH | PCF 頭 | MQFMT_ADMIN / MQFMT_EVENT / MQFMT_PCF |
MQRMH | 參考訊息頭 | MQFMT_REF_MSG_HEADER |
MQRFH | 格式化頭 | MQFMT_RF_HEADER |
MQRFH2 | 版本 2 規則和格式化頭 | MQFMT_RF_HEADER_2 |
MQWIH | 工作資訊頭 | MQFMT_WORK_INFO_HEADER |
MQXQH | 傳輸佇列頭 | MQFMT_XMIT_Q_HEADER |
我們可對附加頭進行約束,即應用程式資料可以選擇性地在負載資料前包含一個或多個訊息頭。以 WebSphere MQ V7 之前的釋出或訂閱應用程式的訊息為例 — 訊息資料可同時以 MQRFH1 和 MQRFH2 開頭。如果在負載資料前新增多於一個訊息頭時,它們以同樣的方式連結在一起,如上面圖 3 Format 欄位所示。
WebSphere MQ V7(此後簡稱 V7)引入了訊息屬性(來自 JMS)的概念,因此 WebSphere MQ 訊息的兩個組成部分變為:
- 訊息屬性(訊息頭)
- 應用程式資料(訊息體)
V7 的訊息格式如圖 4 所示,圖中還顯示了訊息屬性與訊息描述符之間的對應:
1. 訊息屬性
作為 Message Queue Interface (MQI) 的一部分,訊息屬性是 V7 的新增特性。新的 MQI 函式呼叫用於設定、查詢和刪除訊息屬性(MQSETMP,MQINQMP 和 MQDLTMP)。您也可以使用訊息屬性來包含業務資料或狀態資訊,而無需將其儲存在應用程式資料中。WebSphere MQ 中訊息屬性的使用模仿 JMS 中屬性的使用,從而使您能夠在 JMS 環境中設定屬性,然後在過程 WebSphere MQ 應用程式中檢索它們,反之亦然。
訊息屬性隨 WebSphere MQ 佇列管理器中的任何訊息流動,每個訊息屬性都包括一個文字名稱和一個特定型別的值。訊息管理器的大小不能超過佇列管理器的 MaxPropertiesLength 設定。訊息屬性不計入佇列和佇列管理器的訊息長度中,不過它們計入被佇列管理器認為是屬性的長度中。訊息屬性的長度限值是 100 MB,其中不包括每個訊息的訊息描述符或擴充套件。
2. 以 MQRFH2 表示的訊息屬性
訊息屬性可以以 MQRFH2 元素的形式表示。圖 5 顯示了 MQRFH2 頭的結構:
NameValueData 欄位中的字串包括含有零或更多屬性的單一資料夾。如果 content=properties 元素包含在資料夾 start 標記中,則資料夾的內容會被看作是訊息屬性。如果訊息頭中的每個資料夾都包含屬性,MQRFH2 頭欄位本身會被計入到訊息屬性的長度中,併成為訊息屬性的一部分。否則,頭欄位被計入訊息長度中,成為應用程式資料的一部分。因此,應用程式可使用大於 MaxMsgLength 值的緩衝區放置訊息,前提是該緩衝區包含屬性。
3. 作為屬性的訊息描述符欄位
除了 StructId 和 Version 之外,大多數訊息描述符欄位可被看作屬性。屬性名可通過新增字首到訊息描述符欄位名來構建,例如 Root.MQMD.Priority。這裡 Priority 是訊息描述符中的一個欄位。訊息描述符欄位從來不像其他屬性一樣以 MQRFH2 頭的形式表示。如果以 MQMDE 開頭的訊息資料得到佇列管理器的重視,那麼使用與上述描述相同的語義可訪問 MQMDE 欄位。在本例中,從屬性角度來看,MQMDE 欄位從邏輯上被看作是 MQMD 的一部分。
4. 流向上一版本的訊息
當訊息流向 V7 版本之前的佇列管理器時,除了那些在訊息描述符中的屬性之外,訊息屬性都被看作是訊息資料並計入訊息長度中:
因此,對於流向 V7 之前的系統的通道,其 MaxMsgLength 屬性的值應提高,以補償每個訊息本來可能傳送更多資料的損失。
當訊息通過 WebSphere MQ 從一個程式流向另一程式時,為將其傳送到目的地,可能需要對訊息進行更改。本節探討在訊息傳輸中 WebSphere MQ 更改訊息的不同方式。這些更改由佇列管理器、訊息通道代理程式或其他 WebSphere MQ 基礎設施自動完成,且對應用程式透明。
我們知道,WebSphere MQ 可劃分為包含控制資訊的訊息頭和包含負載資料的訊息資料。負載資料一般不由佇列管理器更改,除非需要對其進行資料轉換。多數情況下,對訊息的更改是對控制資訊(訊息頭)進行的,比如附加頭的新增或對已有頭的修改。
在某些情況下,WebSphere MQ 通過對訊息資料附加更多頭字首並更改訊息描述符的 Format 欄位來向訊息新增額外控制資訊。WebSphere MQ 在以下四種情況下向訊息新增頭資訊:
情況 1. 當訊息位於遠端佇列時
當訊息位於遠端佇列時,WebSphere MQ 在將訊息置於傳輸佇列之前向其新增傳輸頭結構(MQXQH)。傳輸頭包括目標佇列名稱(RemoteQName)和佇列管理器名稱(RemoteQMgrName),即定址資訊。該資訊用於傳送訊息到網路中正確的目的地。表 2 列出了 MQXQH 中的一些主要欄位:
欄位 | 描述 |
---|---|
RemoteQName | 目標佇列的名稱 |
RemoteQMgrName | 目標佇列管理器的名稱 |
MsgDesc | 原始訊息描述符(嵌入式) |
除了定址資訊之外,嵌入式訊息描述符(MsgDesc)也作為訊息資料的一部分儲存在 MQXQH 結構內。此描述符與由輸入端應用程式置入的原始訊息描述符一同產生。另一種訊息描述符在將訊息置於傳輸佇列時由佇列管理器生成,它與訊息資料獨立儲存,稱作獨立的訊息描述符。因此,傳輸佇列上的一條訊息有兩個訊息描述符,如圖 7 所示:
嵌入式訊息描述符始終是 V1 MQMD 結構。如果應用程式置入的訊息對於 MQMD 中的一個或多個 V2 欄位有非預設值,則 MQMDE 結構緊跟在 MQXQH 後面,並位於應用程式訊息資料的前面,如上面圖 7 所示。
當訊息到達其目標佇列時,傳輸頭與獨立的訊息描述符相分離,於是嵌入式訊息描述符便成為訊息特有的訊息描述符 — 它不再是訊息資料的一部分。
情況 2. 當佇列管理器不能傳遞訊息時
在這種情況下,WebSphere MQ 新增死信頭結構(MQDLH)到訊息中,並將其放到死信(未傳遞訊息)佇列上。另外,為表明訊息包含 MQDLH 結構,訊息描述符(MQMD)的 Format 欄位被更改。該結構包含目標佇列的名稱和將訊息放在死信佇列上的原因。表 3 列出了 MQDLH 中的主要欄位:
欄位 | 描述 |
---|---|
Reason | 到達死信佇列的原因訊息 |
DestQName | 原始目標佇列的名稱 |
DestQMgrName | 原始佇列管理器的名稱 |
Format | MQDLH 後面的資料的格式名稱 |
PutApplType | 放置訊息到死信佇列的應用程式型別 |
PutApplName | 放置訊息到死信佇列的應用程式名稱 |
訊息可由佇列管理器、訊息通道、訊息通道代理程式(MCA)和應用程式放到死信佇列上。死信佇列上的所有訊息必須以 MQDLH 為字首,如果由於加入 MQDLH 頭而使訊息相對於佇列太長,可將訊息截短。
從死信佇列獲取訊息的應用程式必須確保訊息以 MQDLH 結構開頭。應用程式可通過檢查訊息描述符中的 Format 欄位確定其是否含有 MQDLH 結構。如果欄位含有 MQFMT_DEAD_LETTER_HEADER 值,則訊息資料以 MQDLH 結構開頭。
情況 3. 當傳送一條訊息到多個目標佇列時
在這種情況下,WebSphere MQ 新增分散式頭結構(MQDH)到訊息中,並將其放在相關的傳輸佇列中。因此,應用程式訊息資料以 MQXQH 和 MQDH 結構為字首。當訊息是儲存在傳輸佇列中的分佈列表訊息時,MQDH 會描述該訊息中的附加資料。分佈列表訊息是傳送到多個目標佇列的訊息。附加資料包括 MQDH 結構和緊接其後的 MQOR 記錄陣列和 MQPMR 記錄資料。表 4 列出了 MQDH 中的主要欄位:
欄位 | 描述 |
---|---|
StrucLength | MQDH 結構與其後的記錄的總長度 |
Format | MQPMR 記錄陣列之後的資料的格式名稱 |
PutMsgRecFields | 表明有哪些 MQPMR 欄位存在的標誌 |
RecsPresent | 當前物件記錄數 |
ObjectRecOffset | 第一個物件記錄與 MQDH 初始位置的偏移量 |
PutMsgRecOffset | 第一個置入訊息(put-message)記錄與 MQDH 初始位置的偏移量 |
傳輸佇列上分佈列表訊息的訊息資料排列順序如下:
- MQXQH 結構
- MQDH 結構與 MQOR 和 MQPMR 記錄陣列
- 應用程式訊息資料(負載資料)
傳輸佇列上分佈列表訊息的結構如圖 8 所示:
StrucLength 是從 MQDH 結構初始位置到 MQOR 和 MQPMR 記錄陣列後面的訊息資料的初始位置之間的位元組數。 ObjectRecOffset 為包含目標佇列名稱的 MQOR 物件記錄陣列中第一個記錄提供位元組偏移量。 PutMsgRecOffset 為包含訊息屬性的 MQPMR 置入訊息記錄陣列的第一個記錄提供位元組偏移量。
情況 4. 當訊息是組中的一個片段或一條訊息時
在這種情況下,WebSphere MQ 可能會新增訊息描述符擴充套件(MQMDE)結構。
訊息分段對於應用程式可以是透明的。如果允許,佇列管理器會在訊息太大以至於佇列不能容納時將訊息分段。如果應用程式使用的是 V1 MQMD,佇列管理器會自動新增 MQMDE 結構到訊息資料中。如上所述,MQMDE 結構包含那些存在於 V2 MQMD 中而 V1 MQMD 沒有的 MQMD 欄位,因為 V1 MQMD 中儲存分段和分組資訊。
除了新增額外頭到資訊中之外,WebSphere MQ 還可能在訊息在傳送和接收訊息的應用程式之間傳輸時更改訊息中已有頭的特定欄位:
1. 所有字首頭中的 Format 欄位
如上所述,WebSphere MQ 在特定環境下新增頭資訊到訊息中。一旦新增了額外的頭,其字首頭結構的 Format 欄位也被 WebSphere MQ 更新,以表明新訊息頭的型別。例如,當 WebSphere MQ 在訊息的訊息描述符後面新增傳輸頭時,MQMD 的 Format 欄位被更改為 MQFMT_XMIT_Q_HEADER。
2. 傳輸頭中包含定址資訊的欄位
在雙向通訊期間(在 WebSphere MQ 中,雙向通訊是指從一個佇列管理器傳送訊息到另一個佇列管理器),當佇列管理器傳送訊息時,如果使用了佇列管理器別名,它可能會更改與訊息一同傳輸的傳輸頭的定址資訊(RemoteQName,RemoteQMgrName)。
來自相鄰系統的訊息包含目標佇列管理器和傳輸頭中佇列的物理名稱(對名稱解析後得到的名稱)。如果佇列管理器別名定義與傳輸頭中引用的同一佇列管理器名均存在,那麼用於傳遞訊息的本地佇列管理器會用來自別名定義的 RQMNAME 覆蓋 RemoteQMgrName 欄位。
3. 訊息描述符中的 ReplyToQ, ReplyToQMgr
事實上,對這兩個欄位的更改是在應用程式將訊息放到佇列之前進行的。如果應用程式將訊息放到為應答訊息而提供 reply-to 佇列名稱(ReplyToQ)的佇列中,同時佇列管理器名稱(ReplyToMgr)為空,本地佇列管理器會通過用與 reply-to 佇列相同的名稱(reply-to 別名)檢查遠端佇列定義來響應空的佇列管理器名稱:
- 如果找不到任何結果,佇列管理器會在保持 ReplyToQ 不變的情況下在訊息描述符的 ReplyToQMgr 欄位中置入自己的名稱。
- 如果定義存在,佇列管理器從定義中抽取佇列名稱和佇列管理器名稱,然後將其放入訊息描述符的 reply-to 欄位中 — 即替換 ReplyToQ 和 ReplyToQMgr 的值。
4. 訊息描述符中的 Context 欄位
訊息上下文資訊儲存在訊息描述符的 context 欄位中。有兩種型別的訊息上下文:身份上下文(identity context)和傳送者上下文(origin context)。V7 中為訊息屬性新增了一種新的上下文資訊:使用者上下文(user context)。圖 5 列出了訊息描述符中的 context 欄位:
上下文型別 | 欄位和描述 |
---|---|
身份上下文 |
UserIdentifier:發起訊息的應用程式的使用者識別符號。 AccountingToken:帳戶標誌 ApplIdentityData:與身份相關的應用程式資料 |
傳送者上下文 |
PutApplType:放置訊息的應用程式的型別 PutApplName:放置訊息的應用程式的名稱。 PutDate:放置訊息的日期。 PutTime:放置訊息的時間。 ApplOriginData:與發起訊息相關的應用程式資料。 |
使用者上下文 |
被應用程式識別為使用者上下文的任何屬性。 |
身份和傳送者上下文的多數字段通常由佇列管理器提供。當然,擁有合適授權的應用程式可提供其自己的上下文:
- 身份上下文資訊標識首次將訊息放入佇列的應用程式的使用者。佇列管理器根據應用程式的執行環境填充 UserIdentifier 和 AccountingToken 欄位。
- 傳送者上下文資訊描述將訊息放入當前儲存訊息的佇列中的應用程式。以下欄位通常由佇列管理器指定:PutApplType、PutApplName、PutDate 和 PutTime。
- 使用者上下文不由佇列管理器自動設定。
5. 訊息描述符(V2)中的 Segmenting/Grouping 欄位
如果允許,佇列管理器會將由於太長而難以傳送的訊息分成大量更小的訊息。同時,佇列管理器在訊息描述符(如果是 V2 的話)中設定以下分段/分組欄位:GroupId、MsgSeqNumber、Offset、MsgFlags 和 OriginalLength。如上所述,如果訊息描述符是 V1,MQMDE 結構由佇列管理器新增。
如果傳送和接收應用程式之間的資料格式不同,就需要進行資料轉換。因為 WebSphere MQ 必須能夠了解訊息描述符(MQMD)的內容,不管建立它的平臺是什麼,MQMD 均由系統自動轉換。不過,對於訊息的應用程式資料部分,情況有點複雜:
- 使用由 WebSphere MQ 定義的格式的資料(內建格式) — 表 1 所列格式是所有內建格式的子集。這些格式中的訊息資料可由佇列管理器自動從一個編碼字符集轉換為另一個編碼字符集,前提是兩種字符集都與單個語言或一組類似語言相關。
- 使用使用者定義格式的資料 — 佇列管理器不能轉換使用者定義格式的資料。應用程式必須為這樣的格式提供資料轉換出口。
綜上所述,只有內建格式的訊息資料在需要資料轉換時才能由 WebSphere MQ 自動進行轉換。
本文描述了 WebSphere MQ 訊息格式和 WebSphere MQ 在訊息排隊期間進行的訊息更改。它顯示了不同版本的 WebSphere MQ 訊息格式在概念上的不同之處和組成上的相似之處,使用了一種包含兩個組成部分的頭-主體結構:
- 訊息描述符和應用程式資料(V6 及之前的所有版本)
- 訊息屬性和應用程式資料(V7 版本)
一條訊息在從一個應用程式傳送到另一應用程式時,WebSphere MQ 可通過三種方式對其進行更改:
- 新增額外的頭(包含更多控制資訊)。
- 更改訊息中已有頭的欄位。
- 執行資料轉換。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14789789/viewspace-630789/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 新增的WebSphere MQ訊息傳遞提供程式簡介WebMQ
- 在 SIBus 和 WebSphere MQ 之間進行簡單的訊息交換WebMQ
- vue---元件間傳遞訊息(父子傳遞訊息,兄弟傳遞訊息)Vue元件
- Android訊息傳遞之元件間傳遞訊息Android元件
- 在多叢集 WebSphere Process Server 單元中配置高效的訊息傳遞WebServer
- 【RocketMQ】MQ訊息傳送MQ
- 使用 Java API 處理 WebSphere MQ 大訊息JavaAPIWebMQ
- C#視窗間傳遞訊息C#
- [原]關於在Python和C#之間訊息傳遞的問題PythonC#
- 任務:訊息: 不可或缺的十種 WebSphere MQ SupportPacWebMQ
- MQ 如何防止訊息重複入隊MQ
- Rocket MQ 的三種訊息傳送(同步、非同步、單向)和訊息訂閱MQ非同步
- Flutter中訊息傳遞Flutter
- Chrome Extension 訊息傳遞Chrome
- MQ和WEBSPHERE整合 (轉)MQWeb
- 整合MQ和WEBSPHERE (轉)MQWeb
- 跨共識訊息格式XCM有幾種傳遞機制?
- flutter 訊息傳遞機制Flutter
- Handler訊息傳遞機制
- Apache Kafka訊息傳遞策略ApacheKafka
- Rocket MQ傳送訊息的三種方式初析MQ
- android 主執行緒和子執行緒之間的訊息傳遞Android執行緒
- Android訊息傳遞之Handler訊息機制Android
- 訊息佇列(MQ)佇列MQ
- 【轉】使用oracle pipe傳遞訊息Oracle
- 用社交網路連線 WebSphere MQ:列隊管理器和 MQ 應用程式的 Twitter 通知WebMQ
- RabbitMQ 和訊息傳遞常用一些術語MQ
- 在WebSphere MQ 網路上規劃 SSLWebMQ
- 在多叢集WPC單元中配置高效的訊息傳遞
- 學習在.NET Core中使用RabbitMQ進行訊息傳遞之持久化(二MQ持久化
- MQ訊息佇列_RabbitMQMQ佇列
- 理解訊息佇列(MQ)佇列MQ
- 在ASP.NET Core 中使用 .NET Aspire 訊息傳遞元件ASP.NET元件
- QNX學習 -- API之訊息傳遞API
- 使用C#在應用程式間傳送訊息C#
- WebSphere MQ傳輸環境搭建和測試WebMQ
- InheritableThreadLocal 線上程池中進行父子執行緒間訊息傳遞出現訊息丟失的解析thread執行緒
- Apache Kafka和Spring Boot的容錯和可靠訊息傳遞 – Arnold GalovicsApacheKafkaSpring Boot