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服務的處理結果。