脈絡:Content Enricher 告訴我們怎麼處理「訊息缺少必要資料項」;Content Filter 讓我們移除不感興趣的資料項。但有時候我們只想「暫時」移除欄位

例如一則訊息可能含有一組稍後在訊息流中會用到、但中間各處理步驟都用不到的資料。

我們不想讓這些資訊被一路揹過每個處理步驟——那會造成效能劣化,也讓除錯更困難(因為要一直帶著這麼多額外資料)。

訊息不適合搬大量資料#

用訊息搬運大量資料可能沒效率:有些訊息系統甚至對訊息大小設下硬性上限;其他系統用 XML 表示資料,這可能讓訊息大小膨脹一個數量級以上

所以,訊息傳遞雖然提供了最可靠、回應性最好的資訊傳輸方式,卻未必是最有效率的

單純的 Content Filter 能減少資料量,但不保證我們之後能還原訊息內容。因此我們得用一種日後能取回的方式,把完整的訊息資訊存起來

而因為每則訊息都要存資料,我們就需要一把鑰匙來取回對應的資料。

我們可以用訊息 ID 當鑰匙,但那樣後續元件就無法把鑰匙傳下去——因為訊息 ID 每則訊息都不同

解法#

模式包含五個步驟:

  1. 一則帶有資料的訊息抵達
  2. 「寄放行李」元件為這份資訊產生一把唯一的鑰匙——它稍後就是那張 Claim Check
  3. 該元件把資料從訊息中取出,存進持久化儲存(檔案或資料庫),並把資料與鑰匙關聯起來
  4. 它把已持久化的資料從訊息中移除,並加上 Claim Check
  5. 另一個元件可以用 Content Enricher 依 Claim Check 取回資料

這就像機場的行李託運:不想自己扛行李,就到航空公司櫃檯託運;作為交換,你的機票上會貼一張帶有參考編號的貼紙,唯一識別你託運的每一件行李。到了目的地就能把行李領回來。

圖 8-13:Claim Check 解法示意

這樣真的有賺到嗎?#

原始訊息中的資料終究還是得「搬」到最終目的地,那我們得到了什麼?

訊息可能經歷多個根本不需要那大量資料的路由步驟;而使用訊息系統時,資料在每一步都得被封送、解封送,可能還要加解密——這類操作非常吃 CPU,而如果只有最終目的地需要那份資料,這些工作完全是白費的

Claim Check 在「訊息經過多個元件後又回到寄件端」的情境中也很好用:此時**「寄放行李」元件與 Content Enricher 位於同一個元件內,資料根本不必跨網路傳輸**。

圖 8-14:資料可以在本地儲存與取回

怎麼選鑰匙#

  • 訊息內文中既有的業務鍵(例如 Customer ID)
  • 訊息 ID
  • 自行產生一個唯一 ID

沿用業務鍵#

重用既有業務鍵看起來最容易:要寄放某些客戶細節,之後就用客戶 ID 取回。

但把鑰匙傳給其他元件時,我們得決定是否要讓那些元件知道「這把鑰匙是客戶 ID」,而不只是一把抽象鑰匙。

把鑰匙表示成抽象鑰匙的好處是:所有鑰匙都能一視同仁地處理,也能做出一套「依抽象鑰匙從資料儲存取資料」的通用機制。

別用訊息 ID#

用訊息 ID 當鑰匙看似方便,但通常不是好主意——這等於替單一資料元素附加了雙重語意,會造成衝突。

例如若我們要把這個參考傳給另一則訊息,新訊息理應被指派一個新的唯一 ID,但那樣就不能再用新 ID 從資料儲存取資料了

只有在「希望資料僅在單一訊息的範圍內可存取」時,用訊息 ID 才有意義。一般而言,最好另外指派一個元素來放鑰匙,避免這種不良的『元素重用』。

資料何時清掉#

資料可能只是暫存,那該怎麼移除?三個選項:

  • 讀取即刪除——修改資料取回的語意,讀了就刪。這樣資料只能取一次,某些情況下基於安全理由這反而是想要的;但它不允許多個元件存取同一份資料
  • 加上到期日 + 垃圾回收——定義一個定期移除所有超齡資料的流程。
  • 完全不移除——例如我們用一個業務系統(如會計系統)當資料儲存,而該系統本來就必須保留所有資料。

資料儲存的實作#

資料儲存可以有多種形式:資料庫是顯而易見的選擇,但一組 XML 檔案或記憶體內的訊息儲存同樣可以勝任,有時我們甚至用某個應用程式當資料儲存。

關鍵是:資料儲存必須能被整合方案中其他部分的元件觸及,那些部分才能重建原始訊息。

用 Claim Check 隱藏資訊#

Claim Check 原本的用意是避免搬運大量資料,但它也能服務其他目的

我們常想在把訊息送給外部單位之前移除敏感資料,讓外部單位只在「需要知道」的基礎上取得資料。例如把員工資料送給外部單位時,我們可能寧可用某個魔術唯一 ID 來指涉員工,並剔除社會安全號碼這類欄位

外部單位處理完之後,我們再把資料儲存中的資料與對方回傳的訊息合併,重建完整訊息

我們甚至可以為這些訊息產生特殊的唯一鑰匙,藉由「對方持有的鑰匙」來限制它能採取的動作。這能防止外部單位惡意地把訊息餵進我們的系統——帶有無效(或已過期、已使用)鑰匙的訊息,會在 Content Enricher 嘗試取資料時被擋下來。

用 Process Manager 當 Claim Check#

若我們與不只一個外部單位互動,Process Manager 可以充當 Claim Check

Process Manager 在訊息抵達時建立流程實例(有時稱 task 或 job),並允許把額外資料與每個實例關聯起來——實際上,流程引擎就成了儲存訊息資料的資料儲存

於是 Process Manager 送給外部單位的訊息只需含有與該單位相關的資料,不必攜帶原始訊息的全部資訊(那些留在流程的資料儲存中);當它收到外部單位的回應訊息時,再把新資料與流程實例所存的資料重新合併

圖 8-15:以 Process Manager 充當 Claim Check