WebsphereMQ设计篇第十二章触发(Trigger)

更新时间:2023-11-07 05:37:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

第十二章 触发 (Trigger)

原理

WebSphere MQ中的本地队列或模型队列上可以设置消息触发器 (Trigger),到达的消息在优先级、数量和到达方式上如果满足预先设定的条件,则会有触发消息自动生成,放入指定的初始化队列,再由触发监控器 (Trigger Monitor) 将触发消息读出,并根据触发消息的内容启动相应的应用程序。一般说来,该程序应该首先从本地队列中将应用消息读出并进行应用处理。

触发消息 初始化队列 Trigger Monitor 触发消息 进程定义 启动 MQPUT/MQPUT1 应用消息 本地队列 应用消息 MQGET

其中,本地队列、初始化队列、进程定义是事先设置好的WebSphere MQ对象,触发监控器也是处于运行状态的,即在初始化队列上等待触发消息,一旦读到触发消息,则可以立即启动MQGET应用程序,所以MQGET应用程序是被触发启动的,通常情况下是触发监控器的子进程。所有这些都只是设定了“连锁反应”中的各个环节,而触动这个机关的是应用消息的到达。 WebSphere MQ 中与消息触发相关的参数如下: 对象 队列管理器 属性 TRIGINT 缺省值 999,999,999 可取值 0 - 999,999,999 说明 TriggerInterval,单位毫秒,只对FIRST方式有效 队列 (Local/Model) 队列 (Local/Model) TRIGGER NOTRIGGER ? ? TRIGGER NOTRIGGER FIRST EVERY DEPTH TriggerControl TRIGTYPE FIRST ? ? ? TriggerType 队列 (Local/Model) TRIGDPTH 1 TriggerDepth 队列 (Local/Model) 队列 (Local/Model) 进程 进程 进程 TRIGMPRI 0 TriggerMsgPriority TRIGDATA 空 最多64字节 触发数据字串,可以用来指明触发通道名 APPLICID APPLTYPE USERDATA 空 空 空 应用程序名 应用程序平台 用户数据,也可以用来指明触发通道名 进程 ENVRDATA 空 环境数据 队列上的 TRIGGER选项有两种取值:TRIGGER或NOTRIGGER,它相当于触发器的开关。如果设置成NOTRIGGER,则不会有触发发生,所有与触发相关的设置全部失效。 队列上共有三种触发方式:FIRST、EVERY、DEPTH,由队列属性TRIGTYPE指定。无论哪一种方式,能够满足触发条件的消息优先级必须大于等于队列触发优先级属性TRIGMPRI。

队列管理器上的TRIGINT属性表示FIRST方式时触发的复位时间。仅对FIRST方式有效。队列上触发深度属性TRIGDPTH表示DEPTH方式时满足触发条件的队列深度,仅对DEPTH方式有效。

触发方式

WebSphere MQ支持三种触发方式:FIRST、EVERY和DEPTH。

FIRST

顾名思义即“第一条”消息会引起触发,以后紧跟的消息则不会。WebSphere MQ 规定,如果队列深度从0到1的时候,发生FIRST触发。以后一段时间内后继到达的消息只要不是将队列深度从0变成1,则不会再引起FIRST触发。在这段时间过后,FIRST触发复位,下一个到达的消息会再次引起FIRST触发。 触发 b 触发 a b a a c d a c a 时间 TriggerInterval TriggerInterval

所以,准确地说,FIRST不是指队列中到达的第一条消息,而是一段时间内到达的第一条消息。这里所谓的“一段时间”是由队列管理器属性TRIGINT (TriggerInterval) 指定的,

TriggerInterval 单位毫秒,缺省值为 999,999,999,是一段很长的时间,大约11.5天。如图,从触发开始记时,在 TriggerInterval 期间,FIRST触发机制被抑制,只有在这段时间过后,FIRST触发机制才重新起作用。 在应用设计与布署的时候,要适当地调整TriggerInterval时间。一批消息到达的时候,以第一条消息触发起应用程序,一般来说,触发起来的应用程序会连续处理队列中的消息直到队列被取空。后到的消息会在队列中等待一段时间,到FIRST触发机制复位后,由以后的第一条消息再次触发起来的应用程序进行处理。如果消息到达队列是均匀的,间隔时间为T,则消息在队列中的最大等待时间为 TriggerInterval + T。如果 TriggerInterval = 0,则FIRST与EVERY的效果相同。

EVERY

EVERY方式即每次消息的到达都会引起消息触发。但由于消息到达、触发消息生成、应用进程启动、消息处理四个步骤是异步流水线方式完成的,所以,如果消息以高频率方式到达,在消息处理的时候,有可能发现队列中不止一条消息,通常会连续处理。反过来,也可能发现没有消息,因为被上一次触发起来的应用程序处理完了。这个时候,就要求应用程序有一定的灵活性,具有触发一次处理多条消息的能力,在触发后未发现相应消息也无需报错。 如果队列中每一条消息的对应处理程序是相同的,为了追求效率,一个通用的做法如下:Trigger Monitor 可以连续读触发消息直到空,然后启动Trigger程序。Trigger程序可以用Wait方式读取消息并进行处理,连续运行直到一段时间内等不到新来的消息。

DEPTH

在队列深度达到一定值 (TRIGDPTH) 后触发,每次触发后队列管理器会自动关闭队列的触发机制,即将队列的TRIGGER (TriggerControl) 属性变成NOTRIGGER。所以,在应用程序中用MQSET将其复位或通过MQSC alter queue 将触发开关重新打开。在计算队列深度的时候,消息的优先级必须大于等于TRIGMPRI。TriggerDepth = 1 时,DEPTH与EVERY效果相同。

配置

以EVERY触发方式有例,每到达一条消息,启动Win2000 记事本程序。

QM: ---

DEFINE QLOCAL

TRIGGER TRIGTYPE PROCESS INITQ

(QL_QM1)

(EVERY) (P_NOTEPAD)

(SYSTEM.DEFAULT.INITIATION.QUEUE)

+ + + + +

REPLACE

(P_NOTEPAD)

('C:/WINNT/system32/notepad.exe') (abc)

+ + +

APPLICID USERDATA REPLACE

DEFINE PROCESS

触发过程

当消息到达本地队列后,WebSphere MQ会检查: ? 队列TRIGGER开关是否打开

? 消息的优先级是否达到TRIGMPRI

? 根据队列的触发类型,检查触发条件是否满足

? 队列属性中是否指定了触发进程 (PROCESS),相应的进程定义是否存在。如果队

列是传输队列,且指定了TRIGDATA,则可以不检查PROCESS属性,然而也不会生成触发消息。

? 是否有进程对初始化队列INPUT方式打开,即初始化队列上OpenInputCount 计数

至少为 1。一般来说,这意味着Trigger Monitor在工作。

如果检查通过,则产生触发消息,消息的目标队列由队列的INITQ属性指定,当然INITQ也可以是一个远程队列,这样可以将触发消息路由去其它队列管理器。触发消息的格式为MQTM结构,共684字节。如下:

struct tagMQTM { MQCHAR4 MQLONG MQCHAR48 MQCHAR48 MQCHAR64 MQLONG

StrucId; Version; QName; ProcessName; TriggerData; ApplType;

“TM ”

MQTM_VERSION_1

本地队列名,即队列的QUEUE属性 触发进程名,即队列的PROCESS属性 触发数据字串,即队列的TRIGDATA属性 应用程序平台,即进程的APPLTYPE属性 应用程序名,即进程的APPLICID属性 环境数据,即进程的ENVRDATA属性 用户数据,即进程的USERDATA属性

MQCHAR256 ApplId; MQCHAR128 EnvData; MQCHAR128 UserData; };

其中的域一半来自本地队列的属性,另一半来自对应进程定义的属性。触发消息被触发监控器 (Trigger Monitor) 读走,Trigger Monitor可以根据MQTM结构中的域启动相应的触发程序。Trigger Monitor可以自己写,这样可以几乎不受约束地做任何事,甚至不启动触发程序,或亲自去应用消息。如果使用系统缺省的触发监控器 (runmqtrm),启动命令如下,则会将MQTM结构中的Version域改为MQTM_VERSION_2,同时在MQTM结构下加一个域 QMgrName (队列管理器名),形成MQTMC2结构。

runmqtrm -m -q

MQTMC2结构:

struct tagMQTMC2 { MQCHAR4 MQLONG

StrucId; Version;

“TM ”

MQTM_VERSION_1

MQCHAR48 MQCHAR48 MQCHAR64 MQLONG

QName; ProcessName; TriggerData; ApplType;

本地队列名,即队列的QUEUE属性 触发进程名,即队列的PROCESS属性 触发数据字串,即队列的TRIGDATA属性 应用程序平台,即进程的APPLTYPE属性 应用程序名,即进程的APPLICID属性 环境数据,即进程的ENVRDATA属性 用户数据,即进程的USERDATA属性 队列管理器名

MQCHAR256 ApplId; MQCHAR128 EnvData; MQCHAR128 UserData; MQCHAR48 };

QMgrName;

缺省的触发监控器 (runmqtrm) 会启动触发程序 (由MQTM2.ApplId指定),并将MQTMC2结构以命令行参数的方式传给它,传入 argv [1]。对于触发程序而言,从命令行参数收到MQTMC2结构后,可以按照约定读取并处理应用消息。触发过程结束。

并发

对于FIRST和DEPTH触发方式,触发程序一般会以INPUT方式打开本地队列,读取并处理应用消息。在触发程序MQCLOSE之前,可能会有新的消息到达,这些消息无法生成新的触发消息。也就是说,在MQOPEN (MQOO_INPUT_*) 到MQCLOSE之间,队列上的FIRST和DEPTH触发机制是暂时失效的。所以,对于FIRST和DEPTH这两种触发方式,是不可能触发起多个应用程序来并行工作的,这也就是为什么触发起来的应用程序通常要连续工作直到将队列取空。 一个初始化队列上可以有多个Trigger Monitor在读触发消息,即初始化队列的 OpenInputCount 可以大于1。这时,这些Trigger Monitor将会轮流读到触发消息。但是,通常来说,使用触发的应用消息到达的频度是比较低的,一个Trigger Monitor是够用的,多个Trigger Monitor也不会提高性能。

如果大消息在放入队列时被自动拆分成多个段 (Segment),则在 MQPUT 时只会触发一次。但是一旦消息路由到远端目标队列, 它们将被视为多条物理消息而在远端触发多次。

在 WMQ for z/OS 中,Non-Shared Local Queue 在DEPTH方式触发计算消息数量的时候,无论消息是否提交都被计算在内。所以被触发起来的程序有可能没有消息可读,因为有消息尚未提交。这种情况下,建议在 MQGET 的时候使用 WaitInterval 选项,使得读消息等一段时间。Shared Local Queue 在计算消息数量的时候,只计算提交后的消息。

触发通道

1. 可以用进程定义的USERDATA也可以用队列的TRIGDATA属性指定要触发的通道 2. 通常用FIRST方式触发,一段时间内的第一消息自动触发连接

3. 在缺省情况下,初始化队列为SYSTEM.CHANNEL.INITQ。当然也可以使用其它的初

始化队列,那样就需要手工runmqchi。

4. 触发应该设置在通道主动方,如SENDER、REQUESTER。可以设定DISCINT在一断

时间后自动断连,重新处于待触发状态。

配置可以是:(每次第一条消息触发通道,隔10秒钟通道自动断开)

QM1: ----

DEFINE QREMOTE QM2: ----

DEFINE QLOCAL

REPLACE

(C_QM1.QM2) (RCVR) (TCP)

+ + +

CHLTYPE TRPTYPE REPLACE

DEFINE CHANNEL

(QL_QM2)

+

RNAME RQMNAME XMITQ REPLACE

(QX_QM2) (XMITQ)

(FIRST) (P_QM1.QM2)

(SYSTEM.CHANNEL.INITQ) (P_QM1.QM2) (C_QM1.QM2) (C_QM1.QM2) (SDR) (TCP)

('127.0.0.1 (1415)') (QX_QM2) (10)

+ + + + + + + + + + + + + +

USAGE TRIGGER TRIGTYPE PROCESS INITQ REPLACE USERDATA REPLACE CHLTYPE TRPTYPE CONNAME XMITQ DISCINT REPLACE

(QR_QM2) (QL_QM2) (QM2) (QX_QM2)

+ + + +

DEFINE QLOCAL

DEFINE PROCESS

DEFINE CHANNEL

也可以是:

QM1: ----

DEFINE QLOCAL

USAGE TRIGGER TRIGTYPE

(QX_QM2) (XMITQ)

(FIRST)

+ + + +

TRIGDATA INITQ REPLACE

(C_QM1.QM2)

(SYSTEM.CHANNEL.INITQ)

+ +

其它相上,不需要有PROCESS定义

QM2: ---- 同上

触发通道是靠通道初始程序 (Channel Initiator) 完成的,它相当于一个Trigger Monitor,监听相应的初始化队列,一旦有消息在传输队列上等待传送,该程序会从初始化队列中读到触发消息,自动启动通道。届时,发送端就会出现runmqchl进程。事实上,这样的程序用户也可以自己开发。系统提供了缺省的Channel Initiator – runmqchi,它缺省监听在初始化队列SYSTEM.CHANNEL.INITQ上,在strmqm启动队列管理器时自动跟随启动。如果要自行指定触发通道的初始化队列,则需手工启动 runmqchi。

runmqchi [-q InitQueue] [-m QMgrName]

触发CICS交易

1. 使用缺省初始化队列:SYSTEM.DEFAULT.INITIATION.QUEUE 2. THLO 是 CICS 交易名

3. 要将 /usr/lpp/mqm/bin/amqltmc0 作为一个 CICS 交易 (如 TMQM) 加入 CICS,再用

EXEC CICS START TRANSID (TMQM) 将其常驻 cicsas

4. amqltmc0 只监视缺省队列管理器的 SYSTEM.DEFAULT.INITIATION.QUEUE,如果是

自己写的Trigger Monitor则可以自行指定监视的队列管理器和队列。 5. 对于UNIX,要将 cics 用户加入 mqm 组中,使其具有相应的权限。

QM: ---

DEFINE QLOCAL CICS: -----

cicsadd -c pd -r $(REGION_NAME) -P PMQM

PathName=/usr/lpp/mqm/bin/amqltmc0

\\ \\

TRIGGER TRIGTYPE PROCESS INITQ REPLACE

(P) (CICS) (TMQM)

+ + +

APPLTYPE APPLICID REPLACE

(Q)

(EVERY) (P)

+ + + +

(SYSTEM.CICS.INITIATION.QUEUE) +

DEFINE PROCESS

ProgType=program RSLKey=public

cicsadd -c td -r $(REGION_NAME) -P TMQM ProgName=PMQM

本文来源:https://www.bwwdw.com/article/1472.html

Top