BEA Tuxedo的消息队列系统详解

  System/Q部件是Tuxedo系统的一个重要组成部分,它提供了一种队列机制,允许消息按某种排队规则存储到持续介质(如磁盘)或非持续介质(如内存)中,然后再转发给其它处理进程。这种存储转发机制可以保证在两个通信实体之间传递的消息不丢失、不重传,从而保证交易的完整性。


  System/Q的队列通信


  System /Q用到了Tuxedo系统提供的两个服务器:消息队列服务器TMQEUE和消息转发服务器TMQFORWARD。TMQEUE用于对消息进行出队入队管理,TMQFORWARD用于将消息从队列中取出,转发给服务器进行处理,然后将处理结果放回响应队列。


  图1

  System/Q的队列通信可以分为两类:客户机对客户机和客户机对服务器,差别在于前者消息不需要转发,而后者需要将消息转发到服务器请求服务处理。因此,对于前者,配置文件中就不用提供转发服务器TMQFORWARD。

  客户机对客户机的通信

  这种端对端的通信模式是队列系统的简单应用,图1是端对端异步通信模式的展示。左侧客户机通过tpenqueue()函数往队列里写了一条消息,然后接着做下面的工作;右侧客户机通过tpdequeue()函数接收消息,并进行处理,之后再往队列中写消息;左侧客户机从队列中取出消息;至此,一个通信周期完成。

  若使用同步通信,左侧客户往队列中写入消息后,就处于阻塞状态,只有等到取得右侧客户机的响应消息后,流程才继续往下执行。

  客户机对服务器的通信

  这种通信模式是System/Q的常规应用,下面是客户机和服务器的通信流程:


  图2

  图2中左侧为客户机,右侧为服务器,中间为消息队列系统。右侧服务器提供了两个服务:SERVICE1和SERVICE2。在消息队列系统中,TMS_QM是System/Q的事务管理服务器,它定义了一个队列服务器组,组中定义了一个队列空间,队列空间中定义了有四个消息队列,SERVICE1和SERVICE2分别是对应于同名的两个服务的队列(这是一种习惯的命名规则,客户机若请求服务器中的SERVICE1服务,就把请求消息放入SERVICE1队列中)。CLIENT_RPLY1是SERVICE1服务对请求的响应队列,FAILUREQ是服务器操作失败的响应队列。图中流程说明:①客户机提出对SERVICE1的请求;②TMQUEUE将请求消息入队;③TMQUEUE向客户机汇报入队是否成功;④TMQFORWARD取出请求消息;⑤将请求消息传给SERVICE1;⑥SERVICE1对请求作出响应;⑦TMQFORWARD将响应消息入队;⑧客户机要求取回响应消息;⑨TMQUEUE取出响应消息;⑩TMQUEUE取消息是否成功。


  队列管理


  在使用System/Q部件之前,需要先创建队列空间和队列。Tuxedo对队列的操作和管理基本上是通过qmadmin来完成的,在NT下,qmadmin是一个DOS应用程序,运行前,先要设置环境变量QMCONFIG,如:

  set QMCONFIG=C:\qsample\QUE

  qmadmin通过这个变量决定在C:\qsample目录下创建队列设备QUE。运行qmadmin,出现一个操作环境,按照如下命令依次创建队列设备、队列空间和消息队列:

  > crdl c:\qsample\QUE 0 400

  … …

  > qspacecreate -n 100B

  Queue space name: QSPACE

  IPC Key for queue space: 62839

  Size of queue space in disk pages: 100

  Number of queues in queue space: 6

  …

  > qopen QSPACE

  > qcreate

  Queue name: STRING

  Queue order (priority, time, expiration, fifo, lifo): fifo

  crdl命令创建了一个队列设备,名为QUE,大小为400个磁盘块;接着用qspacecreate命令创建了一个队列空间,名为QSPACE,大小为100个磁盘块;最后用qcreate命令在QSPACE中创建了一个名为STRING的队列,它使用了先进先出(fifo)的排队规则。为了完成本文中介绍的例子,还必须创建另外两个队列:RPLYQ和ERRQUE。


  System/Q的应用实例


  qsample是Tuxedo用于演示System/Q的例子,客户机将一个包含字符串的消息放入STRING队列中,TMQFORWARD将该消息转发到STRING服务,要求它将消息体内的字符串转换成大写。处理完毕后,TMQFORWARD把响应消息放入响应队列RPLYQ,客户机再从RPLYQ中取出响应消息,进行打印输出。

  qsample的服务程序

  服务程序server.c的内容如下,其中第2行定义了一个名为 STRING的服务,第9行完成字母的大写转换,第11行通过tpreturn函数将转换结果传回给TMQFORWARD服务器,并表明转换成功。

  1. #include "atmi.h"

  2. STRING(msg)

  3. TPSVCINFO msg;

  4. {

  5. char str;

  6. int i;

  7. str = (char )msg->data;

  8. for (i = 0; i < msg->len; i++) {

  9. str[i] = toupper(str[i]);

  10. }

  11. tpreturn(TPSUCCESS, 0, msg->data, 0L, 0);

  设置环境变量

  除了设置QMCONFIG外,还需要根据实际情况设置:TUXDIR(Tuxedo的安装目录)、APPDIR和TUXCONFIG环境变量。

  创建消息队列

  qsample用到了一个队列空间QSPACE和三个队列STRING、RPLYQ与errque。在NT平台下创建它们的最好办法是使用nmake命令,即“c:\qsample\nmake/f qsapme.nt QUE”,当然也可以手工创建。

  创建事务日志

  TMS_QM在队列事务管理时,需要用到日志设备,创建办法也是用nmake命令:

  c:\qsample\nmake/f qsapme.nt TLOG

  它执行了qsample.nt中预定义的一组Tuxedo命令。

  qsample的客户程序

  客户程序client.c的流程是:加入Tuxedo系统→消息入队→消息出队→退出系统。simpapp直接通过tpcall()函数调用TOUPPER服务,而qsample则将消息放入队列STRING,由TMQFORWARD服务器通过tpcall()调用STRING服务。下面是部分源代码,其中略去了错误捕捉处理的部分:

  #include "Uunix.h"

  #include "atmi.h"

  main(){

  char reqstr;

  / 要发送的字符串 /

  long len;

  / 返回的字符串长 /

  TPQCTL qctl;

  / System/Q的控制结构 /

  tpinit(NULL);

  / 加入Tuxedo系统 /

  reqstr = tpalloc("STRING",NULL,100));

  / System/Q的控制结构 /

  (void) strcpy(reqstr,"this is a q example");

  / 输入要转换的字符串 /

  (void) printf("before: %s\n", reqstr);

  qctl.flags = TPQREPLYQ; / 说明要指定响应队列 /

  (void) strcpy(qctl.replyqueue, "RPLYQ"); / 指定响应队列名称为RPLYQ /

  / 使用消息进入队列空间QSPACE的STRING队列,reqstr为消息体 /

  tpenqueue("QSPACE", "STRING", (TPQCTL )&&qctl,(char )reqstr,0, 0);

  qctl.flags = TPQWAIT;

  / 设置等待响应标记 /

  tpdequeue("QSPACE", "RPLYQ", (TPQCTL )&&qctl, (char )&&reqstr,&&len, TPNOTIME);

  (void) printf("after: %s\n",reqstr);

  tpfree(reqstr);

  / 释放内存并退出 /

  (void) tpterm();

  / 退出Tuxedo系统 /

  }

  修改配置文件

  配置文件ubb.sample定义了三个服务器:server、TMQUEUE、TMQFORWARD和两个组:GROUP1和QUE1。SERVER提供STRING服务,TMQUEUE和TMQFORWARD属于QUE1组。QUE1组中的OPENINFO参数定义了队列资源管理器TUXEDO/QM、队列设备和队列空间。最后一行CLOPT参数中定义了将消息转发给STRING服务。

  GROUPS

  GROUP1

   LMID = SITE1 GRPNO = 1

   TMSNAME=TMS TMSCOUNT=2

  QUE1

   LMID = SITE1 GRPNO = 2

   TMSNAME = TMS_QM TMSCOUNT = 2

   OPENINFO = "TUXEDO/QM:c:\qsample\QUE;QSPACE"

  SERVERS

  DEFAULT: CLOPT="-A"

  server SRVGRP=GROUP1 SRVID=1

  TMQUEUE

   SRVGRP = QUE1 SRVID = 1

   GRACE = 0 RESTART = Y CONV = N MAXGEN=10

   CLOPT = "-s QSPACE:TMQUEUE -- "

  TMQFORWARD

   SRVGRP=QUE1 SRVID= 5 GRACE=0 RESTART=Y CONV=N MAXGEN=10

  编译和运行

  确保make文件qsample.nt中include和lib变量已经包含了Tuxedo系统的头文件和库文件,然后使用如下命令进行编译:

  c:\qsample\nmake/f qsample.nt all

  成功后,用tmloadcf命令加载配置文件,用tmboot命令启动应用程序,最后,运行客户程序client.exe,就可以看到STRING服务的处理结果。

你可能感兴趣的:(技术)