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

  • 格式:doc
  • 大小:135.00 KB
  • 文档页数:8

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

一般说来,该程序应该首先从本地队列中将应用消息读出并进行应用处理。

应用消息触发消息其中,本地队列、初始化队列、进程定义是事先设置好的WebSphere MQ对象,触发监控器也是处于运行状态的,即在初始化队列上等待触发消息,一旦读到触发消息,则可以立即启动MQGET应用程序,所以MQGET应用程序是被触发启动的,通常情况下是触发监控器的子进程。

所有这些都只是设定了“连锁反应”中的各个环节,而触动这个机关的是应用消息的到达。

队列上的 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 触发。

所以,准确地说,FIRST 不是指队列中到达的第一条消息,而是一段时间内到达的第一条消息。

这里所谓的“一段时间”是由队列管理器属性TRIGINT (TriggerInterval) 指定的,TriggerInterval 单位毫秒,缺省值为999,999,999,是一段很长的时间,大约11.5天。

如图,从触发开始记时,在TriggerInterval 期间,FIRST触发机制被抑制,只有在这段时间过后,FIRST触发机制才重新起作用。

在应用设计与布署的时候,要适当地调整TriggerInterval时间。

一批消息到达的时候,以第一条消息触发起应用程序,一般来说,触发起来的应用程序会连续处理队列中的消息直到队列被取空。

后到的消息会在队列中等待一段时间,到FIRST触发机制复位后,由以后的第一条消息再次触发起来的应用程序进行处理。

如果消息到达队列是均匀的,间隔时间为T,则消息在队列中的最大等待时间为TriggerInterval + T。

如果TriggerInterval = 0,则FIRST 与EVERY的效果相同。

EVERYEVERY方式即每次消息的到达都会引起消息触发。

但由于消息到达、触发消息生成、应用进程启动、消息处理四个步骤是异步流水线方式完成的,所以,如果消息以高频率方式到达,在消息处理的时候,有可能发现队列中不止一条消息,通常会连续处理。

反过来,也可能发现没有消息,因为被上一次触发起来的应用程序处理完了。

这个时候,就要求应用程序有一定的灵活性,具有触发一次处理多条消息的能力,在触发后未发现相应消息也无需报错。

如果队列中每一条消息的对应处理程序是相同的,为了追求效率,一个通用的做法如下:Trigger Monitor 可以连续读触发消息直到空,然后启动Trigger程序。

Trigger程序可以用Wait方式读取消息并进行处理,连续运行直到一段时间内等不到新来的消息。

DEPTH在队列深度达到一定值(TRIGDPTH) 后触发,每次触发后队列管理器会自动关闭队列的触发机制,即将队列的TRIGGER (TriggerControl) 属性变成NOTRIGGER。

所以,在应用程序中用MQSET将其复位或通过MQSC alter queue 将触发开关重新打开。

在计算队列深度的时候,消息的优先级必须大于等于TRIGMPRI。

TriggerDepth = 1 时,DEPTH与EVERY 效果相同。

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

QM:---DEFINE QLOCAL (QL_QM1) +TRIGGER +TRIGTYPE (EVERY) +PROCESS (P_NOTEPAD) +INITQ (SYSTEM.DEFAULT.INITIATION.QUEUE) +REPLACEDEFINE PROCESS (P_NOTEPAD) +APPLICID ('C:/WINNT/system32/notepad.exe') +USERDATA (abc) +REPLACE触发过程当消息到达本地队列后,WebSphere MQ会检查:●队列TRIGGER开关是否打开●消息的优先级是否达到TRIGMPRI●根据队列的触发类型,检查触发条件是否满足●队列属性中是否指定了触发进程(PROCESS),相应的进程定义是否存在。

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

●是否有进程对初始化队列INPUT方式打开,即初始化队列上OpenInputCount 计数至少为1。

一般来说,这意味着Trigger Monitor在工作。

如果检查通过,则产生触发消息,消息的目标队列由队列的INITQ属性指定,当然INITQ 也可以是一个远程队列,这样可以将触发消息路由去其它队列管理器。

触发消息的格式为MQTM结构,共684字节。

如下:struct tagMQTM {MQCHAR4 StrucId; “TM ”MQLONG Version; MQTM_VERSION_1MQCHAR48 QName; 本地队列名,即队列的QUEUE属性MQCHAR48 ProcessName; 触发进程名,即队列的PROCESS属性MQCHAR64 TriggerData; 触发数据字串,即队列的TRIGDATA属性MQLONG ApplType; 应用程序平台,即进程的APPLTYPE属性MQCHAR256 ApplId; 应用程序名,即进程的APPLICID属性MQCHAR128 EnvData; 环境数据,即进程的ENVRDATA属性MQCHAR128 UserData; 用户数据,即进程的USERDATA属性};其中的域一半来自本地队列的属性,另一半来自对应进程定义的属性。

触发消息被触发监控器(Trigger Monitor) 读走,Trigger Monitor可以根据MQTM结构中的域启动相应的触发程序。

Trigger Monitor可以自己写,这样可以几乎不受约束地做任何事,甚至不启动触发程序,或亲自去应用消息。

如果使用系统缺省的触发监控器(runmqtrm),启动命令如下,则会将MQTM结构中的V ersion域改为MQTM_VERSION_2,同时在MQTM结构下加一个域QMgrName (队列管理器名),形成MQTMC2结构。

runmqtrm -m <Queue Manager> -q <Init Queue>MQTMC2结构:struct tagMQTMC2 {MQCHAR4 StrucId; “TM ”MQLONG Version; MQTM_VERSION_1MQCHAR48 QName; 本地队列名,即队列的QUEUE属性MQCHAR48 ProcessName; 触发进程名,即队列的PROCESS属性MQCHAR64 TriggerData; 触发数据字串,即队列的TRIGDATA属性MQLONG ApplType; 应用程序平台,即进程的APPLTYPE属性MQCHAR256 ApplId; 应用程序名,即进程的APPLICID属性MQCHAR128 EnvData; 环境数据,即进程的ENVRDATA属性MQCHAR128 UserData; 用户数据,即进程的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也可以用队列的TRIGDA TA属性指定要触发的通道2.通常用FIRST方式触发,一段时间内的第一消息自动触发连接3.在缺省情况下,初始化队列为SYSTEM.CHANNEL.INITQ。