WebSphere Message Broker 中使用者出口跟蹤訊息

CloudSpace發表於2009-05-06

引言

IBM® WebSphere® Message Broker(以下稱為 Message Broker)提供了可動態配置的非干擾性機制來跟蹤動態訊息。它允許您在訊息通過訊息流傳遞時呼叫使用者出口中的自定義程式碼,從而在訊息生命週期中的某個點跟蹤訊息。您的自定義程式碼可以呼叫 Message Broker 實用工具函式來獲得有關訊息內容及其在訊息流中的當前執行點的資訊。本文提供了一個演示此技術的簡單示例。

描述

使用者出口是使用者或供應商提供的可由 Message Broker 呼叫的函式。這些呼叫可由以下事件觸發:

  • 當輸入節點(內建/外掛)讀取某個訊息時
  • 當訊息傳播到某個節點時
  • 當節點的處理完成時
  • 當某個事務(COMMIT 或 ROLLBACK)發生或在工作單元 (UOW) 結束時

對於這其中每個事件,Message Broker 允許您使用使用者出口訪問特定的資訊。除了 Environment 和 Local Environment 樹以外,所有的此類訪問都是隻讀的。下面是您在指定的事件發生時可以訪問的資訊:

  • 當輸入節點(內建/外掛)讀取某個訊息時:
    • 訊息樹位流
    • 輸入節點
    • Environment 樹
  • 當訊息傳播到某個節點時:
    • 訊息樹
    • LocalEnvironment 樹
    • 異常列表
    • Environment 樹
    • 原始碼
    • 目標節點
  • 當訊息的處理完成時:
    • 訊息樹
    • LocalEnvironment 樹
    • 異常列表
    • Environment 樹
    • 節點
    • 上游節點
    • 異常(如有的話)
  • 當某個事務發生或在 UOW 結束時:
    • 輸入節點
    • 異常(如有的話)
    • Environment 樹

此外,您可以靈活地呼叫 Message Broker 實用工具函式。在使用者程式碼中,您可以查詢有關訊息流中的當前執行點和訊息內容的資訊。您可以從自定義的使用者出口程式碼中使用使用者出口 API 查詢以下資訊:

  • 訊息流資訊:
    • 訊息流名稱
    • 代理名稱
    • 代理佇列管理器名稱
    • 執行組名稱
    • 訊息流 commit count 屬性
    • 訊息流 commit interval 屬性
    • 訊息流 coordinated transaction 屬性
  • 節點資訊:
    • 節點名稱
    • 節點型別
    • 終端名稱
    • 節點屬性

節點還可以執行以下任務:

  • 導航和讀取訊息組裝(Message、LocalEnvironment、ExceptionList)
  • 導航和讀取或寫入 Environment 樹

編寫使用者出口以後,對其進行編譯並使其對 Message Broker 可用。您可以動態地註冊它們,而無需重新部署配置。您無需更改 Message Broker 部署配置即可啟用和禁用它們,從而提供了動態啟用或禁用跟蹤、稽核和效能監視活動的靈活性。

可以註冊多個使用者出口,在這樣的情況下,將按照已定義的順序呼叫它們(有關該順序的詳細資訊,請參閱有關 mqsichangeflowuserexits 命令的參考資料)。使用者出口對訊息組裝做出的任何更改都將對後續的使用者出口可見。

因此,可以同時在事務級別和節點級別跟蹤訊息。在事務級別,您可以跟蹤訊息何時從輸入源中的佇列離開,以及訊息事務何時結束。在節點級別,您可以跟蹤訊息從一個節點到另一個節點的傳遞。

請考慮以下示例場景:


圖 1. 顯示使用者出口位置的示例
圖 1. 顯示使用者出口位置的示例

在上面的關係圖中,MQInput 節點用作接收訊息的源。它連線到計算節點,後者又連線到 MQOutputNode。使用者出口並不僅限於內建節點,它們適用於所有使用者定義的外掛節點。在點 (1) 處,緊跟在節點傳播訊息之前呼叫了使用者出口。隨後在點 (2) 處,在訊息傳播到該節點進行處理時呼叫了使用者出口。接下來在點 (3) 處,在節點處理完成後呼叫了使用者出口。在點 (4) 處,在事務結束時呼叫了使用者出口。使用者出口不是事務的一部分,並在事務完成以後被呼叫。請注意,即使沒有任何事務處理完成,也會呼叫使用者出口。注意:在點 (1) 處,在內建輸入節點上呼叫使用者出口的方式與在使用者定義的輸入節點上稍有不同。對於所有的內建輸入節點,將在從輸入源讀取資料以後立即呼叫使用者出口;而對於使用者定義的外掛輸入節點,則緊跟在從輸入節點傳播訊息之前呼叫使用者出口。

效能

如果沒有任何使用者出口是活動的,則此功能對效能沒有影響。如果註冊並啟用了使用者出口,則效能會受到影響,具體取決於那些出口中的使用者程式碼的效能。

安全性

Message Broker 系統上的使用者出口的部署需要 mqbrkrs 許可權來設定 Message Broker 屬性 userExitPathactiveUserExits。使用者必須在為使用者出口路徑配置的目錄上使用主機系統檔案訪問控制,以確保庫不容易受到攻擊。

開發使用者出口

在 Message Broker 中,使用者出口僅支援使用 C 或 C++ 程式語言。所有使用者出口(與平臺無關)將編譯並構建為帶 .lel 副檔名的動態連結庫或共享庫。Message Broker 只能通過此副檔名確定要載入的使用者出口模組。強烈建議不要使用使用者出口來通過 JNI 呼叫 Java 程式碼。

使用者出口 API 在使用者定義的 C 節點 API 中提供。API 包括可以在使用者出口中呼叫的實用工具函式,以及必須在使用者出口中實現的函式。

每個使用者出口應該實現 BipCpi.h 標頭檔案中定義的兩個必備函式。

void bipInitializeUserExits() 此函式在執行組載入使用者出口 .lel 可載入檔案時呼叫。在該函式的實現中,我們應該使用唯一的名稱註冊該使用者出口。對於每個使用者出口,可以通過指定以下值呼叫 cciRegisterUserExit() 來完成其註冊:
  • 名稱——註冊和控制使用者出口的活動狀態。
  • 使用者上下文儲存——可以傳入任何指標,並將傳遞給所有的後續回撥。
  • 指向要呼叫的回撥函式的指標(對於一種或多種事件型別)——為每種特定的事件註冊一個回撥函式,然後將在事件發生時呼叫這些函式。
void bipTerminateUserExits() 此函式在解除安裝使用者出口 (.lel) 時呼叫,通常是在執行組程式終止的時候。您可以指定相關邏輯以清理在使用者出口中分配的資源。請注意,在此方法中呼叫 API 實用工具函式不是很好的實踐。

部署使用者出口

使用者出口的狀態可在每個訊息流的基礎上設定為活動或非活動的。下面敘述用於部署和啟用使用者出口的步驟。

1. 在代理上安裝使用者出口程式碼

必須將包含使用者出口程式碼的庫安裝在可由 Message Broker 訪問的檔案系統上。用於執行 Message Broker 的使用者 ID 必須具有該檔案的讀取和執行許可權。Message Broker 在兩個地方查詢包含使用者出口的庫:

代理屬性 UserExitPath(對於 64 位執行組為 UserExitPath64)。這是一個冒號(在 Windows 上為分號)分隔的目錄列表。可以在 mqsicreatebrokermqsichangebroker 上通過 –x 標誌設定此屬性。希望將使用者出口載入到某些代理中的使用者應該設定此屬性。 環境變數 MQSI_USER_EXIT_PATH(對於 64 位執行組為 MQSI_USER_EXIT_PATH64 這是一個冒號(在 Windows 上為分號)分隔的目錄列表。當需要將使用者出口載入到某個環境的每個代理中時,通常要設定此環境變數。

如果同時對這兩者進行了設定,則環境變數優先。系統將按照目錄在該環境變數中的出現順序搜尋其中的所有目錄。然後將按照目錄在 Message Broker 屬性中的出現順序搜尋其中的所有目錄。

2. 將使用者出口載入到代理的程式中

在代理上安裝使用者出口庫以後,必須對其進行載入。您可以採用以下任一種方法:

  • 停止然後啟動 Message Broker。
  • 使用命令 mqsireload,此命令將導致執行組程式重新啟動。

3. 啟用使用者出口

使用者出口可以是活動或非活動的。其狀態預設為非活動的。可以在每個代理的基礎上將一組使用者出口的預設狀態更改為活動的。下面是用於更改預設使用者出口狀態的步驟:

  1. 停止代理
  2. 使用 mqsichangebroker 命令設定代理的 activeUserExits 屬性。
  3. 啟動代理並檢查系統日誌,以確保所有執行組都已啟動,沒有任何錯誤。如果指定了任何無效的使用者出口名稱(也就是說,該使用者出口不是由執行組載入的任何庫提供的),則會向系統日誌寫入一條 BIP2314 訊息,並且執行組中的所有流都將無法啟動。

覆蓋預設狀態

使用 mqsichangeflowuserexits 命令,按照先訊息流然後執行組的順序,可以在每個執行組或每個訊息流的基礎上啟用/禁用使用者出口。

當為給定的流啟用了多個出口時,則會按照已定義的順序呼叫它們。有關此順序的詳細資訊,請參閱有關 mqsichangeflowuserexits 命令的參考資料。

示例開發和測試

我們已通過一個示例舉例說明了使用者出口的概念。該示例包括以下檔案:

brokerExits.h 包含 API 函式的原型 brokerExits.c 包含使用者出口 API 模組的實現 build.bat 用於編譯 brokerExits.c 的指令集(針對 Windows) build.sh 用於編譯 brokerExits.c 的指令集(針對 AIX)

用於關聯和呼叫上述流的使用者出口函式的最簡單步驟序列如下:

  1. Example.zip 中的所有檔案提取到某個資料夾。
  2. 修改 build.bat 以反映 Visual Studio 和 Message Broker 安裝的適當路徑。
  3. 從提取檔案的目錄中執行 build.bat。這將在當前目錄中建立 brokerExits.lel。
  4. mqsichangebroker -x -e mySampleUserExit.
    這將向代理註冊使用者出口 mySampleUserExit,並啟用特定的使用者出口。
  5. 在 Services 皮膚中更改代理的服務屬性,以使其能夠與桌面互動。這樣做是為了在控制檯上看到與 DataFlowEngine 程式關聯的訊息。
  6. mqsistart
  7. 當將訊息放在與 MQInput 節點關聯的 MQ 佇列上時,將會在控制檯上顯示以下訊息,其中的代理名稱、佇列管理器名稱和 EG 名稱各不相同:
bipInitializeUserExits on Broker: V6BK, EG: default, QMgr: V6
myInputMessageCallback called on Broker: V6BK, EG: default, Node: MQInput 
myPropagatedMessageCallback called on Broker: V6BK, EG: default 
Message propagated from Node MQInput to Node Compute 
myPropagatedMessageCallback called on Broker: V6BK, EG: default 
Message propagated from Node Compute to Node MQOutput 
myNodeCompletionCallback() called on Broker: V6BK, EG: default 
myNodeCompletionCallback() called on Broker: V6BK, EG: default 
transactionEventCallback on Broker: V6BK, EG: default, Node: MQInput  

bipTerminateUserExits 在任何對應條件得到滿足時被呼叫,例如執行組關閉。

檔案描述

brokerExits.h

此檔案包含使用者出口模組及其呼叫的其他實用工具函式的原型。

/* Include the Message Broker Exits Header File */ 
#include  
#include  

這些檔案包含 C 外掛節點實現(包括使用者出口)中使用的原因程式碼、typedef 和實用工具函式的原型。

#ifdef _WIN32 
#define exportpref __declspec(dllexport) 
#else 
#define exportpref  
#endif  

__declspec(dllexport) 屬性確保可以在 Windows 上從 DLL 匯出函式。它在構建 DLL 庫時通過動態符號表匯出符號的定義。

brokerExits.c

此檔案包含使用者出口模組及其呼叫的其他實用工具函式的實現。編譯此檔案後,這些函式將在流生存期中發生各個事件時執行。

bipInitializeUserExits 在代理開始註冊一個或多個訊息跟蹤出口時被呼叫。cciGetBrokerInfo 獲取代理資訊並將其儲存在一個結構中。所有異常將通過 exceptionHandler 函式傳遞給代理以實現穩定性。它接受函式名稱、返回程式碼、檔名稱和行號以實現跟蹤目的。

myVft.iFpInputMessageCallback      = myInputMessageCallback; 
myVft.iFpTransactionEventCallback  = myTransactionEventCallback; 
myVft.iFpPropagatedMessageCallback = myPropagatedMessageCallback; 
myVft.iFpNodeCompletionCallback    = myNodeCompletionCallback;  

myVft 結構使用與事件對應的函式進行填充,例如,myInputMessageCallback 將在輸入節點讀取訊息時被呼叫。

最重要的是,將呼叫 cciRegisterUserExit(&rc,myUserExitName,0x00, &myVft); 來註冊使用者出口,並將在每個事件發生時呼叫函式。為了便於說明,我們將訊息顯示在控制檯上。也可以將它們重定向到日誌。

bipTerminateUserExits 將在執行組結束時被呼叫。

build.bat

此檔案包含使用 Visual Studio 的 C++ 編譯器編譯 C 程式並生成 .lel 檔案的語句。本質上,我們是將 .dll 檔案重新命名為 .lel,因為 Message Broker 只能通過此副檔名識別使用者出口模組。.lel 檔案由代理載入,使用者出口向代理進行註冊。

call "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\Vcvars32.bat" 

此命令呼叫設定編譯環境的 VC++ 批處理檔案。

cl /VERBOSE /GX /LD /MDd /Zi /I. /I
"C:\PROGRA~1\IBM\MQSI\65F51~1.0FP\include\plugin" /I"." 
brokerExits.c -link /DLL 
"C:\PROGRA~1\IBM\MQSI\65F51~1.0FP\lib\imbdfplg.lib" /OUT:brokerExits.lel 

此命令通過命令列呼叫 C++ 編譯器。使用的選項包括:

/VERBOSE 在控制檯上顯示步驟的描述 /GX 啟用 C++ EH(與 /Ehsc 相同) /LD 建立 .DLL /MDd 與 MSVCRTD.LIB 除錯庫連結 /Zi 啟用除錯資訊 /I"C:\PROGRA~1\IBM\MQSI\65F51~1.0FP\include\plugin" \include\plugin 目錄新增到 include 搜尋路徑 /I"." 將當前目錄新增到 include 搜尋路徑 brokerExits.c 要編譯的程式的名稱 -link 指定連結器選項和庫 /DLL "C:\PROGRA~1\IBM\MQSI\65F51~1.0FP\lib\imbdfplg.lib" \lib 目錄新增到 include 搜尋路徑 /OUT:brokerExits.lel 指定輸出檔名

build.sh

此檔案包含使用 IBM XL C 編譯器編譯 C 程式並生成 .lel 檔案的語句。本質上,我們是將 .so 檔案重新命名為 .lel,因為 Message Broker 只能通過此副檔名識別使用者出口模組。此 .lel 檔案由代理載入,使用者出口向代理進行註冊。

xlc_r -I . -I /opt/IBM/mqsi/6.0fp6/include/plugin -c brokerExits.c -o brokerExits.o

使用的選項包括:

-I . 將當前目錄新增到 include 搜尋路徑 -I /opt/IBM/mqsi/6.0fp6/include/plugin /include/plugin 目錄新增到 include 搜尋路徑 brokerExits.c 要編譯的程式的名稱 -o brokerExits.o 目標檔案的名稱
xlc_r -qmkshrobj -bM:SRE -bexpall -bnoentry -o brokerExits.lel brokerExits.o 
	-L /opt/IBM/mqsi/6.0fp6/lib -l imbdfplg

使用的選項包括:

-qmkshrobj 在生成的目標檔案的基礎上建立共享庫 -bM:SRE 建立共享庫 -bexpall 指定應該匯出的所有符號 -bnoentry 指定編譯器不應該查詢 main() -o brokerExits.lel 輸出庫檔案的名稱 -L /opt/IBM/mqsi/6.0fp6/lib 庫檔案的路徑 -I imbdflpg 要使用的外掛庫檔案的名稱 chmod a+r brokerExits.lel 確保所有使用者都擁有該檔案的讀取許可權

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14789789/viewspace-594331/,如需轉載,請註明出處,否則將追究法律責任。

相關文章