脈絡:多數訊息系統把訊息資料分成表頭與內文。表頭欄位供訊息基礎設施管理訊息流之用。
但參與整合方案的多數端點系統根本不知道這些額外資料元素的存在,有些系統甚至會把這些欄位視為錯誤,因為它們不符合該應用程式使用的訊息格式。
另一方面,在應用程式之間路由訊息的訊息元件可能需要這些表頭欄位,缺了正確的表頭就把訊息視為無效。
兩個典型場景#
安全機制#
假設訊息系統採用專有的安全方案:有效訊息必須含有安全憑證,其他訊息元件才會接受處理——這能防止未授權使用者把訊息餵進系統。此外訊息內容可能被加密以防未授權者竊聽(在發布訂閱機制中這特別重要)。
但被整合的既有應用程式多半不知道「使用者身分」或「訊息加密」這些概念。因此「原始」訊息必須被轉譯成符合訊息系統規則的訊息。
跨越多套訊息基礎設施#
有些大型企業使用不只一套訊息基礎設施,訊息可能得透過 Messaging Bridge 跨系統路由,而每套系統對內文與表頭格式的要求可能都不同。
這個場景可以從既有的 TCP/IP 網路協定學到東西:許多情況下,連到另一個系統只能用特定協定(例如 telnet 或 SSH)。要用另一種協定(例如 FTP)通訊,就得把那個協定的格式封裝進符合所支援協定的封包,到了另一端再把酬載取出——這個過程稱為 tunneling(隧道)。
封裝造成的可見性問題#
一種訊息格式被封裝進另一種時,系統可能失去存取酬載內部資訊的能力。多數訊息系統只允許元件(例如 Content-Based Router)存取已定義的訊息表頭中的資料欄位;若一則訊息被塞進另一則訊息的資料欄位裡,元件就無法用原始訊息的欄位來執行路由或轉換。
因此有些資料欄位必須從原始訊息「提升」到新訊息格式的表頭中。
解法#
包裝與拆封的過程有五個步驟:
- 訊息來源以原始格式發布訊息——這種格式由應用程式的本質決定,不符合訊息基礎設施的要求
- Wrapper 取得原始訊息,轉換成符合訊息系統的格式——可能包括加上表頭欄位、加密、加上安全憑證等
- 訊息系統處理這些合規訊息
- 結果訊息被送到 Unwrapper,由它逆轉 wrapper 所做的一切修改——移除表頭欄位、解密、驗證安全憑證
- 訊息接收者收到一則「明文」訊息
信封通常同時包住表頭與內文:可以把表頭想成寫在信封外面的資訊(訊息系統用它來路由與追蹤訊息),信封裡的東西就是酬載——在抵達目的地之前,訊息基礎設施(在一定限度內)並不太在意它。

圖 8-2:Envelope Wrapper 解法示意
包裝器會加東西#
包裝器對原始訊息添加資訊是常態。
例如內部備忘錄要經郵政系統寄出之前,得先查出郵遞區號。就這一點而言,包裝器帶有 Content Enricher 的某些性質——但它增益的不是實際的資訊內容,而是加上路由、追蹤與處理訊息所必需的資訊。
這些資訊可以有三種來源:
- 當場產生——例如建立唯一的訊息 ID 或加上時間戳
- 從基礎設施取得——例如取回安全脈絡
- 從原始訊息內文中拆分到表頭——例如原始訊息裡的某個鍵欄位
最後這種作法有時稱為提升(promotion)——某個欄位從「藏在內文裡」被提升到「顯眼地出現在表頭中」。
包裝器可以串接#
包裝器與拆封器經常被串接起來,運用分層協定模型。結果是:一則訊息的酬載裡含有一個新的信封,而那個信封裡又包著一組表頭與酬載——形成階層式的信封結構。

圖 8-3:層層串接的包裝器形成階層式信封結構
範例:SOAP、TCP/IP 與郵政系統
SOAP 訊息格式#
基本的 SOAP 訊息格式相對簡單:一個信封包住訊息表頭與訊息內文。以下例子展示內文如何裝著另一個信封,而那個信封又含有自己的表頭與內文。
組合後的訊息被送給一個中介者,由它拆開外層訊息並轉送內層訊息。
<env:Envelope xmlns:env="http://www.w3.org/2001/06/soap-envelope">
<env:Header env:actor="http://example.org/xmlsec/Bob">
<n:forward xmlns:n="http://example.org/xmlsec/forwarding">
<n:window>120</n:window>
</n:forward>
</env:Header>
<env:Body>
<env:Envelope xmlns:env="http://www.w3.org/2001/06/soap-envelope">
<env:Header env:actor="http://example.org/xmlsec/Alice"/>
<env:Body>
<secret xmlns="http://example.org/xmlsec/message">
The black squirrel rises at dawn</secret>
</env:Body>
</env:Envelope>
</env:Body>
</env:Envelope>TCP/IP#
我們常把「TCP/IP」講成一個詞,它其實包含兩個協定:IP 提供基本的定址與路由服務,TCP 則是疊在 IP 之上、可靠且連線導向的協定。依 OSI 分層模型,TCP 是傳輸層協定、IP 是網路層協定,而 TCP/IP 資料通常透過實作鏈路層的乙太網路傳輸。
因此應用資料先被包進 TCP 信封,再包進 IP 信封,再包進乙太網路信封。
由於網路是串流導向的,一個信封可以同時包含表頭與尾標(trailer)。

圖 8-4:應用資料被層層信封包裹後在網路上傳輸
郵政系統#
Envelope Wrapper 可以類比郵政系統:
- 員工寫了一份給同事的內部備忘錄——任何一張紙都是可接受的格式
- 要送達就得把它「包」進一個含有收件人姓名與部門代碼的公司內部信封
- 若收件人在另一個據點,這則「公司內部訊息」會被塞進一個大信封,經郵政服務寄出——為了符合郵局要求,新信封需要郵遞區號與郵資
- 郵局可能決定走空運,於是把寄往特定區域的所有信封塞進一個郵袋,貼上以三字母機場代碼標示目的地的條碼
- 郵袋抵達目的地機場後,包裝順序被逐層反轉,直到同事收到原始的備忘錄
這個例子也說明了「隧道」一詞:郵件可以被「隧道」穿過空運,就像 UDP multicast 封包可以被隧道穿過 TCP/IP 連線以抵達不同的 WAN 網段。
郵政系統的例子也展示了用 Pipes and Filters 串接包裝器與拆封器的常見實務:訊息可能被多個步驟包裝,也必須由一組對稱的拆封步驟拆開。
保持各步驟彼此獨立,讓訊息基礎設施有彈性增減包裝與拆封步驟——例如因為所有流量都改走 VPN 而不再需要加密時,就能直接把那一步拿掉。