级别: 中级 Shravan K Kudikala, 高级软件工程师,IBM India Software Labs, IBM, Software Group Tushita Jain, 系统软件工程师,IBM India Software Labs, IBM
2009 年 5 月 04 日 WebSphere Message Broker 提供了一种非干扰性的方法来监视正在组消息流中传递的消息,以便您能够安全地监视、跟踪和审核消息而不影响消息流。该技术使您能够在连接基于 C 的代码的地方使用回调出口点,然后在消息处理过程中提取有关消息及其事务状态的数据。
引言
IBM® WebSphere® Message Broker(以下称为 Message Broker)提供了可动态配置的非干扰性机制来跟踪动态消息。它允许您在消息通过消息流传递时调用用户出口中的自定义代码,从而在消息生命周期中的某个点跟踪消息。您的自定义代码可以调用 Message Broker 实用工具函数来获得有关消息内容及其在消息流中的当前执行点的信息。本文提供了一个演示此技术的简单示例。
描述
用户出口是用户或供应商提供的可由 Message Broker 调用的函数。这些调用可由以下事件触发:
- 当输入节点(内置/插件)读取某个消息时
- 当消息传播到某个节点时
- 当节点的处理完成时
- 当某个事务(COMMIT 或 ROLLBACK)发生或在工作单元 (UOW) 结束时
对于这其中每个事件,Message Broker 允许您使用用户出口访问特定的信息。除了 Environment 和 Local 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. 显示用户出口位置的示例
在上面的关系图中,MQInput 节点用作接收消息的源。它连接到计算节点,后者又连接到 MQOutputNode。用户出口并不仅限于内置节点,它们适用于所有用户定义的插件节点。在点 (1) 处,紧跟在节点传播消息之前调用了用户出口。随后在点 (2) 处,在消息传播到该节点进行处理时调用了用户出口。接下来在点 (3) 处,在节点处理完成后调用了用户出口。在点 (4) 处,在事务结束时调用了用户出口。用户出口不是事务的一部分,并在事务完成以后被调用。请注意,即使没有任何事务处理完成,也会调用用户出口。注意:在点 (1) 处,在内置输入节点上调用用户出口的方式与在用户定义的输入节点上稍有不同。对于所有的内置输入节点,将在从输入源读取数据以后立即调用用户出口;而对于用户定义的插件输入节点,则紧跟在从输入节点传播消息之前调用用户出口。
性能
如果没有任何用户出口是活动的,则此功能对性能没有影响。如果注册并激活了用户出口,则性能会受到影响,具体取决于那些出口中的用户代码的性能。
安全性
Message Broker 系统上的用户出口的部署需要 mqbrkrs 权限来设置 Message Broker 属性 userExitPath 和 activeUserExits。用户必须在为用户出口路径配置的目录上使用主机系统文件访问控制,以确保库不容易受到攻击。
开发用户出口
在 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 上为分号)分隔的目录列表。可以在 mqsicreatebroker 或 mqsichangebroker 上通过 –x 标志设置此属性。希望将用户出口加载到某些代理中的用户应该设置此属性。
- 环境变量
MQSI_USER_EXIT_PATH(对于 64 位执行组为 MQSI_USER_EXIT_PATH64)
- 这是一个冒号(在 Windows 上为分号)分隔的目录列表。当需要将用户出口加载到某个环境的每个代理中时,通常要设置此环境变量。
如果同时对这两者进行了设置,则环境变量优先。系统将按照目录在该环境变量中的出现顺序搜索其中的所有目录。然后将按照目录在 Message Broker 属性中的出现顺序搜索其中的所有目录。
2. 将用户出口加载到代理的进程中
在代理上安装用户出口库以后,必须对其进行加载。您可以采用以下任一种方法:
- 停止然后启动 Message Broker。
- 使用命令
mqsireload,此命令将导致执行组进程重新启动。
3. 激活用户出口
用户出口可以是活动或非活动的。其状态缺省为非活动的。可以在每个代理的基础上将一组用户出口的缺省状态更改为活动的。下面是用于更改缺省用户出口状态的步骤:
- 停止代理
- 使用 mqsichangebroker 命令设置代理的 activeUserExits 属性。
- 启动代理并检查系统日志,以确保所有执行组都已启动,没有任何错误。如果指定了任何无效的用户出口名称(也就是说,该用户出口不是由执行组加载的任何库提供的),则会向系统日志写入一条 BIP2314 消息,并且执行组中的所有流都将无法启动。
覆盖缺省状态
使用 mqsichangeflowuserexits 命令,按照先消息流然后执行组的顺序,可以在每个执行组或每个消息流的基础上激活/禁用用户出口。
当为给定的流激活了多个出口时,则会按照已定义的顺序调用它们。有关此顺序的详细信息,请参阅有关 mqsichangeflowuserexits 命令的参考资料。
示例开发和测试
我们已通过一个示例举例说明了用户出口的概念。该示例包括以下文件:
-
brokerExits.h
- 包含 API 函数的原型
-
brokerExits.c
- 包含用户出口 API 模块的实现
-
build.bat
- 用于编译
brokerExits.c 的指令集(针对 Windows)
-
build.sh
- 用于编译
brokerExits.c 的指令集(针对 AIX)
用于关联和调用上述流的用户出口函数的最简单步骤序列如下:
- 将
Example.zip 中的所有文件提取到某个文件夹。
- 修改 build.bat 以反映 Visual Studio 和 Message Broker 安装的适当路径。
- 从提取文件的目录中执行 build.bat。这将在当前目录中创建 brokerExits.lel。
-
mqsichangebroker <broker> -x <User Exit Path> -e mySampleUserExit.
这将向代理注册用户出口 mySampleUserExit,并激活特定的用户出口。
- 在 Services 面板中更改代理的服务属性,以使其能够与桌面交互。这样做是为了在控制台上看到与 DataFlowEngine 进程关联的消息。
-
mqsistart <broker>
- 当将消息放在与 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 <BipCci.h>
#include <BipCni.h>
|
这些文件包含 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"
- 将 <WMB_install>\include\plugin 目录添加到 include 搜索路径
-
/I"."
- 将当前目录添加到 include 搜索路径
-
brokerExits.c
- 要编译的程序的名称
-
-link
- 指定链接器选项和库
-
/DLL "C:\PROGRA~1\IBM\MQSI\65F51~1.0FP\lib\imbdfplg.lib"
- 将 <WMB_install> \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
- 将 <WMB_install> /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
- <WMB_install> 库文件的路径
-
-I imbdflpg
- 要使用的插件库文件的名称
-
chmod a+r brokerExits.lel
- 确保所有用户都拥有该文件的读取权限
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| Code sample | Example.zip | 11 KB | HTTP |
|---|
参考资料 学习
获得产品和技术
讨论
作者简介  | |  |
Shravan K Kudikala 是在印度德拉巴 IBM India Software Lab 工作的一名高级软件工程师。他是 WebSphere Message Broker Level 3 Support Team 的成员。他曾发表过大量其他方面的文章,涉及 IA97、IA0X 和 IA9W 支持实践。 |
 | |  | Tushita Jain 是位于印度班加罗尔的 IBM India Software Lab 的一名系统软件工程师。她是 WebSphere Message Broker Level 3 Support Team 的成员。 |
对本文的评价
|