import bea.jolt.JoltRemoteService;
import bea.jolt.JoltSession;
import bea.jolt.JoltSessionAttributes;
public class SimpleApp {
public static void main(String[] args) {
JoltSession session;
JoltSessionAttributes sattr;
JoltRemoteService joltService;
String userName = "";
String userPassword = "";
String appPassword = "";
String userRole = "";
sattr = new JoltSessionAttributes();
sattr.setString(JoltSessionAttributes.APPADDRESS,
"http://XX.XX.X:8307");
sattr.setInt(JoltSessionAttributes.IDLETIMEOUT, 300);
session = new JoltSession(sattr, userName, userRole, userPassword,
appPassword);
joltService = new JoltRemoteService("testServiceName", session);
joltService.setString("sw01_1", "<Hello>");
joltService.setString("sw01_2", "<Hello>");
joltService.setString("sw01_3", "<Hello>");
joltService.setString("sw01_4", "<Hello>");
joltService.setString("sw01_5", "<Hello>");
joltService.setString("sw01_6", "<Hello>");
joltService.setString("sw01_7", "<Hello>");
joltService.setString("sw01_8", "<Hello>");
joltService.call(null);
}
}
摘要:
本《功略》集中了TUXEDO應(yīng)用中,可能涉及到的所有時(shí)間參數(shù),并分別對其進(jìn)行詳細(xì)描述,不但對其出處、取值等基本屬性進(jìn)行查證,而且,通過分析其內(nèi)在的控制機(jī)制,給出設(shè)置建議,以期能夠達(dá)到透徹理解、方便查閱、準(zhǔn)確使用的目的。
1 前言
金融、電信等眾多行業(yè)的綜合營業(yè)系統(tǒng)中,廣泛使用了TUXEDO交易中間件,用來處理大量并發(fā)的聯(lián)機(jī)事務(wù)處理(OLTP)業(yè)務(wù)。典型的OLTP業(yè)務(wù),每筆業(yè)務(wù)的信息量較小,而且,具有一定的實(shí)時(shí)性,對時(shí)間的要求非常嚴(yán)格。
TUXEDO,聯(lián)系著DATABASE和客戶端軟件,憑借其多層次的超時(shí)控制機(jī)制,達(dá)到客戶端快速響應(yīng),服務(wù)器端穩(wěn)定可靠的效果。
TUXEDO的多層次的超時(shí)控制機(jī)制中,涉及到的時(shí)間參數(shù)不少于10個(gè),再加上與之緊密聯(lián)系的DATABASE中的幾個(gè)超時(shí)參數(shù),確實(shí)比較復(fù)雜。遺憾的是,目前還沒有的專門的文檔對它們進(jìn)行詳細(xì)說明,而是分散在不同的專題中分別說明,而且,不同的專題中,解釋的詳細(xì)程度也不一樣,在查閱過程中,多有不便。
本文試圖將這些參數(shù)集中起來,對每一個(gè)都加以詳細(xì)說明,并試圖解釋每個(gè)參數(shù)存在的原因。大部分參數(shù)時(shí)間長短的設(shè)置,除個(gè)別外,基本沒有固定的模式,只要了解它們的具體含義,并結(jié)合具體應(yīng)用系統(tǒng)的實(shí)際要求,相信大家都能夠作出合理的配置。
2 全功略解讀
2.1 SCANUNIT
2.1.1 參數(shù)出處
UBBCONFIG配置文件 -> RESOURCES -> SCANUNIT 。
2.1.2 時(shí)間單位
秒,且必須為5的倍數(shù)。
2.1.3 取值范圍
大于0小于等于60中5的倍數(shù),即{5,10,15,20,25,30,35,40,45,50,55,60}。
2.1.4 默認(rèn)取值
10 。
2.1.5 用途解釋 ⑴
這個(gè)參數(shù)大家都會用,比較好理解,TUXEDO中,BBL是用來對Bulletin Board進(jìn)行管理和監(jiān)控的系統(tǒng)進(jìn)程,它基于時(shí)間片的輪詢方式,時(shí)間片的大小就是SCANUNIT的值,SCANUNIT是Tuxedo對系統(tǒng)進(jìn)行管理的最基本時(shí)間單位。每隔SCANUNIT,BBL對Bulletin Board進(jìn)行一次檢查,看看有沒有超時(shí)的事務(wù)或阻塞的服務(wù)請求。后面講到的很多時(shí)間參數(shù)都是以SCANUNIT為單位。
2.1.6 超時(shí)后果
僅僅是個(gè)輪詢時(shí)間單位而已,到時(shí)間就輪詢,如此而已。
2.1.7 設(shè)置考慮
作為一個(gè)涉及到整個(gè)TUXDO系統(tǒng)的基本單位時(shí)間,如果業(yè)務(wù)需要,對時(shí)間參數(shù)控制比較嚴(yán)格,設(shè)置為5也不算小。如果系統(tǒng)業(yè)務(wù)對時(shí)間要求不嚴(yán)格,那就大點(diǎn)兒,60也沒什么不可以;畢竟頻繁輪詢是要耗費(fèi)更多系統(tǒng)資源的,而任何對資源的不必要的消耗都是浪費(fèi)。
2.2 SANITYSCAN
2.2.1 參數(shù)出處
UBBCONFIG配置文件 -> RESOURCES -> SANITYSCAN 。
2.2.2 時(shí)間單位
SCANUNIT 。
2.2.3 取值范圍
1 ~32767 。
2.2.4 默認(rèn)取值
大約120/SCANUNIT。
2.2.5 用途解釋 ⑵
進(jìn)行系統(tǒng)健全性檢查,主要包括Server進(jìn)程狀態(tài)和Bulletin Board數(shù)據(jù)結(jié)構(gòu),檢查Server進(jìn)程是否存活,如果已經(jīng)不存在,會清理Bulletin Board中相應(yīng)的數(shù)據(jù)項(xiàng)及IPC資源,并根據(jù)參數(shù)配置決定是否重新啟動,如果設(shè)了RESTART=Y,所占的Message Queue不會被清除,Queue中的Request得到保留,仍會被處理。如果是MP模式,BBL還會給DBBL發(fā)狀態(tài)消息。
2.2.6 超時(shí)后果
僅僅是個(gè)系統(tǒng)健康檢查的間隔時(shí)間而已,到時(shí)間就檢查,如此而已。
2.2.7 設(shè)置考慮
作為一個(gè)涉及到整個(gè)TUXDO系統(tǒng)健康檢查的間隔時(shí)間,如果系統(tǒng)處在一個(gè)穩(wěn)定的運(yùn)行環(huán)境中,網(wǎng)絡(luò)、數(shù)據(jù)庫、應(yīng)用都很穩(wěn)定,那這個(gè)參數(shù)可以大一些;如果運(yùn)行環(huán)境不穩(wěn)定,系統(tǒng)繁忙,而且Server進(jìn)程經(jīng)常因異常(如超時(shí))而死掉,那就設(shè)置小一些。設(shè)置的原則和SCANUNIT一樣:不要隨意浪費(fèi)系統(tǒng)資源。
2.3 BBLQUERY
2.3.1 參數(shù)出處
UBBCONFIG配置文件 -> RESOURCES -> BBLQUERY。
2.3.2 時(shí)間單位
SCANUNIT
2.3.3 取值范圍 ⑶
BBLQUERY必須大于等于SANITYSCAN,tmloadcf 時(shí)會強(qiáng)制檢查,如果設(shè)的值小于SANITYSCAN,tmloadcf會自動調(diào)整為SANITYSCAN。
2.3.4 默認(rèn)取值
大約300/SCANUNIT。
2.3.5 用途解釋 ⑷
BBL檢查,在MP模式下,BBL會每隔一段時(shí)間都發(fā)送了" I am ok "心跳信息給DBBL,這個(gè)間隔就是BBLQUERY。
2.3.6 超時(shí)后果 ⑸
如果DBBL在規(guī)定時(shí)間間隔內(nèi)沒有收到某個(gè)BBL的信息,DBBL它會主動發(fā)送Request給那個(gè)BBL,判斷其是否正常。(如果等了DBBLWAIT后仍然沒有回復(fù),DBBL會認(rèn)為那臺機(jī)器有問題,然后,將其隔離。)
2.3.7 設(shè)置考慮
此設(shè)置僅僅在MP模式下才起作用。
在MP模式下,如果TUXEDO系統(tǒng)需要對不穩(wěn)定的運(yùn)行環(huán)境可能發(fā)生的故障作出快速的反應(yīng),那么BBLQUERY要設(shè)置小一些,讓系統(tǒng)快速的自我檢查??紤]網(wǎng)絡(luò)傳輸時(shí)間、系統(tǒng)反應(yīng)速度等因素,網(wǎng)絡(luò)速度越慢,系統(tǒng)負(fù)載越重,取值越大;反之亦然。
如果系統(tǒng)運(yùn)行環(huán)境很穩(wěn)定,利用其默認(rèn)值即可,甚至可以更大數(shù)值。
2.4 DBBLWAIT
2.4.1 參數(shù)出處
UBBCONFIG配置文件 -> RESOURCES -> DBBLWAIT。
2.4.2 時(shí)間單位
SCANUNIT。
2.4.3 取值范圍
大于0。
2.4.4 默認(rèn)取值
1和20/SCANUNIT中的較大者 。
2.4.5 用途解釋 ⑹
如果DBBL在規(guī)定時(shí)間間隔BBLQUERY內(nèi)沒有收到某個(gè)BBL的"I AM OK"信息,它會發(fā)Request給那個(gè)BBL,其等待回復(fù)的時(shí)間就是DBBLWAIT。
2.4.6 超時(shí)后果 ⑺
DBBL等了DBBLWAIT后仍然沒有回復(fù),DBBL會認(rèn)為相關(guān)BBL的機(jī)器有問題,然后,將其隔離(partation)。
2.4.7 設(shè)置考慮
此設(shè)置僅僅在MP模式下才起作用。
在MP模式下,考慮網(wǎng)絡(luò)傳輸時(shí)間、系統(tǒng)反應(yīng)速度等因素,網(wǎng)絡(luò)速率越大,系統(tǒng)負(fù)載越輕,此數(shù)值越小;反之亦然。
2.5 BLOCKTIME
2.5.1 參數(shù)出處
UBBCONFIG配置文件 -> RESOURCES -> BLOCKTIME。
2.5.2 時(shí)間單位
SCANUNIT。
2.5.3 取值范圍
大于0。
2.5.4 默認(rèn)取值
大約60/SCANUNIT。
2.5.5 用途解釋
Client端阻塞請求(Blocking call)服務(wù)的超時(shí)值,BBL發(fā)現(xiàn)有超時(shí)的Request時(shí),會給相應(yīng)的Client端發(fā)超時(shí)信息。
此參數(shù)僅僅在"阻塞請求"的情況下起作用,因此,理解它,關(guān)鍵要理解什么是阻塞請求(Blocking call)?習(xí)慣上,我們將"阻塞請求"理解為"同步請求",將"異步請求"理解為"非阻塞請求",是源于將"<發(fā)送請求-得到結(jié)果>"這一過程看成為一個(gè)整體。如果是整體的同步操作,就認(rèn)為是"阻塞請求";如果是分開異步的操作,就認(rèn)為是"非阻塞請求"。
其實(shí),異步操作中,同樣存在"阻塞請求",tuxedo中,tpacall和tpgetrply這兩個(gè)異步操作各自本身就是"阻塞請求",tpacall是將請求發(fā)送到請求隊(duì)列,tpgetrply是將從結(jié)果隊(duì)列中取出結(jié)果,如果沒有特殊的設(shè)置,這兩個(gè)操作本身都是阻塞的,BLOCKTIME將起作用。
以Request/Reply方式為例,將成功發(fā)送請求的時(shí)長設(shè)置為T1,將請求處理的時(shí)長(含排隊(duì)等待)設(shè)置為T2,將成功取得結(jié)果的時(shí)長設(shè)置為T3,那么在下面不同的情況下,將觸發(fā)BLOCKTIME,引起超時(shí):
?。?) tpcall()不在transaction中,flag為0,當(dāng)T1+T2+T3 > BLOCKTIME時(shí),發(fā)生超時(shí) ;
(2) tpcall()不在transaction中,flag為TPNOBLOCK,只有當(dāng)一次調(diào)用即成功完成T1階段發(fā)送請求的任務(wù)后,T2+T3 > BLOCKTIME時(shí),發(fā)生超時(shí) ;
(3) tpacall()不在transaction中,flag為0,當(dāng)T1 > BLOCKTIME時(shí),發(fā)生超時(shí) ;
?。?) tpgetrply()不在transaction中,flag為0,當(dāng)T2+T3 > BLOCKTIME時(shí),發(fā)生超時(shí) ;
(5) tpcall,tpacall,tpgetrply,在其他任何情況,BLOCKTIME都將不起作用。
?。?) 如果請求處于事務(wù)交易(transaction)中,此參數(shù)不起作用,取代它的是 TransactionTimeOut。
2.5.6 超時(shí)后果
在上面描述的四種情況下,Server端 BBL返回Client端超時(shí)錯(cuò)誤:tperrno = 13 (TPETIME)。同時(shí),client端和Server端已經(jīng)建立的聯(lián)接不受任何影響,繼續(xù)保持聯(lián)接。
2.5.7 設(shè)置考慮
此參數(shù)涉及整個(gè)TUXEDO系統(tǒng),不能夠直接適應(yīng)業(yè)務(wù)系統(tǒng)中不同場合的不同時(shí)間等待要求,而且在應(yīng)用過程中,存在誤差,不適合進(jìn)行精確到秒的時(shí)間控制。
準(zhǔn)確有效的使用這個(gè)參數(shù),需要考慮好以下幾個(gè)問題:
?。?) 應(yīng)用中是否完全依賴這個(gè)參數(shù)進(jìn)行時(shí)間控制?
?。?) 有哪些業(yè)務(wù)依賴這個(gè)參數(shù)進(jìn)行時(shí)間控制?
?。?) 平衡各種業(yè)務(wù),此參數(shù)設(shè)置為多少?
?。?) 除此參數(shù)外,是否需要利用其他的超時(shí)控制機(jī)制?
2.6 WSL CLOPT [-T Client_timeout]
2.6.1 參數(shù)出處
UBBCONFIG配置文件 -> SERVERS -> WSL -> CLOPT "-T"。
2.*** 默認(rèn)取值
0 ,意味著無限等待時(shí)間。
2.6.5 用途解釋 ⑻
系統(tǒng)允許的Client靜默時(shí)長,即Client和WSH建立聯(lián)接后,如果在此指定的時(shí)間內(nèi)客戶端沒有發(fā)送任何請求,WSH會自動回收與此Client端相關(guān)的資源。
2.6.6 超時(shí)后果 ⑼
WSH會自動釋放和這個(gè)Client端的聯(lián)接,并將此Client在Bulletin Board中的數(shù)據(jù)項(xiàng)清空,RollBack它未完成的事務(wù) 。
2.6.7 設(shè)置考慮
此參數(shù)的設(shè)置目的,主要是從Server的角度進(jìn)行考慮,防止在Client端意外失效的情況下仍然耗費(fèi)Server端的資源。
如果設(shè)置太小,那么頻繁的檢測同樣要消耗Server端一定的資源,而且,在使用長聯(lián)接的系統(tǒng)中,系統(tǒng)空閑時(shí),容易造成已經(jīng)建立的長聯(lián)接頻繁的釋放,影響正常業(yè)務(wù)的提供。
如果設(shè)置為0,不管發(fā)生什么狀況,哪怕是Client端系統(tǒng)真的崩潰了,也不會觸發(fā)此超時(shí),這將造成Server端資源的無謂浪費(fèi)。
建議:在業(yè)務(wù)負(fù)載不均衡的長聯(lián)接業(yè)務(wù)系統(tǒng)中,根據(jù)業(yè)務(wù)實(shí)際空閑時(shí)間,適當(dāng)加大此數(shù)值。
2.7 WSL CLOPT [-t timeout]
2.7.1 參數(shù)出處
UBBCONFIG配置文件 -> SERVERS -> WSL -> CLOPT "-t"。
2.7.2 時(shí)間單位
SCANUNIT。
2.7.3 取值范圍
大于0。
2.7.4 默認(rèn)取值
非安全應(yīng)用為3,安全應(yīng)用為6 。
2.7.5 用途解釋
建立聯(lián)接時(shí)長,指workstation Client建立與server端WSH建立聯(lián)接允許的最長時(shí)間,因?yàn)榉前踩珣?yīng)用建立聯(lián)接時(shí)不需要進(jìn)行用戶校驗(yàn)等步驟,因此,建立聯(lián)接需要的時(shí)間較短。同理,安全應(yīng)用需要的時(shí)間較長。
2.7.6 超時(shí)后果
建立聯(lián)接失敗。
2.7.7 設(shè)置考慮
設(shè)置此參數(shù),要分析業(yè)務(wù)系統(tǒng)中,網(wǎng)絡(luò)帶寬因素、用戶驗(yàn)證的復(fù)雜程度等。
2.8 WSL CLOPT [-I init_timeout]
2.8.1 參數(shù)出處
UBBCONFIG配置文件 -> SERVERS -> WSL -> CLOPT "-I"。
2.8.2 時(shí)間單位
秒。
2.8.3 取值范圍
大于0。
2.8.4 默認(rèn)取值
60 。
2.8.5 用途解釋 ⑽
WorkStation Client端和后臺建立聯(lián)接的超時(shí)參數(shù)值。
?。ㄗⅲ焊杏X上此參數(shù)和 WSL CLOPT [-t timeout]功能類似)
2.8.6 超時(shí)后果
不確定,現(xiàn)有的文檔沒有一點(diǎn)兒解釋。按照字面解釋,應(yīng)該是tpinit的超時(shí)時(shí)間,但是,在tpinit所有的錯(cuò)誤中,只有TPESYSTEM可能承擔(dān)這個(gè)超時(shí)后果,而且僅僅是可能。
2.8.7 設(shè)置考慮
在使用過程中,沒有感覺到這個(gè)參數(shù)的存在,也從來沒有專門設(shè)置過。
2.9 WSL CLOPT [-N network_timeout]
2.9.1 參數(shù)出處
UBBCONFIG配置文件 -> SERVERS -> WSL -> CLOPT "-N"。
2.9.2 時(shí)間單位
秒。
2.9.3 取值范圍
大于等于0。
2.9.4 默認(rèn)取值
0 。
2.9.5 用途解釋
網(wǎng)絡(luò)超時(shí),指Workstation client利用網(wǎng)絡(luò)接收數(shù)據(jù)(receive data)的等待時(shí)間。
我們同樣需要分析觸發(fā)Network Timeout的不同條件。
以Request/Reply方式中的tpcall為例,將成功發(fā)送請求的時(shí)長設(shè)置為T1,將請求處理的時(shí)長(含排隊(duì)等待)設(shè)置為T2,將成功取得結(jié)果的時(shí)長設(shè)置為T3,那么在如下情況下,將觸發(fā)Network Timeout,引起超時(shí):
?。?) tpcall()不在transaction中,flag為0,當(dāng) BLOCKTIME> T1+T2+T3 > NetworkTimeout時(shí),觸發(fā)此超時(shí) ;
?。?) tpcall() 在transaction中,flag為0,當(dāng)TranactionTimeout> TI+T2+T3 > NetworkTimeout時(shí),觸發(fā)此超時(shí) ;
?。?) tpcall()不在transaction中,flag為TPNOBLOCK,只有當(dāng)一次調(diào)用即成功完成T1階段發(fā)送請求的任務(wù)后,當(dāng) BLOCKTIME> T2+T3 > NetworkTimeout時(shí),觸發(fā)此超時(shí) ;
?。?) tpcall()在transaction中,flag為TPNOBLOCK,只有當(dāng)一次調(diào)用即成功完成T1階段發(fā)送請求的任務(wù)后,當(dāng) TranactionTimeout> T2+T3 > NetworkTimeout時(shí),觸發(fā)此超時(shí) ;
?。?) tpcall()不在transaction中,flag為TPNOTIME,當(dāng) T1+T2+T3 > NetworkTimeout時(shí),觸發(fā)此超時(shí) ;
(6) tpcall()在transaction中,flag為TPNOTIME,當(dāng) TranactionTimeout> TI+T2+T3 > NetworkTimeout時(shí),觸發(fā)此超時(shí) ;
(7) tpcall在其他任何情況,NetworkTimeout都將不起作用。
?。?) 同理,可以確定NetworkTimeout在tpacall和tpgetrply中起的作用。
2.9.6 超時(shí)后果
在上面描述的六種情況下, Client端操作失敗,同時(shí),client端斷開與Server端已經(jīng)建立的聯(lián)接。Server端已經(jīng)為此Client完成的操作和分配的資源不能立刻回滾和釋放,Server端需要等待前面介紹過的Client_timeout時(shí)間后,再釋放相關(guān)的資源。
2.9.7 設(shè)置考慮
此參數(shù)的設(shè)置目的,主要是從Client的角度進(jìn)行考慮,防止在Server端意外失效的情況下,仍然消耗Client端的資源。
設(shè)置參數(shù),必須避免小于BLOCKTIME或TransactionTimeout的情況,因?yàn)樵谶@種情況下,會出現(xiàn)業(yè)務(wù)正常等待中,聯(lián)接卻中斷的現(xiàn)象,這是一定要避免的。
同時(shí),由于此超時(shí)觸發(fā)的聯(lián)接中斷,并不能立刻釋放Server端的資源,帶來業(yè)務(wù)執(zhí)行過程中的不確定性,因此,此參數(shù)要謹(jǐn)慎使用。
2.10 SVCTIMOUT
2.10.1 參數(shù)出處
UBBCONFIG配置文件 -> SERVICES -> SVCTIMEOUT 。
2.10.2 時(shí)間單位
秒
2.10.3 取值范圍
大于等于0。
2.10.4 默認(rèn)取值
0,表示無限時(shí)長 。
2.10.5 用途解釋
服務(wù)處理時(shí)長(Service Processing Time),表示系統(tǒng)允許服務(wù)處理請求的時(shí)間長度。
此參數(shù)主要是維護(hù)Server端系統(tǒng)安全的角度,防止由于系統(tǒng)異常引起的失控服務(wù)占據(jù)系統(tǒng)資源,阻礙正常的后續(xù)業(yè)務(wù)請求。它起到了一個(gè)清道夫的作用,將不能有效提供服務(wù)的Services清除出系統(tǒng),并依靠系統(tǒng)的其他機(jī)制,重新產(chǎn)生具有活力的Services。
2.10.6 超時(shí)后果
超時(shí)后,此Service所屬的Server將被系統(tǒng)的SIGKILL信號清除;此操作不會影響與此Server相關(guān)的其他正在運(yùn)行的副本Servers。
如果系統(tǒng)設(shè)置SERVERS->RESTART=Y,那么,被清除的Server將立刻自動重新啟動。重新啟動的次數(shù)受隨后介紹的MAXGEN和GRACE兩個(gè)參數(shù)聯(lián)合限制。
如果系統(tǒng)設(shè)置SERVERS->RCMD為有效命令文件,那么,在重啟此Server時(shí),將同時(shí)執(zhí)行此命令,如向管理員發(fā)送通知郵件等。
如果SERVER沒有RESTART=Y(jié)設(shè)置,那么Server將不會自動重新啟動。
2.10.7 設(shè)置考慮
此參數(shù)不是系統(tǒng)全局參數(shù),而是涉及到單個(gè)Service,可以根據(jù)不同的Service的處理時(shí)間進(jìn)行設(shè)置。由于其主要起到系統(tǒng)清道夫的角色,因此,建議設(shè)置為正常Service處理時(shí)長的3倍較合適,以避免清除正常運(yùn)行的Service,使正常運(yùn)行的業(yè)務(wù)受到影響。
如果系統(tǒng)運(yùn)行環(huán)境基本穩(wěn)定,一旦出現(xiàn)底層網(wǎng)絡(luò)或數(shù)據(jù)庫系統(tǒng)故障,不是在短時(shí)間內(nèi)能夠恢復(fù),建議將此參數(shù)增大,至少為平均恢復(fù)時(shí)間,甚至可以利用默認(rèn)值0,無限等待,避免此自動機(jī)制,而用人工介入的方法進(jìn)行服務(wù)恢復(fù)。因?yàn)橄到y(tǒng)自動的、頻繁的SIGKILL將影響到整個(gè)TUXEDO系統(tǒng)的穩(wěn)定。
2.11 GRACE
2.11.1 參數(shù)出處
UBBCONFIG配置文件 -> SERVERS -> GRACE 。
2.11.2 時(shí)間單位
秒。
2.11.3 取值范圍
0-2147,483,647。
2.11.4 默認(rèn)取值
86400(24小時(shí))。
2.11.5 用途解釋
此時(shí)間參數(shù)與其他兩個(gè)參數(shù)緊密相關(guān)RESTART, MAXGEN。
關(guān)聯(lián)起來解釋就是,當(dāng)Server異常終止時(shí),如果RESTART=Y,那么此SERVER可立即自動重新啟動,這個(gè)重新啟動的次數(shù)被限制為在GRACE指定的時(shí)間間隔內(nèi),重啟不超過MAXGEN-1 次。
如果RESTART這個(gè)參數(shù)為N,其他的相關(guān)參數(shù)將都無效。
2.11.6 超時(shí)后果
此參數(shù)不僅僅是時(shí)間的限制,如果在GRACE時(shí)間段內(nèi),此SERVER重啟次數(shù)已經(jīng)達(dá)到MAXGEN-1,后續(xù)重啟將不能執(zhí)行。
2.11.7 設(shè)置考慮
此組參數(shù)設(shè)置的綜合目的是避免運(yùn)行Server無限的重啟,重啟次數(shù)說明了系統(tǒng)目前異常狀況的嚴(yán)重程度,如果在一定時(shí)間內(nèi),Server重啟次數(shù)達(dá)到了一定的數(shù)量,說明這個(gè)Server相關(guān)的資源已經(jīng)出現(xiàn)較嚴(yán)重的故障,需要人工進(jìn)行干預(yù)了。
另外,經(jīng)過調(diào)優(yōu)的生產(chǎn)系統(tǒng)是不需要自動重啟的,因此,RESTART這個(gè)參數(shù)更多是應(yīng)用在系統(tǒng)測試版本中,在正常運(yùn)行的生產(chǎn)系統(tǒng)中,應(yīng)該有不同參數(shù)設(shè)置,謹(jǐn)慎使用,因?yàn)檫^多的重啟將有可能嚴(yán)重影響Server端的整體穩(wěn)定性。
2.12 Transaction TimeOut
2.12.1 參數(shù)出處
tpbegin(timeout,0)。
2.12.2 時(shí)間單位
秒,且必須為SCANUINT的倍數(shù)。
2.12.3 取值范圍
大于等于0。
2.12.4 默認(rèn)取值
無,使用時(shí)必須明確指定。
2.12.5 用途解釋
交易時(shí)長,確定交易(transaction)的持續(xù)時(shí)間,如果超過此時(shí)間,系統(tǒng)將返回超時(shí)錯(cuò)誤。
分析其觸發(fā)條件,分兩種情況:
?。?) Server端發(fā)起交易,
對Client而言,因?yàn)镃lient不在交易范圍內(nèi),即使BLOCKTIME設(shè)置小于此參數(shù),起有效作用的仍然將是BLOCKTIME,而不是此參數(shù)。
?。?) Client端發(fā)起交易。
對Client而言,因?yàn)镃lient在交易范圍內(nèi),此時(shí),BLOCKTIME將失效,此參數(shù)取而代之。只要處理時(shí)間超過此參數(shù),將觸發(fā)此超時(shí),交易處理將隨時(shí)中斷。
2.12.6 超時(shí)后果
相關(guān)交易將被標(biāo)識為abort only。注意,僅僅是標(biāo)識為abort only,而不是系統(tǒng)自動執(zhí)行tpabort進(jìn)行交易恢復(fù)。隨后必須主動執(zhí)行tpabort,恢復(fù)交易,保障交易完整性。如果沒有執(zhí)行tpabort,系統(tǒng)將通過其他機(jī)制,恢復(fù)交易,保障交易完整性。
2.12.7 設(shè)置考慮
此參數(shù)的主要目的是將交易處理過程限制在合理的時(shí)間范圍內(nèi),如果確實(shí)是完成交易的條件不具備,系統(tǒng)也能夠作出反應(yīng),避免系統(tǒng)資源的長時(shí)間占用。因此,不管交易由Client還是由Server發(fā)起,此參數(shù)都要按照業(yè)務(wù)的實(shí)際狀況進(jìn)行設(shè)置。如果設(shè)置為0,就基本相當(dāng)于無限時(shí)長。(系統(tǒng)unsigned long數(shù)據(jù)類型的最大值)
2.13 TRANTIME
2.13.1 參數(shù)出處
UBBCONFIG配置文件 -> SERVICES -> TRANTIME/AUTOTRAN。
2.13.2 時(shí)間單位
秒,且必須為SCANUNIT的倍數(shù)。
2.13.3 取值范圍
0-2147,483,647。
2.13.4 默認(rèn)取值
30 。
2.13.5 用途解釋
此參數(shù)必須與AUTOTRAN配合使用,表示不需要調(diào)用tpbegin,就可自動發(fā)起的隱含交易(AUTOTRAN implicitly transactions)處理持續(xù)時(shí)長。其實(shí),起到與tpbegin(timeout,0)中的timeout相同的作用。
其實(shí),AUTOTRAN這個(gè)參數(shù)更為重要,其默認(rèn)值為N, 其作用描述如下:
(1) 請求發(fā)起方不在交易模式,AUTOTRAN=Y(jié),Service將自動發(fā)起一個(gè)交易,TRANTIME將起作用;
?。?) 請求發(fā)起方在交易模式,而且,其中的標(biāo)記參數(shù)(flags)不是TPNOTRAN,那么,無論AUTOTRAN如何,Service將自動加入請求方交易中,TRANTIME將不起作用;
(3) 請求發(fā)起方在交易模式,而且,其中的標(biāo)記參數(shù)(flags)是TPNOTRAN,如果AUTOTRAN=N,Service將自動加入請求方交易中,TRANTIME將不起作用;
?。?) 請求發(fā)起方在交易模式,而且,其中的標(biāo)記參數(shù)(flags)是TPNOTRAN,如果AUTOTRAN=Y(jié),Service將不加入請求方交易中,而是產(chǎn)生一個(gè)新的交易,TRANTIME將在新交易中起作用;
2.13.6 超時(shí)后果
與tpbegin(timeout,0)中的timeout相同。
2.13.7 設(shè)置考慮
與tpbegin(timeout,0)中的timeout相同。
2.14 ORACLE XA OPENINFO參數(shù):SESTM
2.14.1 參數(shù)出處
UBBCONFIG配置文件 -> GROUPS -> OPENINFO ->SESTM 。
2.14.2 時(shí)間單位
秒。
2.14.3 取值范圍
大于等于0,0表示無限時(shí)長。
2.14.4 默認(rèn)取值
無,使用時(shí)必須明確設(shè)置 。
2.14.5 用途解釋
會話靜默等待時(shí)長,即全局交易中,作為資源管理器(resource manager)已經(jīng)參與交易并完成相應(yīng)的數(shù)據(jù)操作的數(shù)據(jù)庫,等待全局交易中的其他參與方操作完成的時(shí)間長度。
舉例說明:
假設(shè)一個(gè)全局交易由以下幾個(gè)部分組成:
(1)tpbegin(T,0) ->
?。?)tpcall(S1) -> DB1 完成耗時(shí) T1;
?。?)tpcall(S2) -> DB2 完成耗時(shí) T2;
?。?)其他操作 耗時(shí) T3
?。?)tpcommit()
其中,tpcall(S1)訪問數(shù)據(jù)庫DB1, tpcall(S2)訪問數(shù)據(jù)庫DB2。
對DB1而言,如果T-T1> T2+T3 > SESTM1,則觸發(fā)超時(shí);
對DB2而言,如果T-T1-T2 > T3 > SESTM2,則觸發(fā)超時(shí);
由此可以看出,此參數(shù)的主要目的是對數(shù)據(jù)庫進(jìn)行資源保護(hù),避免在全局交易中,已經(jīng)完成任務(wù)的數(shù)據(jù)庫,為等待其他參與方耗費(fèi)過多的資源,畢竟ORACLE中并發(fā)全局交易的數(shù)量是很有限的。
2.14.6 超時(shí)后果
觸發(fā)此超時(shí)后,數(shù)據(jù)庫將自己主動回滾已經(jīng)完成的任務(wù),釋放全局交易資源。TUXEDO控制的全局交易進(jìn)行TPCOMMIT時(shí),如果總時(shí)間仍沒有超過Transaction TimeOut,那么TPCOMMIT將失敗,XALOG會記錄下ORACLE錯(cuò)誤:"ORA-24756: Transaction does not exist"。確實(shí)如此,拿上面的例子來說,等到最后TPCOMMIT的時(shí)候,DB1已經(jīng)主動回滾了所有的數(shù)據(jù),不難理解,對DB1而言,它好像根本沒有參加過這個(gè)全局交易,自然就會有這樣的錯(cuò)誤提示。
2.14.7 設(shè)置考慮
這個(gè)參數(shù)是從數(shù)據(jù)庫自我保護(hù)的角度設(shè)計(jì)的,對數(shù)據(jù)庫而言,是不得已的辦法。最好的措施還是TUXEDO能夠控制時(shí)間,趕在SESTM之前,進(jìn)行TPABORT,主動通知數(shù)據(jù)庫進(jìn)行數(shù)據(jù)回滾。
用一個(gè)簡單的比方:冬天,客人出門時(shí)沒有關(guān)門,SESTM時(shí)間后,客人還沒有回來,主人感覺到冷了,只好自己去關(guān)門,不管什么理由,這樣總是不太好。如果在SESTM時(shí)間內(nèi),客人能及時(shí)回來關(guān)門,主人就不會感覺那么差。
從前面的超時(shí)觸發(fā)分析,我們也能發(fā)現(xiàn),只要設(shè)置SESTM 能夠大于 TransactionTimeOut的話,就能夠盡量的不觸發(fā)此超時(shí)機(jī)制,達(dá)到較好的效果。
2.15 ORACLE XA OPENINFO參數(shù):SESWT
2.15.1 參數(shù)出處
UBBCONFIG配置文件 -> GROUPS -> OPENINFO -> SESWT。
2.15.2 時(shí)間單位
秒。
2.15.3 取值范圍
大于0。
2.15.4 默認(rèn)取值
60 。
2.15.5 用途解釋
會話繁忙等待時(shí)長,指全局交易中的一個(gè)交易分支(transaction branch)正在一個(gè)會話(session)中處理數(shù)據(jù)過程中,如果第二個(gè)會話也要對此交易分支進(jìn)行操作,那么第二個(gè)會話必須等待第一個(gè)會話完成,如果在等待SESWT后,第一個(gè)會話仍然沒有完成,那么第二個(gè)分支將觸發(fā)此超時(shí)。
舉例說明:
假設(shè)一個(gè)全局交易由以下幾個(gè)部分組成:
?。?)tpbegin(T,0) ->
?。?)tpcall(S1) -> DB1 完成數(shù)據(jù)操作耗時(shí) T1;
(3)tpcall(S2) -> DB2 完成數(shù)據(jù)操作耗時(shí) T2;
?。?)其他操作 耗時(shí) T3
?。?)tpcommit()
其中,tpcall(S1)訪問數(shù)據(jù)庫DB1, tpcall(S2)訪問數(shù)據(jù)庫DB2,任何操作失敗后,將調(diào)用tpabort。
假設(shè) T1+T2 > T > T1,也就是說,在成功執(zhí)行第二步tpcall(S1)后,應(yīng)用執(zhí)行到第三步tpcall(S2),在執(zhí)行過程中,將觸發(fā)TransactionTimeout,tpcall(S2)將返回錯(cuò)誤,應(yīng)用將立即調(diào)用tpabort進(jìn)行交易回滾,DB1的數(shù)據(jù)將立刻回滾;而DB2并不能中斷tpcall(S2)引起的數(shù)據(jù)操作,對于ORACLE DB2而言,tpcall(S2)引起的數(shù)據(jù)操作屬于第一個(gè)會話,而tpabort引起的數(shù)據(jù)庫回滾操作是通過XA接口,屬于第二個(gè)會話,所以,tpabort作用到DB2上,只有等待第一個(gè)會話完成,如果等待SESWT后,第一個(gè)會話仍然沒有完成,即SESTM
2.15.6 超時(shí)后果
系統(tǒng)將返回XA_RETRY錯(cuò)誤,提示TMS此操作不能完成,需再試一次。如果應(yīng)用程序?qū)Υ藳]有再次嘗試的話,仍以上例說明,DB2只能利用SESTM2,觸發(fā)超時(shí),自動回滾。
2.15.7 設(shè)置考慮
查閱ORACLE相關(guān)資源,發(fā)現(xiàn)oracal9.2與以前版本效果不同,以前的版本都是第二個(gè)會話在等待SESWT后,如果第一個(gè)會話操作仍然沒有結(jié)束,第二個(gè)會話能夠使第一個(gè)會話操作立即進(jìn)行有效的回滾,使第一個(gè)會話返回錯(cuò)誤:ORA-24761。
不難理解,兩者的區(qū)別是,打個(gè)簡單比方說,A正在用杯子喝水時(shí),B要A放下杯子,B等待SESWT后:
oracle9.2的做法很民主,A還沒有用完,通知B,A還在用杯子,不能放下,還想讓A放下杯子,可以,再來一次;也就是說,只要A在用,B就不能讓人家放下杯子,某種程度上,A代表了強(qiáng)權(quán)。
Oracle9.2之前版本的做法很粗暴,通知A不能使用這個(gè)杯子了,必須放下,因?yàn)锽讓你放下,而且已經(jīng)等很久了,某種程度上,B代表了強(qiáng)權(quán)。
因此,如果是ORACLE9.2后的版本,SESWT適當(dāng)放長一些,畢竟還是希望能夠等到能做事的時(shí)候,把想做的事情做了。如果是以前的版本,SESWT適當(dāng)放短一些,反正一定能等到,為什么不少等一會兒呢?
2.16 ORACLE sqlnet.expire_time
2.16.1 參數(shù)出處
$ORACLE_HOME/network/admin/sqlnet.ora -> expire_time 。
2.16.2 時(shí)間單位
分鐘。
2.16.3 取值范圍
大于0。
2.1*** 默認(rèn)取值
無 。
2.16.5 用途解釋 ⑾
死聯(lián)接檢測DCD(Dead Connection Detection)是 SQL*NetV2.1 和此版本以后的一個(gè)新特性, 當(dāng)它檢測到對方 c/s 或者s/s 聯(lián)接意外終止時(shí), 釋放相關(guān)占用的資源。
DCD 起初是專為客戶機(jī)沒有從會話中斷開聯(lián)接的情況下斷電的環(huán)境設(shè)計(jì)的。
DCD由服務(wù)端開始建立聯(lián)接。 這時(shí)候SQL*Net 從參數(shù)文件中讀取變量, 設(shè)置一個(gè)定時(shí)器定時(shí)產(chǎn)生信號。 這個(gè)時(shí)間間隔是sqlnet.ora文件中的SQLNET.EXPIRE_TIME提供的。
當(dāng)定時(shí)器設(shè)定的時(shí)間到了之后, 服務(wù)器上的SQL*Net 發(fā)送一個(gè)探測包到客戶端。(如果是數(shù)據(jù)庫聯(lián)接, 目的端的服務(wù)器發(fā)送探測包到另一端)。 探測包是由空的SQL*Net包組成, 不體現(xiàn)SQL*Net層任何數(shù)據(jù), 但會在下一層的網(wǎng)絡(luò)協(xié)議中產(chǎn)生數(shù)據(jù)流量。
如果客戶端的聯(lián)接仍然是活動的, 探測包被丟棄,計(jì)時(shí)裝置復(fù)位。 如果客戶端異常斷掉,服務(wù)器將收到由發(fā)送探測包的調(diào)用發(fā)出的錯(cuò)誤。
2.16.6 超時(shí)后果
服務(wù)器將收到由發(fā)送探測包的調(diào)用發(fā)出的錯(cuò)誤,SQL*Net 將會通知操作系統(tǒng)釋放聯(lián)接占用的資源。
需要說明的是, SQL*Net 2.1.x中 一個(gè)活動的孤兒進(jìn)程(active orphan process) ,如單獨(dú)的查詢進(jìn)程,在查詢完成之前不會被殺掉。 在SQL*Net 2.2中,孤兒進(jìn)程占用的資源將會被無條件釋放,不管查詢是否結(jié)束。
2.16.7 設(shè)置考慮
ORACLE 在NT操作系統(tǒng)上,此功能表現(xiàn)很差,檢測出的無效聯(lián)接(dead connection)不能被盡快釋放,而必須等到數(shù)據(jù)庫重新啟動時(shí)才釋放。SQL*Net v2.3以后版本改善了以上問題。
此功能只是服務(wù)器的特性,如果不設(shè)置此參數(shù),此功能將不啟動。按照ORACLE的建議,對大多數(shù)應(yīng)用來說,設(shè)置10分鐘較合適,其實(shí)關(guān)鍵還是分析應(yīng)用系統(tǒng)的實(shí)際情況。
同時(shí),不難理解,作為一個(gè)數(shù)據(jù)庫自我管理的機(jī)制,也是要占用數(shù)據(jù)庫資源和網(wǎng)絡(luò)資源的,太頻繁的探測同樣會降低系統(tǒng)和網(wǎng)絡(luò)的性能。在低速網(wǎng)絡(luò)上,設(shè)置此參數(shù),就需更為慎重。
客戶端不需要設(shè)置此參數(shù)。
2.17 ORACLE distributed_lock_timeout
2.17.1 參數(shù)出處
ORACLE初始參數(shù)文件:init.ora -> distributed_lock_timeout。
2.17.2 時(shí)間單位
秒。
2.17.3 取值范圍
大于0。
2.17.4 默認(rèn)取值
60 。
2.17.5 用途解釋
分布式事務(wù)鎖等待超時(shí)(distributed transaction waiting for lock),指第二個(gè)事務(wù)處理需要的數(shù)據(jù)庫資源,正被第一個(gè)分布式事務(wù)占用而鎖定,那么,第二個(gè)事務(wù)將等待第一個(gè)分布式事務(wù)釋放此資源,等待distributed_lock_timeout時(shí)間后,如果第一分布式事務(wù)仍然沒有釋放此資源,第二個(gè)事務(wù)觸發(fā)此超時(shí)。
2.17.6 超時(shí)后果
如果資源被第一個(gè)事務(wù)正常使用鎖定,ORACLE回滾第二個(gè)事務(wù),并返回錯(cuò)誤:"ORA-02049: time-out: distributed transaction waiting for lock "。
如果第一個(gè)事務(wù)處理完成,資源釋放后,再嘗試第二個(gè)事務(wù),就會成功。如果第二個(gè)事務(wù)不能等待資源自動釋放,那么可以采用處理數(shù)據(jù)庫死鎖(deadlock)的措施,人工介入,清除第一個(gè)事務(wù),但一般不建議采用這種方式,因?yàn)榈谝粋€(gè)事務(wù)一般會正常結(jié)束的。
如果資源被第一個(gè)事務(wù)因?yàn)樘幱诓淮_定分布事務(wù)狀態(tài)(in-doubt distributed transaction)而鎖定,ORACLE回滾第二個(gè)事務(wù),并返回錯(cuò)誤:"ORA-01591: lock held by in-doubt distributed transaction identifier "。
這種錯(cuò)誤遇到的可能性較小,一般只有在分布事務(wù)的關(guān)鍵提交階段出現(xiàn)網(wǎng)絡(luò)、系統(tǒng)故障,才可能出現(xiàn)此故障,而且,當(dāng)網(wǎng)絡(luò)、系統(tǒng)故障恢復(fù)后,ORACLE一般可以自己解決此問題,不需要人工介入。如果一定要人工介入,可以查閱ORACLE專門的手冊。
2.17.7 設(shè)置考慮
出現(xiàn)這樣的超時(shí),是因?yàn)樘囟〝?shù)據(jù)庫資源的使用碰撞,要分析應(yīng)用系統(tǒng)的業(yè)務(wù)特點(diǎn),確定碰撞可能發(fā)生的條件,在此條件下,資源可能被先來者鎖定多長時(shí)間(T1),后來者又能夠等多長時(shí)間(T2),再來設(shè)置此參數(shù)(T)的大小。如果在大多數(shù)情況下,T1 < T2, 那么就設(shè)置T1 < T < T2;反之,大多數(shù)情況下,T1 > T2,那么,就設(shè)置T < T2。
因此,不分析業(yè)務(wù)特點(diǎn),一味的增大和減小是不恰當(dāng)?shù)摹?/p>
2.18 ORACLE Max_commit_propagation_delay
2.18.1 參數(shù)出處
ORACLE初始文件:init.ora -> Max_commit_propagation_delay。
2.18.2 時(shí)間單位
0.01秒。
2.18.3 取值范圍
0 ~ 90000。
2.18.4 默認(rèn)取值
700 。
2.18.5 用途解釋
最大提交傳播時(shí)延(MAX_COMMIT_PROPAGATION_DELAY,簡稱MCPD),在ORACLE RAC(或OPS)環(huán)境中才使用,表示在RAC系統(tǒng)中,一個(gè)instance系統(tǒng)提交產(chǎn)生的最新系統(tǒng)改變碼(SCN),能夠以多快的速度反應(yīng)到另一個(gè)instance中。
舉例說明,RAC系統(tǒng),有A,B兩個(gè)實(shí)例(instance),A、B本地系統(tǒng)改變碼為SCN1,A更新數(shù)據(jù)DATA1提交, LGWR操作完成后,A本地系統(tǒng)改變碼為SCN2,經(jīng)過不大于MAX_COMMIT_PROPAGATION_DELAY時(shí)間后,B系統(tǒng)本地改變碼才變?yōu)镾CN2。
2.18.6 超時(shí)后果
Global Cache Services 將刷新RAC中的SCN。不管SCN是否及時(shí)刷新,后續(xù)的數(shù)據(jù)查詢都不會因此產(chǎn)生數(shù)據(jù)庫錯(cuò)誤。但,在此時(shí)間內(nèi),有可能查詢結(jié)果不是最新數(shù)據(jù),產(chǎn)生讀一致性(read consistency)問題。
2.18.7 設(shè)置考慮
RAC環(huán)境中的所有實(shí)例,此參數(shù)值必須相同。
ORACLE8i后,建議常用的兩個(gè)值是0和700(默認(rèn)),其他數(shù)值皆不建議。其實(shí),這兩個(gè)數(shù)值就代表了RAC環(huán)境中,兩種SCN 產(chǎn)生機(jī)制:
Lamport Scheme和 Broadcast on Commit scheme。
設(shè)置為默認(rèn)值700,表示采用Lamport Scheme,SCN改變不會完全同步,同步將在 7秒鐘內(nèi)完成,而不是總等待7秒鐘后才完成。如果系統(tǒng)比較空閑,同步可能在0.5秒(甚至更短時(shí)間)內(nèi)完成;不管系統(tǒng)多繁忙,同步時(shí)間也不可能超過7秒。不難理解,采用此模式,整個(gè)RAC系統(tǒng)的運(yùn)行效率較高。
設(shè)置為0,表示采用Broadcast on Commit scheme,SCN改變完全同步。每當(dāng)commit時(shí)(即LGWR 寫redo log時(shí)):
?。?LGWR發(fā)送消息更新全局SCN(global SCN),
?。?LGWR 發(fā)送消息給每個(gè)活動的實(shí)例更新其本地SCN(local SCN)。
有資料說,只要MCPD < 700,系統(tǒng)將采用Broadcast on Commit scheme。
Lamport Scheme能夠適應(yīng)絕大部分應(yīng)用的要求,只有個(gè)別實(shí)時(shí)性特別高的業(yè)務(wù),才需要Broadcast on Commit scheme。通過分析,不難理解,Broadcast on Commit scheme將需要更多的系統(tǒng)資源。
3 總結(jié)
以上所有時(shí)間參數(shù),都是tuxedo系統(tǒng)或ORACLE數(shù)據(jù)庫系統(tǒng)提供的時(shí)間控制機(jī)制,更多的是從維護(hù)本系統(tǒng)自身安全的角度,建立起相互之間溝通的規(guī)則。在Client 端,中間件服務(wù)器,數(shù)據(jù)服務(wù)器這相互聯(lián)系的三者之間,用一個(gè)簡單的比方,就是先保證自己盡量不給相關(guān)人帶來麻煩;一旦相關(guān)人出了麻煩,自己能夠自我保障,不受別人干擾。
這些時(shí)間參數(shù)還有的一個(gè)共性的特點(diǎn)就是"不精確",如果業(yè)務(wù)需要要精確到1秒,則必須依靠業(yè)務(wù)程序中更精確的時(shí)間編程。
總之,要保障整個(gè)業(yè)務(wù)系統(tǒng)的有效性和健壯性,必須了解都有哪些時(shí)間參數(shù)?都表示什么意思?都起哪些作用?自己的業(yè)務(wù)應(yīng)用對時(shí)間要求是怎樣的?這些參數(shù)該如何配置才能滿足應(yīng)用的要求?希望本文能夠在以上方面給大家?guī)硪稽c(diǎn)方便。
4 后記
自2002年真正在項(xiàng)目中利用TUXEDO起,就發(fā)現(xiàn)已有資料在時(shí)間參數(shù)解釋方面的缺憾,那時(shí),就有寫這樣一個(gè)專題的打算,開始收集這方面的資料。由于后來工作內(nèi)容的變化,也就沒有精力再作整理,但心里一直惦記著這件事情。直到前些天知道了BEA的這個(gè)活動,再到網(wǎng)絡(luò)上搜集資料,發(fā)現(xiàn)已經(jīng)有了一些類似的資料,但感覺仍然不夠完整,不夠透徹,因此,我認(rèn)為整理這樣一個(gè)專題資料,還是有必要的,便下決心借此機(jī)會做完這件事情。經(jīng)過近十天的查閱、整理,終于完成,算是了我多年夙愿。
文中的參數(shù),我僅僅使用過其中的12個(gè),其他未用參數(shù),主要是靠查閱資料和邏輯分析,根據(jù)我自己的理解進(jìn)行解釋,再加上時(shí)間倉促,或遺漏、不妥之處,敬請指正,讓我們一起來使此《功略》更準(zhǔn)確、更全面,讓更多的人從中受益。
5 參考文獻(xiàn)
http://e-docs.bea.com BEA TUXEDO RELEASE 7.1 。
http://dev2dev.bea.com.cn/techdoc/tuxedo/20030230.html 《Tuxedo 中關(guān)于時(shí)間的參數(shù)的說明》作者:不詳 。
《ORACLE8i Reference》。
《ORACLE9i Reference》。
《ORACLE8i Parallel Server Concepts and Administration》。
《ORACLE8i Application Developers Guide - Fundamentals》。
http://metalink.oracle.com 相關(guān)問題解決資料。
http://www.chinaunix.net 《DCD死聯(lián)接檢測》作者:yukaikai
注:文章中標(biāo)注⑴~⑽涉及的內(nèi)容,引自參考文獻(xiàn)-2 ,標(biāo)注⑾涉及的內(nèi)容,引自參考文獻(xiàn)-8 。
在沒有負(fù)載均衡的情況下,是由一個(gè)server(可能包含一個(gè)或多個(gè)service)來處理客戶端對其中service的請求,所有的請求首先放入這個(gè)server的隊(duì)列里面,然后server逐個(gè)取出處理。在UNIX系統(tǒng)上,TUXEDO較多的使用了隊(duì)列,并且也用到了共享內(nèi)存和信號量,相關(guān)的UNIX系統(tǒng)參數(shù)會影響到系統(tǒng)的性能,但這個(gè)不在本文討論范圍之內(nèi),這里假設(shè)已經(jīng)調(diào)到了合適的范圍,具體請查閱TUXEDO關(guān)于IPC的文檔。
現(xiàn)以一個(gè)帳單處理的server為例,負(fù)載均衡前server的ubb配置為:
billpay SRVGRP=GROUP1 SRVID=1
在單個(gè)server不能滿足性能要求的情況下,就考慮采用TUXEDO的負(fù)載均衡方法。
方法一是直接將相關(guān)server啟多份,將上面的配置改為:
billpay SRVGRP=GROUP1 SRVID=1 MIN = 5 MAX = 10
這樣tmboot的時(shí)候,就會有MIN = 5個(gè)billpay啟動,類似下面的情況:
billpay 00001.00001 GROUP1 1 0 0 ( IDLE )
billpay 00001.00002 GROUP1 2 0 0 ( IDLE )
(依此類推,共5個(gè))
其中第二列是該server的隊(duì)列名,"."前面是GRPNO,后面是SRVID,每個(gè)server有自己的隊(duì)列。相關(guān)的另一個(gè)參數(shù)就是在ubb的*RESOURCES段的LDBAL,表示是否啟動Load Balancing,默認(rèn)是"N"(不啟動),你可以通過設(shè)置成"Y"來啟動。這里需要注意的是,為"N"的時(shí)候并不表示多個(gè)server不能分擔(dān)負(fù)載。主要的差別是為"Y"時(shí),TUXEDO在接收到請求時(shí)會按照它的負(fù)載均衡的算法來找到合適的server來處理,而設(shè)置成"N"時(shí),總是由第一個(gè)可用的server來處理。通過這種方法可以讓多個(gè)server來處理大量并發(fā)的請求,就達(dá)到了改善性能的目的。
方法二是采用MSSQ(Multi Server, Single Queue),顧名思義,就是有多份server,但是只有一個(gè)隊(duì)列(請求隊(duì)列)。具體的配置是:
billpay SRVGRP=GROUP1 SRVID=1 MIN = 5 MAX = 10
RQADDR=" billpay" REPLYQ=Y
啟動后的情況如下:
billpay billpay GROUP1 1 0 0 ( IDLE )
billpay billpay GROUP1 2 0 0 ( IDLE )
(依此類推,共5個(gè))
我們發(fā)現(xiàn)幾個(gè)billpay server都關(guān)聯(lián)相同的名為billpay的隊(duì)列,這就是所謂的Single Queue。
與直接多server相比,多了兩個(gè)參數(shù),RQADDR是這多個(gè)server共用的隊(duì)列名,是一種邏輯名,可以自己命名,不和別的沖突就可以,REPLYQ是標(biāo)示是否設(shè)置返回隊(duì)列,在使用MSSQ的時(shí)候是強(qiáng)烈建議設(shè)置,因?yàn)檫@樣可以將請求和返回分開,避免多個(gè)server共用隊(duì)列時(shí)造成混亂。相關(guān)的其它參數(shù)這里沒有詳細(xì)列出。
到底兩種方式和沒有負(fù)載均衡時(shí)有什么不同,后面將提供相關(guān)的測試結(jié)果。先分析一下兩種方法。方法一有多個(gè)隊(duì)列可以容納請求,但是這些大量的請求怎樣放入這些隊(duì)列必定有一定的策略,而且根據(jù)LDBAL的設(shè)置會不同,但是這個(gè)策略本身的運(yùn)算也是一種消耗,因?yàn)槊總€(gè)請求都面臨著這個(gè)選擇。因?yàn)檫@種情況下每個(gè)隊(duì)列是和server對應(yīng)的,所以隊(duì)列的選擇就意味著選擇了相應(yīng)的那個(gè)server,這樣大量的請求就被分流。雖然有選擇的消耗,但是額外的好處也是顯而易見的,那就是有多個(gè)queue可用,有效避免了請求并發(fā)量很大時(shí)隊(duì)列的溢出,這種情況在實(shí)際的壓力測試中發(fā)生過。使用方法二時(shí),放入隊(duì)列時(shí)不用做選擇,然后每個(gè)server的任務(wù)就是從隊(duì)列取出請求去處理,考慮到多個(gè)server并發(fā)取隊(duì)列,所以用MSSQ時(shí)其server的數(shù)目不宜太多,官方文檔建議2-12。而且在這種情況下,建議不要設(shè)置LDBAL=Y,因?yàn)镸SSQ本身就是一種基于single queue的負(fù)載均衡的方法,這時(shí)再使用系統(tǒng)的策略已經(jīng)沒有意義。這種方法也有一個(gè)問題,如果相對于請求數(shù)來說,處理得不夠快,就比第一種方法更容易造成隊(duì)列溢出。
因?yàn)槲覀儫o法知道TUXEDO一些具體的算法和策略,那就用一些具體的測試來比較吧。筆者在一個(gè)和實(shí)際生產(chǎn)系統(tǒng)配置相同的UNIX+ORACLE+TUXEDO8.0系統(tǒng)上做了一下試驗(yàn),被測服務(wù)是一個(gè)帳單查詢服務(wù),每次根據(jù)一批ID從數(shù)據(jù)庫查詢出具體的帳單,由于都是實(shí)際數(shù)據(jù)和實(shí)際使用的服務(wù),有一定的說明力,但是也不排除一些情況造成的誤差。以下是測試的一些結(jié)果,每個(gè)server的實(shí)際運(yùn)行份數(shù)都是10。
一:客戶端數(shù)目為1,循環(huán)調(diào)用100次。
1. 方法一,LDBAL = Y or N。結(jié)果發(fā)現(xiàn)所有的請求都由其中的一個(gè)server處理,其它全部空閑。在此基礎(chǔ)上再進(jìn)行兩次循環(huán)調(diào)用,結(jié)果還是一樣。
2. 用方法二,LDBAL = Y or N。其中兩次測試的情況是:
<1>19,19,2,2,1,18,18,1,1,19
<2>23,8,23,23,23,(其它空閑)
以上數(shù)據(jù)說明了兩種方式的調(diào)度策略是不一樣的,在單客戶端循環(huán)的情況下方法二更合適。
二:客戶端數(shù)目50,每個(gè)循環(huán)80次,統(tǒng)計(jì)總的執(zhí)行時(shí)間。
1. 用single server。兩次測試的處理時(shí)間分別是219s和196s。
2. LDBAL = Y 方法一:三次測試時(shí)間為:63s,79s,69s
3. LDBAL = N 方法一:三次測試時(shí)間為:74s,79s,85s
4. LDBAL = Y 方法二:三次測試時(shí)間為:74s,73s,77s
5. LDBAL = N 方法二:三次測試時(shí)間為:78s,76s,75s
通過以上數(shù)據(jù)可以看出不管用那種方法,使用負(fù)載均衡相比單個(gè)server都可以在大量請求并發(fā)時(shí)得到更好的性能。但是同時(shí)也發(fā)現(xiàn)后四種情況的總時(shí)間差別不大,考慮一些實(shí)際的誤差,很難斷定哪種更好。
通過前面的分析,并查閱相關(guān)的文檔,建議采用的是兩種方式:多個(gè)server,不用MSSQ,設(shè)置LDBAL = Y;用MSSQ,設(shè)置LDBAL = N。當(dāng)然,在使用TUXEDO的應(yīng)用系統(tǒng)中,不能絕對的說哪一種方式更好,只能是根據(jù)具體的情況來分析,并通過實(shí)際的壓力測試來進(jìn)行選擇,而且這個(gè)和具體server的特點(diǎn)也是有關(guān)的。
以上是一些個(gè)人分析和測試的結(jié)果,算是寫出來和大家探討,也希望大家提出自己的看法并討論。
一、中間件技術(shù)在系統(tǒng)設(shè)計(jì)規(guī)劃方面的經(jīng)驗(yàn)總結(jié)
1.1、中間件應(yīng)用架構(gòu)的選擇
這種架構(gòu)選擇的焦點(diǎn)就是業(yè)務(wù)邏輯到底是放在前臺應(yīng)用中還是放在后臺中間件應(yīng)用中。其實(shí),引入中間件平臺的原因之一就是業(yè)務(wù)邏輯的集中管理,出現(xiàn)這種爭論的原因主要是開發(fā)商對這種業(yè)務(wù)邏輯集中的理解不深,在應(yīng)用設(shè)計(jì)的過程中仍然沒有擺脫以前兩層結(jié)構(gòu)的影響,再加上因?yàn)闃I(yè)務(wù)邏輯集中會增加程序開發(fā)量,才出現(xiàn)了這種情況。我們認(rèn)為,把業(yè)務(wù)邏輯集中在中間件服務(wù)器上不僅對于業(yè)務(wù)邏輯的集中管理有好處,而且對于系統(tǒng)的后期運(yùn)行維護(hù)、軟件的升級管理都有著明顯的優(yōu)勢。當(dāng)然,在開發(fā)的工作量方面,業(yè)務(wù)邏輯集中時(shí)工作量大很多。
1.2、中間件服務(wù)分布的設(shè)計(jì)和優(yōu)化原則
在Tuxedo中,Server可以理解成為Unix的一個(gè)進(jìn)程,Service可以理解成為應(yīng)用進(jìn)程Server中的一個(gè)函數(shù)。用戶可以任意劃分Server和Service:既可以把所有的Service放在一個(gè)單一的Server中,也可以采用“一個(gè)Service一個(gè)Server”的方式。Tuxedo對此沒有任何限制。
中間件應(yīng)用的性能直接影響到營業(yè)前臺服務(wù)的穩(wěn)定性和連續(xù)性,而影響中間件應(yīng)用性能的因素除了硬件資源的保證、數(shù)據(jù)庫響應(yīng)時(shí)間、中間件應(yīng)用軟件本身的質(zhì)量之外,中間件應(yīng)用服務(wù)的分布也起著至關(guān)重要的作用。我們有著這樣的一個(gè)例子,在前臺進(jìn)入收費(fèi)界面的時(shí)候,應(yīng)用程序需要調(diào)用一個(gè)SERVICE名字叫A,A分布在一個(gè)叫SA的server中,而SA中又包含著很多其他的在線統(tǒng)計(jì)的SERVICE B,結(jié)果造成了SA響應(yīng)B調(diào)用的時(shí)候執(zhí)行時(shí)間比較長,所有的SA都在執(zhí)行SERVICE B ,前臺請求SERVICE A得不到響應(yīng),收費(fèi)的界面怎么都進(jìn)不去,從而導(dǎo)致前臺收費(fèi)業(yè)務(wù)中斷。這就是個(gè)典型的因?yàn)榉?wù)分布不當(dāng)造成的系統(tǒng)故障。
我們在系統(tǒng)規(guī)劃設(shè)計(jì)過程中遵循的一個(gè)最基本原則就是盡量將“類似的Service”捆綁在一個(gè)Server之內(nèi)。所謂“類似的Service”是指這些函數(shù)有相似的大小、執(zhí)行時(shí)間、復(fù)雜度或者功能。我們來考慮一個(gè)極端的例子:假設(shè)一個(gè)Service A是完成非常簡單工作的,它的平均執(zhí)行時(shí)間是100毫秒。另一個(gè)Service B進(jìn)行數(shù)據(jù)庫的查詢,它的執(zhí)行時(shí)間可能長達(dá)20秒。如果將這兩個(gè)Service捆綁在一起使用,就會出現(xiàn)非常嚴(yán)重的后果。大家知道,操作系統(tǒng)的基本調(diào)度單位是進(jìn)程。在一個(gè)進(jìn)程中的Service執(zhí)行是串行的。Tuxedo把發(fā)往同一個(gè)Server的請求交易包放在同一個(gè)消息隊(duì)列中。當(dāng)Service B在執(zhí)行的時(shí)候,Service A的請求包必須在隊(duì)列里面等待20秒以上才可能被執(zhí)行,雖然它的執(zhí)行時(shí)間僅僅100毫秒。這顯然是不能容忍和應(yīng)該避免的。
實(shí)際上,用戶在設(shè)計(jì)和開發(fā)應(yīng)用程序的時(shí)候,并不能完全估計(jì)出每個(gè)Service的執(zhí)行時(shí)間和頻度。所以對Server和Service的劃分優(yōu)化是在應(yīng)用程序開發(fā)完畢后進(jìn)行調(diào)整的。調(diào)整的依據(jù)就是在系統(tǒng)運(yùn)行的時(shí)候記錄每個(gè)Service的執(zhí)行時(shí)間和頻度,然后根據(jù)這些數(shù)據(jù)來進(jìn)行優(yōu)化調(diào)整。下面就是我們在實(shí)際當(dāng)中獲得經(jīng)驗(yàn)的一些系統(tǒng)總結(jié)。
1、 區(qū)分Service的不同類型:是業(yè)務(wù)操作還是簡單的數(shù)據(jù)訪問
在中間件應(yīng)用中的Service可以進(jìn)一步細(xì)分成負(fù)責(zé)完成業(yè)務(wù)操作和負(fù)責(zé)數(shù)據(jù)訪問的兩種類型。在設(shè)計(jì)的時(shí)候,最好把這兩種不同類型的Service區(qū)別出來。所謂完成業(yè)務(wù)操作的類型其實(shí)就是進(jìn)行數(shù)據(jù)修改的操作,負(fù)責(zé)數(shù)據(jù)訪問的類型其實(shí)就是進(jìn)行數(shù)據(jù)查詢的操作。但是在實(shí)際的系統(tǒng)運(yùn)行過程中,凡是涉及到數(shù)據(jù)修改的操作過程中必然會有數(shù)據(jù)查詢的操作,這種類型的操作也應(yīng)該規(guī)整到第1種類型中去。
2、 請求/響應(yīng)類型的Service要和會話Service分開在不同的Server中
在Tuxedo中,一個(gè)Server要么支持請求/響應(yīng)類型類型的Service,要么支持會話方式的Service。會話方式和請求/響應(yīng)方式是兩種互斥的通訊方式。請求/響應(yīng)方式效率比較高,是使用最頻繁的通訊類型。Tpcall/tpacall/tpforward都是這種類型的函數(shù)。會話方式適合大量的數(shù)據(jù)傳輸,但是它的代價(jià)是效率的下降。所以這兩種類型的Service要分開放在不同的Server里面。
3、 執(zhí)行時(shí)間相似的Service放在同一個(gè)Server里面
在Tuxedo應(yīng)用環(huán)境中,可能有成百上千的Service,這些Service的執(zhí)行時(shí)間顯然是不同的。對于單線程的Server來說,雖然它可能有多個(gè)Service,但是這些Service的執(zhí)行是串行的。如果某個(gè)Server擁有兩個(gè)Service,A和B。A的執(zhí)行時(shí)間是100ms,B的執(zhí)行時(shí)間是1000ms,也就是說執(zhí)行一次B的時(shí)間可以執(zhí)行十次A。那么當(dāng)B在執(zhí)行的時(shí)候,可能會有十個(gè)A在隊(duì)列里面等待。這種情況會急劇降低該Server處理Service的吞吐率。因此很自然的一個(gè)原則是把執(zhí)行時(shí)間相似的Service放在同一個(gè)Server里面。
4、 具有相同執(zhí)行頻度的Service放在同一個(gè)Server里面
在一個(gè)典型的Tuxedo應(yīng)用系統(tǒng)中,并不是所有的Service的執(zhí)行頻率都是相同的??赡芤恍㏒ervice被頻繁的執(zhí)行,而另外一些Service只是偶爾才被執(zhí)行幾次。把這些SERVICE分開可以避免偶爾調(diào)用的SERVICE堵塞頻繁調(diào)用的SERVICE。
5、 避免死鎖的情況發(fā)生
在Tuxedo中的死鎖情況有兩種,第一種是一個(gè)Server中的Service A去調(diào)用同在一個(gè)Server中的Service B。這種死鎖發(fā)生的原因是,對于單線程的Server來說,它其中的Service是串行執(zhí)行的。Service A去調(diào)用Service B的時(shí)候,Service A還沒有執(zhí)行完,它等待Service B的返回結(jié)果。 但是Service B不能執(zhí)行,因?yàn)樵揝erver還處于執(zhí)行Service A的狀態(tài)。最終導(dǎo)致Service A超時(shí)而出錯(cuò)。
第二種情況是兩個(gè)Server中的Service互相調(diào)用。例如Server1和Server2,Server1中的Service A去調(diào)用Server2中的Service X。同時(shí)Server2中的Service Y去調(diào)用Server1中的Service B。這種情況發(fā)生的死鎖和第一種情況非常類似,都是因?yàn)檫M(jìn)程只能串行實(shí)行Service導(dǎo)致的。
這兩種死鎖情況在應(yīng)用設(shè)計(jì)時(shí)特別要注意避免。第一種情況是比較容易察覺的,但是第二種情況就不大容易察覺。
1.3、中間件系統(tǒng)應(yīng)用平臺FAILOVER方式的選擇在真實(shí)的生產(chǎn)運(yùn)行環(huán)境中,運(yùn)行平臺的failover是一個(gè)必須考慮的問題。Tuxedo平臺上的實(shí)現(xiàn)failover機(jī)制基本上有兩種,一種是利用tuxedo自己的failover機(jī)制配合前臺配兩個(gè)WSNADDR地址來實(shí)現(xiàn)failover。一種是利用雙機(jī)軟件來實(shí)現(xiàn)。
第一種方式是指使兩臺的中間件服務(wù)器處于MP工作模式下,在每一臺都啟動WSL進(jìn)程,然后在中間件前臺配置兩個(gè)ip地址。通過自己實(shí)驗(yàn)發(fā)現(xiàn)利用tuxedo自己的failover機(jī)制只有如下好處即不需要額外的操作系統(tǒng)和軟件的支持,但是其缺點(diǎn)確很多,主要缺點(diǎn)如下:
1、兩臺中間件平臺的MASTER切換必須要手工完成,無法自動完成。
2、前臺配置的兩個(gè)WSNADDR地址,如果第一個(gè)地址失敗,要重新連接到第二個(gè)地址需要很長的時(shí)間,并且在每次服務(wù)調(diào)用時(shí)都要等待同樣的時(shí)間。
通過雙機(jī)軟件來實(shí)現(xiàn)FAILOVER是指兩臺中間件服務(wù)器都配置在SHP模式下,然后利用雙機(jī)軟件的ip切換功能來實(shí)現(xiàn)failover。這種方法需要在各自的配置文件中加入另外一臺主機(jī)的WSL的信息,在另外一臺主機(jī)故障時(shí),通過雙機(jī)軟件進(jìn)行IP切換,再通過雙機(jī)切換腳本將這臺主機(jī)的備用WSL啟動即可。采用這種方式有以下優(yōu)點(diǎn)
1、機(jī)器切換自動完成,不需要人工干預(yù)。
2、前臺業(yè)務(wù)不受影響,能保證業(yè)務(wù)開展的連續(xù)性。
缺點(diǎn)主要有
1、在正常情況下,每一臺主機(jī)的啟動中間件時(shí),備用的WSL服務(wù)會啟動失敗,不過這不影響正常使用,備用的WSL只在另外一臺主機(jī)故障后才起作用。
2、需要額外的雙機(jī)配置和腳本配置工作。
經(jīng)過這些比較,我們選定了采用雙機(jī)軟件的方案實(shí)現(xiàn)了中間件的failover機(jī)制。在以后的運(yùn)行維護(hù)過程中起到了好的效果。
1.4、中間件與數(shù)據(jù)庫的連接方式的選擇在TUXEDO中間件應(yīng)用中連接數(shù)據(jù)庫的方式有兩種,一種為通過XA方式連接數(shù)據(jù)庫,另外一種是在應(yīng)用程序中自己連接數(shù)據(jù)庫。
通過XA方式連接數(shù)據(jù)庫是指利用關(guān)系型數(shù)據(jù)庫的XA接口,在tuxedo的配置文件中的OPENINFO段中加入連接信息,然后在server程序的初始化代碼的中調(diào)用中tp_open(或xa_open),當(dāng)SERVER啟動時(shí)進(jìn)行數(shù)據(jù)庫連接。
通過應(yīng)用程序直接連接數(shù)據(jù)庫,數(shù)據(jù)庫的連接操作不一定是在SERVER啟動時(shí)進(jìn)行的。
這兩種方式的連接在BOSS系統(tǒng)中都會用到,其中的區(qū)別主要就在于如果業(yè)務(wù)操作的事務(wù)為分布式事務(wù)時(shí),則必須要用XA方式。詳細(xì)比較如下:
1、通過XA連接的方式可以實(shí)現(xiàn)分布式事務(wù),即能夠保證事務(wù)在不同數(shù)據(jù)庫中的一致性。但是正是因?yàn)槿绱耍鼘χ虚g件系統(tǒng)和數(shù)據(jù)庫系統(tǒng)都有額外的開銷,有時(shí)候這種開銷甚至?xí)绊懴到y(tǒng)的性能。
2、通過應(yīng)用程序直連數(shù)據(jù)庫的方法不能夠?qū)崿F(xiàn)分布式事務(wù),但是同時(shí)也因此減少了對系統(tǒng)的壓力。
綜上,選擇數(shù)據(jù)庫的連接方式對整個(gè)系統(tǒng)的性能影響也是至關(guān)重要的,我們有個(gè)原則,凡是在不涉及到分布式事務(wù)的地方就不用XA連接。過多的依賴了XA接口,會給系統(tǒng)帶來了許多額外的負(fù)擔(dān)和壓力,也會造成許多額外的故障。
二、中間件技術(shù)在系統(tǒng)維護(hù)方面的經(jīng)驗(yàn)總結(jié)在中間件的日常維護(hù)中,我們了解了一些TUXEDO的基本知識,摸索了一套行之有效的故障排除方法,積累了一些常見故障的排除經(jīng)驗(yàn),現(xiàn)在與大家介紹如下:
2.1、LICENSE數(shù)的問題tuxedo的license由文本文件lic.txt來控制,位于udataobj目錄下,分為SDK/RTK兩種,兩種LICENSE不能合并使用。它控制的是并發(fā)用戶數(shù)并且有10%的冗余,這里的并發(fā)用戶數(shù)是指在某一時(shí)刻前臺程序已經(jīng)發(fā)起tpinit還沒有作tpterm的連接數(shù),所以在tuxedo中間件的使用中存在著長連接和短連接的問題。長連接是指tpinit后就開始一系列的服務(wù)調(diào)用,只在系統(tǒng)重啟或系統(tǒng)非??臻e的時(shí)候才做tpterm,而短連接是指每次服務(wù)調(diào)用前作tpinit,調(diào)用結(jié)束后立即作tpterm調(diào)用。因?yàn)槎踢B接下的服務(wù)調(diào)用需要額外的連接時(shí)間消耗,這對系統(tǒng)響應(yīng)時(shí)間會有影響,而長連接又會占用系統(tǒng)的并發(fā)用戶數(shù)。所以在系統(tǒng)設(shè)計(jì)時(shí)需要針對不同的應(yīng)用情況做出不同的設(shè)計(jì),比如針對接口類型的應(yīng)用因?yàn)榉?wù)調(diào)用比較頻繁,進(jìn)行連接的時(shí)間就會占比較大的比重,這時(shí)就需要使用長連接,而對于前臺應(yīng)用類型的應(yīng)用,連接過程的時(shí)間對于業(yè)務(wù)操作的時(shí)間來說是可以忽略的,這時(shí)就要用短連接來節(jié)約license資源。
2.2、客戶端連接的問題當(dāng)客戶端無法連接中間件時(shí),我們需要確認(rèn)的是
1、 客戶端的WSNADDR是否設(shè)置或是否設(shè)置正確。
2、 系統(tǒng)配置文件中的MAXWSCLIENTS和MAXACCESS是否正確設(shè)置。
3、 WSL是否啟動,WSH的個(gè)數(shù)是否足夠。
4、 是否有防火墻,如果有防火墻存在,則需要在WSL的配置中作相應(yīng)的地址映射和端口指定。
5、 操作系統(tǒng)是否有足夠的SCOKET資源使用。
解決了這些問題后,一般就可以解決客戶端連接不上的問題了。
在TUXEDO中,參數(shù)TMTRACE對故障的定位和排除很有作用,它是一個(gè)環(huán)境境變量。我們一般在系統(tǒng)監(jiān)控的工作終端上將此參數(shù)設(shè)置為on,在前臺報(bào)系統(tǒng)故障的時(shí)候,我們直接進(jìn)入故障模塊將故障重現(xiàn),然后在終端機(jī)器的c:\或者tuxedo的安裝目錄下打開一個(gè)ULOG文件,在此文件中會發(fā)現(xiàn)tpcall服務(wù)的失敗信息,根據(jù)這個(gè)信息查找對應(yīng)的SERVER和SERVICE的對應(yīng)表,很快就可以找到問題服務(wù)。采用這種方式,維護(hù)人員不需要了解程序的具體流程就可以定位錯(cuò)誤解決故障。
在TUXEDO的服務(wù)端,有幾類文件需要關(guān)注,這些文件包括ULOG文件、XA接口的trc文件、數(shù)據(jù)庫連接故障的sqlnet.log、標(biāo)準(zhǔn)輸出文件stdout(也可以被應(yīng)用程序自己定義)。在這些文件中包含著豐富的系統(tǒng)運(yùn)行錯(cuò)誤告警信息。ULOG記載關(guān)于中間件的啟停記錄和系統(tǒng)本身的一些配置運(yùn)行告警信息。XA的trc文件記錄的是XA接口方面的一些的錯(cuò)誤信息,關(guān)于分布式事務(wù)的一些錯(cuò)誤在這個(gè)文件中都有記錄。sqlnet.log記錄了應(yīng)用程序和數(shù)據(jù)庫連接故障的信息,只要有當(dāng)前日期時(shí)間的這個(gè)文件存在,應(yīng)用和數(shù)據(jù)庫的連接就會存在問題。標(biāo)準(zhǔn)輸出文件stdout記錄了應(yīng)用程序本身的運(yùn)行信息。這些文件的跟蹤檢查對于及時(shí)主動的發(fā)現(xiàn)故障有著重要的意義。
2.3、事務(wù)控制的問題1、事務(wù)邊界的問題:在這里我們要遵循誰發(fā)起發(fā)起事務(wù),誰就結(jié)束的原則,這里的誰主要是指中間件的前臺和后臺。我們知道在TUXEDO中事務(wù)的發(fā)起既可以在前臺程序中發(fā)起,也可以在后臺程序中發(fā)起。無論放在前臺還是放在后臺都有其優(yōu)缺點(diǎn)。事務(wù)放在前臺增加了網(wǎng)絡(luò)傳輸?shù)牧髁?,?dāng)時(shí)可以保證異常情況下前后臺操作的一致性,事務(wù)放在后臺可以減少網(wǎng)絡(luò)流量,但是對于異常情況下前后臺操作的一致性很難保證。我們采用的是事務(wù)放在前臺程序中。但是無論放在前臺還是后臺,都要遵循誰發(fā)起,誰結(jié)束的原則。
2、XA接口使用的注意事項(xiàng):首先是XA資源文件的配置,在oracle數(shù)據(jù)庫中一般用到的是libclntsh.a,我們可以先Make sample,提取其中用到的連接庫加入到RM文件中即可。其次在oracle8i之前要對XA進(jìn)行授權(quán),要在oracle的DBA用戶下執(zhí)行g(shù)rant select on dba_pending_transactions to public。
3、事務(wù)掛起的問題:在使用XA的情況下,我們經(jīng)常會遇到這種情況,SERVER進(jìn)程還在,可就是不做事。在相關(guān)的日志文件中總是報(bào)“當(dāng)前的進(jìn)程已經(jīng)在一個(gè)本地事務(wù)中了”的錯(cuò)誤,這時(shí)只有重啟該SERVER,才能排除故障。其實(shí)這是一個(gè)事務(wù)控制的問題,它產(chǎn)生的根本原因是在開啟全局事務(wù)前,該SERVER執(zhí)行了一個(gè)本地的事務(wù)并且沒有提交或回滾。在程序代碼上表現(xiàn)為如下三種原因:
(1)、在調(diào)用該SERVER的某個(gè)帶DML語句的service前沒有加tpbegin。
(2)、在調(diào)用tpbegin后沒有判斷返回值。
(3)、tpbegin后的tpcall服務(wù)調(diào)用沒有判斷返回值,在全局事務(wù)超時(shí)后沒有能夠及時(shí)的退出后續(xù)的調(diào)用,導(dǎo)致下一個(gè)tpcall產(chǎn)生了一個(gè)本地事務(wù)。
此外,還會有一類比較特殊的問題,那就是TMS服務(wù)掛起的問題,利用tmadmin中的pq命令發(fā)現(xiàn)TMS的隊(duì)列中有很多請求存在,在這種情況下,一般只能等待其執(zhí)行完成,情況嚴(yán)重時(shí),則需要調(diào)整相應(yīng)的數(shù)據(jù)庫參數(shù),在ORACLE中該參數(shù)應(yīng)該設(shè)為max_commit_propagation_delay>=90000。
在實(shí)際的運(yùn)行維護(hù)中,我們發(fā)現(xiàn)即使把數(shù)據(jù)庫參數(shù)調(diào)整了,有時(shí)還會有TMS掛起的故障發(fā)生。針對這件事情我們專門作了研究,TMS之所以掛起是因?yàn)門MS在等待數(shù)據(jù)庫中DX獨(dú)占鎖的釋放,這種獨(dú)占鎖加鎖的對象一般都是ORACLE的系統(tǒng)對象,而這種獨(dú)占鎖的產(chǎn)生一般是在全局事務(wù)中執(zhí)行著DML語句,當(dāng)這種DML語句執(zhí)行比較慢時(shí),就會引起TMS的鎖等待現(xiàn)象。此外,我們還發(fā)現(xiàn),一般的查詢語句是不會產(chǎn)生鎖的(OPS的lm_lock鎖除外),但是如果將查詢放入一個(gè)全局事務(wù)中時(shí),它就會產(chǎn)生一個(gè)共享的DX鎖,如果這個(gè)在全局事務(wù)中的查詢的調(diào)用是通過ORACLE的工具包DBMS_SQL來進(jìn)行的話,那就會產(chǎn)生一個(gè)DX的排他鎖?;谶@些結(jié)果,我們建議在程序的開發(fā)過程中要遵循能不用XA全局事務(wù)的情況下就不用,能將查詢放到事務(wù)之外的就不要放到事務(wù)之內(nèi),能不用ORACLE工具包進(jìn)行開發(fā)的就不要用。我們也按照這個(gè)原則要求我們的開發(fā)商,取得了比較好的效果。
4、事務(wù)超時(shí)設(shè)置的問題
中間件應(yīng)用系統(tǒng)的事務(wù)超時(shí)控制很重要,不設(shè)置超時(shí)時(shí)間對系統(tǒng)來說簡直就是一種災(zāi)難。我們曾經(jīng)就有過因?yàn)槌瑫r(shí)時(shí)間的設(shè)置沒設(shè)和設(shè)置不當(dāng)造成了嚴(yán)重的系統(tǒng)故障,最直接的故障就是系統(tǒng)報(bào)全局事務(wù)數(shù)不夠的錯(cuò)誤,無法開啟新的事務(wù),從而導(dǎo)致前臺業(yè)務(wù)的終止。TUXEDO的超時(shí)主要有三種,一個(gè)是在代碼中的tpbegin超時(shí)(值為其參數(shù))T1,他控制整個(gè)事務(wù)的完成時(shí)間,第二個(gè)為XA連接的超時(shí)(配置文件中的open_info中的SesTm )T2,他控制同一連接中對于分布式事務(wù)鎖的等待超時(shí)時(shí)間,還有一個(gè)為數(shù)據(jù)庫中等待數(shù)據(jù)庫對象非分布式事務(wù)鎖釋放的超時(shí)時(shí)間(_dirstributed_lock_timeout)T3。這三個(gè)超時(shí)共同作用并且有如下的關(guān)系 T1
2.4、服務(wù)不能正常啟動的問題在實(shí)際的維護(hù)工作中,經(jīng)常會出現(xiàn)服務(wù)不能正常啟動的現(xiàn)象。明明所有的服務(wù)都已經(jīng)關(guān)閉了,tmboot就是起不來。這種原因一般是因?yàn)橄到y(tǒng)的IPC資源沒有釋放。IPC資源是操作系統(tǒng)用來進(jìn)行進(jìn)程間通訊的系統(tǒng)資源,主要包括信號燈、共享內(nèi)存、消息隊(duì)列。在UNIX操作系統(tǒng)下通過IPCS命令可以清楚的看到IPC資源的使用情況。當(dāng)服務(wù)無法啟動的時(shí)觀察IPCS就會發(fā)現(xiàn)tuxedo運(yùn)行環(huán)境的用戶下的ipc資源沒有被釋放,這時(shí)使用ipcrm命令清除相應(yīng)的IPC資源,再啟動服務(wù)就可以了。
草木瓜 2006-6-1
------------------------
一、簡介
------------------------
外部應(yīng)用訪問Tuxedo服務(wù)是很經(jīng)常的事,一般有兩種方法WTC和Jolt,網(wǎng)上很多關(guān)于Jolt調(diào)用Tuxedo服務(wù)
文章,描述的太多籠統(tǒng),其實(shí)通過Jolt并不是很復(fù)雜的事情,這里使用Eclipse3.1+Jolt+WebLogic8.1
+Tuxedo9.0環(huán)境描述調(diào)用服務(wù)的全過程。
Jolt是Bea Tuxedo自帶的jar組件,在Tuxedo9.0的安裝過程中可以看到安裝的Jolt組件。
調(diào)用服務(wù)理論步驟是這樣的:
1.先準(zhǔn)備Tuxedo服務(wù)端代碼
2.在Tuxedo中配置Jolt相關(guān)文件
3.啟動Tuxedo服務(wù)
4.配置WebLogic服務(wù)與Tuxedo Jolt相關(guān)的參數(shù)
5.配置Eclipse3.1啟動WebLogic服務(wù)
6.編寫Eclipse Servlet代碼,運(yùn)行調(diào)用服務(wù)。
本例使用了《Windows Tuxedo的安裝配置-數(shù)據(jù)庫補(bǔ)充》一文中的Tuxedo數(shù)據(jù)服務(wù)文件,所以在啟動
Tuxedo服務(wù)前,必須先啟動數(shù)據(jù)庫實(shí)例,因?yàn)樵趖psvinit()里面就配置了數(shù)據(jù)連接。關(guān)于Tuxedo配置
要點(diǎn)需參閱《Tuxedo的安裝配置-...》的四篇文章。
------------------------
二、Tuxedo服務(wù)文件全代碼
------------------------
這里把server.pc服務(wù)文件代碼再次列出。其中包括三個(gè)服務(wù)DBREAD(讀數(shù)據(jù)庫)和TOUPPER(轉(zhuǎn)換大寫)。
本例不使用TOUPPER,所以不用理會那段代碼。
其中liwei/liwei@windb連接的表tuxedo_test,結(jié)構(gòu)如下:
CREATE TABLE TUXEDO_TEST(
ID NUMBER(2),
NAME VARCHAR2(10)
)
ID NAME
------------------------
1 aaaaaaa
2 bbbbbbb
#include <stdio.h>
#include <ctype.h>
#include <atmi.h> /* TUXEDO Header File */
#include <userlog.h> /* TUXEDO Header File */
EXEC SQL BEGIN DECLARE SECTION;
VARCHAR ora_no[2];
int ora_id;
VARCHAR ora_value[10];
VARCHAR ora_cn[30];
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE sqlca;
tpsvrinit()
{
strcpy(ora_cn.arr,"liwei/liwei@windb");
ora_cn.len = strlen(ora_cn.arr);
ora_cn.arr[ora_cn.len]='\0';
//EXEC SQL WHENEVER SQLERROR GOTO cnError;
EXEC SQL CONNECT :ora_cn;
return(0);
}
tpsrvdone()
{
EXEC SQL COMMIT WORK RELEASE;
}
DBREAD(TPSVCINFO *rqst)
{
strcpy(ora_no.arr,(char *)rqst->data);
ora_no.len=strlen(ora_no.arr);
ora_no.arr[ora_no.len]='\0';
userlog("ERRSRV: %s",ora_no.arr);
EXEC SQL select name into :ora_value from tuxedo_test where id=:ora_no;
if(sqlca.sqlcode!=0)
{
userlog("ERRSRV: select name from tuxedo_test where id=, sqlcode=%ld , sqlerr=\n",sqlca.sqlcode);
strcpy(rqst->data,sqlca.sqlerrm.sqlerrmc);
tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
}
/* Return the transformed buffer to the requestor. */
strset(rqst->data,"");
strcpy(rqst->data,ora_value.arr);
tpreturn(TPSUCCESS, 0, rqst->data, 0L, 0);
}
TOUPPER(TPSVCINFO *rqst)
{
int i;
for(i = 0; i < rqst->len-1; i++)
rqst->data[i] = toupper(rqst->data[i]);
/* Return the transformed buffer to the requestor. */
tpreturn(TPSUCCESS, 0, rqst->data, 0L, 0);
}
------------------------
三、編譯服務(wù)
------------------------
編譯命令的注意事項(xiàng),以前Tuxedo系列文章都提過。
proc server.pc include=%TUXDIR%\include
buildserver -o server -f server.c -s DBREAD -s TOUPPER -v -l orasql9.lib
------------------------
四、配置Tuxedo服務(wù)的config文件
------------------------
完全文件如下:
#Liwei
*RESOURCES
IPCKEY 123456
DOMAINID liweiapp
MASTER lw
MAXACCESSERS 150
MAXSERVERS 100
MAXSERVICES 100
MODEL SHM
LDBAL N
*MACHINES
LWYM
LMID = lw
TUXDIR = "E:\bea\tuxedo9.0"
TUXCONFIG = "G:\Liwei\Tuxedo\dbread\tuxconfig"
APPDIR = "G:\Liwei\Tuxedo\dbread"
MAXWSCLIENTS=1
TLOGDEVICE = "G:\Liwei\Tuxedo\dbread\TLOG"
TLOGNAME=TLOG
TLOGSIZE = 100
*GROUPS
APPGRP LMID=lw GRPNO = 1
#OPENINFO="Oracle_XA:Oracle_XA+Acc=P/liwei/liwei+SqlNet=linux+SesTm=600+MaxCur=5+LogDir=."
#TMSNAME="TMS_ORA9i" TMSCOUNT=2
JSLGRP LMID=lw GRPNO = 2
JREPGRP LMID=lw GRPNO = 3
*SERVERS
server SRVGRP=APPGRP SRVID=1
#WSL SRVGRP=APPGRP SRVID =300
#CLOPT="-A -- -n //192.168.0.166:8888 -d/dev/tcp -m1 -M5 -x 10"
JSL SRVGRP=JSLGRP SRVID=301
CLOPT="-A -- -n //192.168.0.166:9878 -M 10 -x 10 -m 2"
JREPSVR SRVGRP=JREPGRP SRVID=302
CLOPT="-A -- -W -P E:\bea\tuxedo9.0\udataobj\jolt\repository\jrepository"
*SERVICES
DBREAD
TOUPPER
細(xì)心一看,這個(gè)config文件比在*GROUPS和*SERVERS各加了兩項(xiàng)對應(yīng)內(nèi)容:
JSLGRP LMID=lw GRPNO = 2
JREPGRP LMID=lw GRPNO = 3
和
JSL SRVGRP=JSLGRP SRVID=301
CLOPT="-A -- -n //192.168.0.166:9878 -M 10 -x 10 -m 2"
JREPSVR SRVGRP=JREPGRP SRVID=302
CLOPT="-A -- -W -P E:\bea\tuxedo9.0\udataobj\jolt\repository\jrepository"
這兩項(xiàng)是用于jolt的訪問接口。JSL和JREPSVR必須是獨(dú)自的GROUP,由于外部調(diào)用通過JSL和JREPSVR直接于
Tuxedo服務(wù)通信,WSL就沒用了。JSL的主機(jī)地址是Tuxedo服務(wù)器地址,端口是隨意指定的,不要與其他重復(fù)
即可,一般設(shè)置的大一點(diǎn)。在config里面加入這此內(nèi)容后,config文件就Ok了。
------------------------
五、配置jrepository文件
------------------------
直接打開E:\bea\tuxedo9.0\udataobj\jolt\repository\jrepository文件添加以下內(nèi)容:
add SVC/DBREAD:vs=1:ex=1:bt=STRING:\
bp:pn=STRING:pt=string:pf=167772161:pa=rw:ep:
add PKG/SIMPSERV:DBREAD:
這個(gè)文件如果沒有DBREAD配置,調(diào)用會提示DBREAD not avaliable,DBREAD配置錯(cuò)誤,會提示DBREAD has
been modifed ...
對這個(gè)文件操作還有以下兩種方式:
方式一:在IE打開E:\bea\tuxedo9.0\udataobj\jolt\RE.html,是個(gè)java applet,里面是圖形界面,添加
完服務(wù),設(shè)置好參數(shù)即可。具體方法可以查閱網(wǎng)上資料,有圖文解說的。
方式二:在命令行鍵入Java bea.jolt.admin.jbld //192.168.0.166:9878 services.rep,其中//192..要與
JSL的設(shè)置一致。services.rep是隨意的一個(gè)文件,不過文件內(nèi)容絕對不隨意,如下:
service=DBREAD
inbuf=STRING
outbuf=STRING
export=true
param=STRING
type=string
access=inout
要執(zhí)行這個(gè)命令設(shè)置jdk環(huán)境變量是必不可少的,PATH,CLASSPATH。我的CLASSPATH加入了以下內(nèi)容,
E:\bea\tuxedo9.0\udataobj\jolt\joltwls.jar;
E:\bea\tuxedo9.0\udataobj\jolt\joltjse.jar;
E:\bea\tuxedo9.0\udataobj\jolt\jolt.jar;
E:\bea\tuxedo9.0\udataobj\jolt\joltadmin.jar
個(gè)人認(rèn)為對于這個(gè)java命令joltadmin是必須的,其他三個(gè)沒用,不過沒有親自嘗試。
方式一,二修改后,jrepository文件會顯得比較亂,所以我不喜歡!最好是自已手工修改。
------------------------
六、編譯啟動服務(wù)
------------------------
當(dāng)然,數(shù)據(jù)庫必須要有了,編譯config后,啟動tuxedo服務(wù)。
tmloadcf -y config
tmboot -y
提示如下:
exec BBL -A :
process id=3520 ... Started.
Booting server processes ...
exec server -A :
process id=3812 ... Started.
exec JSL -A -- -n //192.168.0.166:9878 -M 10 -x 10 -m 2 :
process id=252 ... Started.
exec JREPSVR -A -- -W -P E:\bea\tuxedo9.0\udataobj\jolt\repository\jrepository :
process id=2920 ... Started.
4 processes started.
------------------------
七、配置Eclipse3.1
------------------------
我們要在Eclipse里面啟動WebLogic服務(wù),《Eclipse3.1 Web開發(fā)配置》一文中已經(jīng)說明了,如何配置
WebLogic8.1的服務(wù)器,這里對WebLogic的服務(wù)本身也要做此必要的配置。
打開選用的WebLogic8.1服務(wù)路徑,編輯config.xml文件,本機(jī)位置G:\Liwei\WebLogic\WebServer\config.xml。
加入如下內(nèi)容:
<JoltConnectionPool FailoverAddresses="http://192.168.0.166:9878"
MaximumPoolSize="2" MinimumPoolSize="1" Name="JoltPool"
PrimaryAddresses="http://192.168.0.166:9878"
SecurityContextEnabled="false" Targets="webServer"/>
<StartupClass
ClassName="bea.jolt.pool.servlet.weblogic.PoolManagerStartUp"
LoadBeforeAppActivation="true" Name="MyStartup" Targets="webServer"/>
<ShutdownClass
ClassName="bea.jolt.pool.servlet.weblogic.PoolManagerShutDown"
Name="MyShutdown" Targets="webServer"/>
這里要說明一下:PrimaryAddresses,F(xiàn)ailoverAddresses地址是前面Tuxedo配置文件指定的JSL地址和端口
SecurityContextEnabled一定要是false!所有name是隨意的,StartupClass和ShutdownClass的ClassName
絕對不能錯(cuò)!
除此方法,還可以通過Weblogic服務(wù)的控制臺進(jìn)行管理。啟動服務(wù)后,在http://localhost:7001/console/
登陸后的主頁面上選擇 連接性->通過 JOLT 的 Tuxedo ->配置新的Jolt 連接緩沖池...輸入?yún)?shù)內(nèi)容就是
上面config.xml的參數(shù)。另外首頁中 已部署的資源 ->啟動和關(guān)閉 需要設(shè)置兩個(gè)Class,參數(shù)也同上。
連接性->通過 JOLT 的 Tuxedo ->配置新的Jolt 連接緩沖池...
①進(jìn)入選項(xiàng)卡的General(常規(guī)),輸入?yún)?shù):
Name: JoltPool
Minimum Pool Size: 1
Maximum Pool Size: 2
Recv Timeout: 0
點(diǎn)擊Apply應(yīng)用按紐
②進(jìn)入選項(xiàng)卡的Addresses(地址),輸入?yún)?shù):
Primary Addresses: //192.168.0.166:9878
Failover Addresses: //192.168.0.166:9878
點(diǎn)擊Apply應(yīng)用按紐
③進(jìn)入Targets欄:
選中myserver
點(diǎn)擊Apply應(yīng)用按紐.
已部署的資源 ->啟動和關(guān)閉 分別配置StartUp,ShutDown的Class
①進(jìn)入Configuration(設(shè)置)
在ClassName:中輸入: bea.jolt.pool.servlet.weblogic.PoolManagerStartUp,
其它采用默認(rèn)值。
②進(jìn)入Targets(目標(biāo))欄:
選中myserver,點(diǎn)擊Apply應(yīng)用按紐.
①進(jìn)入Configuration(設(shè)置)
在ClassName:中輸入: bea.jolt.pool.servlet.weblogic.PoolManagerShutDown,
其它采用默認(rèn)值。
②進(jìn)入Targets(目標(biāo)):
選中myserver,點(diǎn)擊Apply應(yīng)用按紐.
到這里config.xml文件就設(shè)置完了,下面需要編輯startWebLogic.cmd,加入對jolt jar的引用,否則jolt
是啟動失敗的。在echo CLASSPATH=%CLASSPATH%前加入以下代碼,設(shè)置CLASSPATH,這里classpath跟外部環(huán)境
變量是兩碼事。
set CLASSPATH=%CLASSPATH%;E:\bea\tuxedo9.0\udataobj\jolt\jolt.jar;E:\bea\tuxedo9.0\udataobj\jolt\joltwls.jar;E:\bea\tuxedo9.0\udataobj\jolt\joltjse.jar
設(shè)置完后,重啟服務(wù),在Eclipse管理WebLogic服務(wù)時(shí)如果出現(xiàn)啟動關(guān)閉不成功,多試幾次就可以了。
在啟動的console界面里如果出現(xiàn)以下內(nèi)容,就說明jolt pool啟動成功!
<2006-6-1 下午09時(shí)12分55秒 CST> <Notice> <WebLogicServer> <BEA-000327> <Starting WebLogic Admin Server "webServer" for domain "WebServer">
Jolt pool deployed for webServer
<2006-6-1 下午09時(shí)13分13秒 CST> <Notice> <Security>...
------------------------
八、Eclipse3.1編寫Servlet代碼
------------------------
首先需要在所建工程->右鍵->Properties->Java BuildPath ->Library->Add External jars ..添加jolt的jar包
這里需要三個(gè)jar包,如下:
E:\bea\tuxedo9.0\udataobj\jolt\jolt.jar
E:\bea\tuxedo9.0\udataobj\jolt\joltjse.jar
E:\bea\tuxedo9.0\udataobj\jolt\joltwls.jar
添加jar完后,建立一個(gè)主頁面index.jsp和一個(gè)Servlet。關(guān)于Eclipse3.1配置Servlet在《Eclipse3.1 Web開發(fā)配置》
一文也有說明。這里Servlet名為liwei.java,具體內(nèi)容如下:
index.jsp
<body>
<form id=form1 name="form1" action=liwei method=post>
<input type="text" name="STRING" value="1">
<input type=submit value=submit>
</form>
</body>
說明:name要是STRING,用來傳遞參數(shù),action是liwei.java即Servlet。
liwei.java
public class liwei extends javax.servlet.http.HttpServlet
{
//聲明管理連接池的變量
private bea.jolt.pool.servlet.ServletSessionPoolManager bool_mgr = (bea.jolt.pool.servlet.ServletSessionPoolManager) bea.jolt.pool.SessionPoolManager.poolmgr;
public void init(javax.servlet.ServletConfig config) throws javax.servlet.ServletException
{
//初始化servlet
super.init(config);
}
public void destroy() {
//關(guān)閉servlet
bool_mgr = null;
}
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, java.io.IOException
{
bea.jolt.pool.servlet.ServletResult result;
//設(shè)置頁面類型,如果沒有charset,顯示漢字會亂碼
response.setContentType("text/html;charset=UTF-8");
java.io.PrintWriter out =response.getWriter();
out.println("<html>");
out.println("<body>");
//System.out.println("TEST________________________1");
//獲取在WebLogic服務(wù)定義好的連接池,JoltPool
bea.jolt.pool.servlet.ServletSessionPool pool_session = (bea.jolt.pool.servlet.ServletSessionPool)
bool_mgr.getSessionPool("JoltPool");
if (pool_session == null) {
out.println("獲取Tuxedo服務(wù)失敗。"+
"<br>"+
"確認(rèn)Tuxedo服務(wù)已啟動且配置正確。"+
"</font></body></html>");
out.close();
return;
}
System.out.println(pool_session);
String sendvalue;
sendvalue=request.getParameter("STRING");
System.out.println(sendvalue);
// 調(diào)用服務(wù)
try
{
System.out.println("OK!");
//調(diào)用服務(wù)DBREAD
result = pool_session.call("DBREAD", request);
out.println("傳遞的參數(shù) = " + sendvalue);
out.println("Tuxedo服務(wù)成功調(diào)用。 ");
//跟據(jù)傳遞的變量STRING值,獲取返回值
out.println("返回值:"+result.getValue("STRING", ""));
}
catch (bea.jolt.pool.SessionPoolException e)
{
// 連接池繁忙
out.println("此時(shí)請求不能被處理。\n"+
"錯(cuò)誤信息: "+e.getMessage()+"\n"+
"可能的原因:1.無效的連接池 2.連接池已關(guān)閉");
}
catch (bea.jolt.pool.ServiceException e)
{
// 服務(wù)出錯(cuò),這里主要是Tuxedo的服務(wù)配置,jrepository文件出錯(cuò)
e.printStackTrace();
out.println("錯(cuò)誤信息:"+
"Error message:"+e.getMessage()+
"Error number:"+e.getErrno());
}
catch (bea.jolt.pool.ApplicationException e)
{
// 應(yīng)用程序出錯(cuò)
result = (bea.jolt.pool.servlet.ServletResult) e.getResult();
out.println("錯(cuò)誤代碼:"+result.getApplicationCode());
}
catch (Exception e)
{
out.println("意外錯(cuò)誤:"+e);
}
out.println("</body></html>\n");
out.close();
}
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, java.io.IOException
{
this.doGet(request,response);
}
}
------------------------
九、RUN
------------------------
Run on server ,點(diǎn)擊Submit,顯示 傳遞的參數(shù) = 1 Tuxedo服務(wù)成功調(diào)用。 返回值:aaaaaaa !
=======================
Java通過Jolt訪問Tuxedo服務(wù)-補(bǔ)充說明
草木瓜
2006-6-2
一、頁面參數(shù)文件說明以及通過WebLogic調(diào)用Tuxedo服務(wù)
《Java通過Jolt訪問Tuxedo服務(wù)》一文是在Eclipse環(huán)境下開發(fā)調(diào)用Tuxedo服務(wù)。
其中在index.asp和liwei.java中有這么幾句語句:
index.asp
<form id=form1 name="form1" action=liwei method=post>
<input type="text" name="STRING" value="1">
<input type=submit value=submit>
liwei.java
//跟據(jù)傳遞的變量STRING值,獲取返回值
out.println("返回值:"+result.getValue("STRING", ""));
這兩段的STRING是不可以隨便替換的,這必須與E:\bea\tuxedo9.0\udataobj\jolt\repository
下jrepository文件描述的服務(wù)參數(shù)相一致!且必須為大寫!即:
add SVC/DBREAD:vs=1:ex=1:bt=STRING:\
bp:pn=STRING:pt=string:pf=167772161:pa=rw:ep: //這里面定義的參數(shù)就是STRING
add PKG/SIMPSERV:DBREAD:
下面用WebLogic對Tuxedo服務(wù)調(diào)用再詳細(xì)的舉例說明。
WebLogic通過jolt調(diào)用Tuxedo服務(wù),有了上文的前提就顯得很容易,說白了只是Servlet與Jsp的一點(diǎn)
小轉(zhuǎn)換。除了最后一步在Eclipse3.1編寫Servlet代碼,其他的前提步驟是必須的。WebLogic要使用
Jolt接口,同樣需要jolt,joltjse,joltwls三個(gè)jar包,將它們Copy到WEB-INF下的lib文件夾即可。
以下是完整的示例,參數(shù)名用大寫的TEST。
index.jsp
---------------------------------
<form action="_test/testTuxedo.jsp" method="post">
<p>
<input type="text" value="1" name="TEST" id="text1"><input type="submit" value="tuxedo">
</p>
</form>
testTuxedo.jsp
---------------------------------
<body>
<p>
<%
bea.jolt.pool.servlet.ServletSessionPoolManager bool_mgr = (bea.jolt.pool.servlet.ServletSessionPoolManager) bea.jolt.pool.SessionPoolManager.poolmgr;
bea.jolt.pool.servlet.ServletResult result;
//獲取在WebLogic服務(wù)定義好的連接池
bea.jolt.pool.servlet.ServletSessionPool pool_session = (bea.jolt.pool.servlet.ServletSessionPool)
bool_mgr.getSessionPool("JoltPool");
if (pool_session == null) {
out.println("獲取Tuxedo服務(wù)失敗。"+
"<br>"+
"確認(rèn)Tuxedo服務(wù)已啟動且配置正確。");
out.close();
return;
}
// 調(diào)用服務(wù)
try
{
result = pool_session.call("DBREAD", request);
System.out.println("OK!");
out.println("傳遞的參數(shù) = " + sendvalue);
out.println("Tuxedo服務(wù)成功調(diào)用。 ");
out.println("返回值:"+result.getValue("TEST", ""));
}
catch (bea.jolt.pool.SessionPoolException e)
{
// 連接池繁忙
out.println("此時(shí)請求不能被處理。\n"+
"錯(cuò)誤信息: "+e.getMessage()+"\n"+
"可能的原因:1.無效的連接池 2.連接池已關(guān)閉");
}
catch (bea.jolt.pool.ServiceException e)
{
// 服務(wù)出錯(cuò)
e.printStackTrace();
out.println("Error:"+
"Error message:"+e.getMessage()+
"Error number:"+e.getErrno());
}
catch (bea.jolt.pool.ApplicationException e)
{
// 應(yīng)用程序出錯(cuò)
result = (bea.jolt.pool.servlet.ServletResult) e.getResult();
out.println("錯(cuò)誤代碼:"+result.getApplicationCode());
}
catch (Exception e)
{
out.println("意外錯(cuò)誤:"+e);
}
%>
</p>
</body>
二、典型的服務(wù)應(yīng)用
Oracle服務(wù)器 192.168.0.111
Tuxedo服務(wù)器 192.168.0.66
Web服務(wù)器
通過Web客戶端訪問Web服務(wù)器,調(diào)用Tuxedo服務(wù)訪問數(shù)據(jù)庫
1.配置Tuxedo服務(wù)器的Oracle連接字符串(TNSNAME)。注意Oracle服務(wù)器的防火墻
WINDB =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.111)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = wincn)
)
)
2.配置Tuxedo的jrepository文件
3.配置Tuxedo的Config文件,JSR服務(wù)的IP與端口要與本地IP一致。
JSL SRVGRP=JSLGRP SRVID=301
CLOPT="-A -- -n //192.168.0.66:9988 -M 10 -x 10 -m 2"
4.配置Web服務(wù)器的WebServer,config.xml中ip與端口即為Tuxedo服務(wù)器的JSR服務(wù)IP與端口
注意Tuxedo服務(wù)器的防火墻。
<JoltConnectionPool FailoverAddresses="http://192.168.0.66:9988"
MaximumPoolSize="2" MinimumPoolSize="1" Name="JoltPool"
PrimaryAddresses="http://192.168.0.66:9988"
SecurityContextEnabled="false" Targets="webServer"/>
Windows下Tuxedo的安裝與配置-數(shù)據(jù)庫
草木瓜 2005-5-18
一、準(zhǔn)備數(shù)據(jù)庫環(huán)境
這里使用的是Linux+Oracle9的虛擬機(jī)數(shù)據(jù)庫環(huán)境。本機(jī)配置Tuxedo服務(wù)器。在上篇無數(shù)據(jù)庫配置
基礎(chǔ)上,配置Tuxedo服務(wù)器連接Oracle理解起來就相對簡單了。這里采用XA方式連接數(shù)據(jù)庫。
二、準(zhǔn)備客戶端,服務(wù)端的應(yīng)用程序
這里是自已寫的代碼。
client.c
#include <stdio.h>
#include <atmi.h> /* TUXEDO Header File */
main(int argc, char *argv[])
{
char *sendbuf;
long sendlen=1024;
int ret;
if(argc != 2) {
(void) fprintf(stderr, "args not exist\n");
exit(1);
}
/* 與服務(wù)器建立連接 */
if (tpinit((TPINIT *) NULL) == -1)
{
(void) fprintf(stderr, "Tpinit failed\n");
exit(1);
}
/* 分配發(fā)送緩沖 */
sendbuf = (char *) tpalloc("STRING", NULL, sendlen);
if (sendbuf== (char *)NULL)
{
(void) fprintf(stderr,"Error allocating send buffer\n");
tpterm();
exit(1);
}
(void) strcpy(sendbuf, argv[1]);
(void) fprintf(stdout, "InputValue: %s\n", argv[1]);
/* 向服務(wù)發(fā)送請求 */
ret = tpcall("DBSERV", (char *)sendbuf, 0L, (char **)&sendbuf, &sendlen, 0L);
if(ret == -1) {
(void) fprintf(stderr, "Can't send request to service DBREAD\n");
(void) fprintf(stderr, "Tperrno = %d\n", tperrno);
tpfree(sendbuf);
tpterm();
exit(1);
}
(void) fprintf(stdout, "Returned string is: %s\n", sendbuf);
/* Free Buffers & Detach from System/T */
tpfree(sendbuf);
tpterm();
return(0);
}
server.pc 這里用到了ProC的一些方法
#include <stdio.h>
#include <ctype.h>
#include <atmi.h> /* TUXEDO Header File */
#include <userlog.h> /* TUXEDO Header File */
EXEC SQL INCLUDE sqlca;
EXEC SQL BEGIN DECLARE SECTION;
VARCHAR ora_no[2];
VARCHAR ora_value[10];
EXEC SQL END DECLARE SECTION;
DBREAD(TPSVCINFO *rqst)
{
strcpy(ora_no.arr,(char *)rqst->data);
ora_no.len=strlen(ora_no.arr);
ora_no.arr[ora_no.len]='\0';
userlog("ERRSRV: %s",ora_no.arr);
EXEC SQL select name into :ora_value from tuxedo_test where id=:ora_no;
if(sqlca.sqlcode!=0)
{
userlog("ERRSRV: select name from tuxedo_test where id=, sqlcode=%ld \n",sqlca.sqlcode);
tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
}
strcpy(rqst->data,ora_value.arr);
tpreturn(TPSUCCESS, 0, rqst->data, 0L, 0);
}
三、編譯客戶端,服務(wù)端代碼
buildclient -o client -f client.c -v
對pc文件,須首先編譯為c,然后再編譯為服務(wù)。在proc編譯的過程,會出現(xiàn)link錯(cuò)誤,這是因?yàn)閠uxedo本身
帶的sqlca.h與oracle proc沖突,將C:\bea\tuxedo9.0\include\sqlca.h改名即可。
proc server.pc include=%TUXDIR%/include
buildserver -o server -f server.c -r Oracle_XA -s DBREAD -v
四、配置Tuxedo的RM文件
本地Tuxedo9.0安裝路徑為C:\bea\tuxedo9.0。
打開C:\bea\tuxedo9.0\udataobj路徑下的rm文件。找到Oracle_XA:這句,可以注釋掉,然后增加下面內(nèi)容。
Oracle_XA;xaosw;E:\oracle\ora92\rdbms\XA\ORAXA9.LIB E:\oracle\ora92\precomp\lib\orasql9.lib
注:本機(jī)如果沒有裝服務(wù)版的Oracle,可能找不到對應(yīng)庫文件,可從服務(wù)器端復(fù)制過來即可。
這兩個(gè)lib是用于編譯tms文件的,tuxedo通過TMS_ORA9i與Oracle數(shù)據(jù)庫進(jìn)行XA通訊。
修改完rm文件,運(yùn)行命令buildtms -o C:\bea\tuxedo9.0\bin\TMS_ORA9i -r Oracle_XA編譯生成TMS_ORA9i。
五、修改ubbconfig文件
在*GROUP下添加下面語句。liwei/liwei@linux是連接數(shù)據(jù)庫的tns配置。TMSCOUNT=2表示啟動兩個(gè)TMS服務(wù)。
OPENINFO="Oracle_XA:Oracle_XA+Acc=P/liwei/liwei+SqlNet=linux+SesTm=600+MaxCur=5+LogDir=."
TMSNAME="TMS_ORA9i" TMSCOUNT=2
另外在*MACHINES添加日志的處理,語句如下。
TLOGDEVICE = "F:\Liwei\Tuxedo\dbread\TLOG"
TLOGNAME = TLOG
TLOGSIZE = 100
因?yàn)榫幾g的服務(wù)文件名是server,*SERVERS下改為server
因?yàn)樯傻姆?wù)是DBREAD,所以*SERVICES下也要改成DBREAD。
修改后文件如下:
#Liwei
*RESOURCES
IPCKEY 123456
DOMAINID liweiapp
MASTER lw
MAXACCESSERS 5
MAXSERVERS 5
MAXSERVICES 5
MODEL SHM
LDBAL N
*MACHINES
LWYM
LMID = lw
TUXDIR = "C:\bea\tuxedo9.0"
TUXCONFIG = "F:\Liwei\Tuxedo\dbread\tuxconfig"
APPDIR = "F:\Liwei\Tuxedo\dbread"
TLOGDEVICE = "F:\Liwei\Tuxedo\dbread\TLOG"
TLOGNAME=TLOG
TLOGSIZE = 100
#ULOGPFX = "F:\Liwei\Tuxedo\dbread\ULOG"
*GROUPS
GROUP1 LMID=lw GRPNO = 1
OPENINFO="Oracle_XA:Oracle_XA+Acc=P/liwei/liwei+SqlNet=linux+SesTm=600+MaxCur=5+LogDir=."
TMSNAME="TMS_ORA9i" TMSCOUNT=2
*SERVERS
DEFAULT:
CLOPT="-A"
server SRVGRP=GROUP1 SRVID=1
*SERVICES
DBREAD
編譯日志后不能立刻tmboot運(yùn)行,需要先用tmadmin創(chuàng)建TLOG。方法如下:
C:\>tmadmin
>crdl -b 500 -z F:\Liwei\Tuxedo\dbread\TLOG
>crlog -m lw
注:lw是ubbconfig里面的LMID。
六、Oracle的設(shè)置
Linux:
sqlplus /nolog
conn sys/*** as sysdba
執(zhí)行xaview.sql 創(chuàng)建v$xatrans$和 v$pending_xatrans$兩個(gè)視圖
@...../rdbms/admin/xaview.sql
并把兩個(gè)視圖的select權(quán)限授給連接用戶如liwei。
grant select on v$xatrans$ to liwei with grant option;
grant select on v$pending_xatrans$ to liwei with grant option;
最后
grant select any table to liwei;
七、運(yùn)行tmboot
你會發(fā)現(xiàn)有個(gè)TMS_ORA9i啟動不起來,沒關(guān)系,將*RESOURCES max系列的設(shè)大點(diǎn),tmshutdown,并且
結(jié)束掉tuxipc,重新編譯config然后tmboot就ok了。
client 1
執(zhí)行就會返回?cái)?shù)據(jù)庫結(jié)果了。
Windows下Tuxedo的安裝配置-數(shù)據(jù)庫補(bǔ)充
草木瓜 2006-5-28
一、序
《Windows下Tuxedo的安裝配置-數(shù)據(jù)庫》一文中介紹了通過XA方法連接數(shù)據(jù)庫,步驟比較多,當(dāng)然也可以采
用另一種方法,在服務(wù)程序里面直接寫入連接數(shù)據(jù)庫的命令。
二、服務(wù)端程序
小作修改
EXEC SQL BEGIN DECLARE SECTION;
VARCHAR ora_no[2];
VARCHAR ora_value[10];
VARCHAR ora_cn[30]; //新增
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE sqlca;
//新增以下內(nèi)容,tpsvinit,tpsrdone是tuxedo默認(rèn)構(gòu)造和析構(gòu)函數(shù)。
tpsvrinit()
{
strcpy(ora_cn.arr,"liwei/liwei@windb");
ora_cn.len = strlen(ora_cn.arr);
ora_cn.arr[ora_cn.len]='\0';
EXEC SQL CONNECT :ora_cn;
return(0);
}
tpsrvdone()
{
EXEC SQL COMMIT WORK RELEASE;
}
三、配置文件
注釋掉與XA相關(guān)項(xiàng),由于客戶端與服務(wù)器是同一臺機(jī)器,WSL要不要無所謂。這里也注釋掉。
*GROUPS
GROUP1 LMID=lw GRPNO = 1
#OPENINFO="Oracle_XA:Oracle_XA+Acc=P/liwei/liwei+SqlNet=linux+SesTm=600+MaxCur=5+LogDir=."
#TMSNAME="TMS_ORA9i" TMSCOUNT=2
*SERVERS
server SRVGRP=GROUP1 SRVID=1
#WSL SRVGRP=GROUP1 SRVID =300
#CLOPT="-A -- -n //192.168.98.166:5898 -d/dev/tcp -m1 -M5 -x 10"
*SERVICES
DBREAD
四、編譯服務(wù)端的命令
修改如下:
proc server.pc include=%TUXDIR%\include
buildserver -o server -f server.c -s DBREAD -v
如果在編譯過程中出現(xiàn)error LNK2001: unresolved external symbol _sqlcxt類似的錯(cuò)誤,那是因?yàn)?br /> 找不到orasql9.lib文件。設(shè)置環(huán)境變量lib,加上e:\oracle\ora92\precomp\lib,修改命令:
buildserver -o server -f server.c -s DBREAD -v -l orasql9.lib
五、編譯config文件,運(yùn)行tmboot
六、補(bǔ)充說明
Tuxedo配置一般如下步驟:
1 設(shè)置環(huán)境變量。
2 準(zhǔn)備服務(wù)端客戶端程序。
3 服務(wù)端客戶端編譯(buildclient buildserver)。
4 準(zhǔn)備tuxedo的config文件。
5 編譯config文件(tmload)。
6 如果config文件包含日志,必須通過tmadmin生成日志文件(crdl,crlog),如出錯(cuò)須將原日志文件刪除。
7 啟動tuxedo服務(wù)(tmboot)。
進(jìn)入linux系統(tǒng),在linux系統(tǒng)dos輸入頁面中輸入tmadmin
進(jìn)入tmadmin的監(jiān)管環(huán)境,輸入下面的命令即可
啟動tmadmin
tmboot -y
1查看服務(wù)信息psr
(1) 命令: printserver 簡寫 psr
(2) psr [-m machine] [-g groupname] [-i srvid] [-q qaddress]
-m machine LMID為 machine的所有服務(wù)進(jìn)程
-g groupname 組名為groupname的所有服務(wù)進(jìn)程
-I srvid SRVID為srvid的服務(wù)進(jìn)程
-q qaddress 消息隊(duì)列為qaddress的所有SERVERS查看server的信息
(3) 結(jié)果示例:
Prog Name Queue Name Grp Name ID RqDone Load Done Current Service
--------- ---------- -------- -- ------ --------- ---------------
rz_Ecsb 00004.04000 APGP2 4000 0 0 ( IDLE )
BBL 70020 simple 0 1 50 ( IDLE )
IFMTMS APGP2_TMS APGP2 30001 1 50 ( IDLE )
ftpserv32 00002.00001 FTPGP 1 60 3000 ( IDLE )
結(jié)果說明:
列號 描述
1. 服務(wù)的可執(zhí)行文件名
2. 服務(wù)連接的隊(duì)列名
3. 組名
4. 服務(wù)的數(shù)字id
5. 服務(wù)已經(jīng)處理的請求數(shù)(該SERVER的所有service的負(fù)載因子總和)
6. 服務(wù)處理的全部請求的參數(shù)和,如果當(dāng)前沒有service被調(diào)用,則為IDLE
2查看交易信息psc
(1) 命令: printservice 簡寫: psc
psc [-m machine] [-g groupname] [-I srvid] [-q qaddress]
[-s service] [-a {0|1|2}]
-s service 顯示名為sevice的service信息
-a {0|1|2} 顯示系統(tǒng)的隱含的service
其他參數(shù)與psr命令相同
(2) 結(jié)果示例:
Service Name Routine Name Prog Name Grp Name ID Machine # Done Status
------------ ------------ ------- -------- -- ------- ------ ------
416701 rz_Ecsb rz_Ecsb APGP2 4000 simple 0 AVAIL
416601 rz_Ecsb rz_Ecsb APGP2 4000 simple 0 AVAIL
416501 rz_Ecsb rz_Ecsb APGP2 4000 simple 0 AVAIL
(3) 結(jié)果說明:
列號 描述
1. Service Name :服務(wù)名
2. Routine Name :函數(shù)名(采用TUXEDO服務(wù)的別名機(jī)制,一個(gè)函數(shù)可以對應(yīng)多個(gè)服務(wù)名)
3. Prog Name :service 所在的SERVER名
4. Grp Name :組名
5. ID :server的ID號
6. Machine :server所在的LMID
7. # Done :service被調(diào)用的次數(shù)
8. Status :service的狀態(tài)。AVAIL表示可用
3查看隊(duì)列信息pq
(1) 命令: printqueue 簡寫:pq [PADRESS]
(2) 結(jié)果示例:
pq 00004.05062
Prog Name Queue Name # Serve Wk Queued # Queued Ave. Len Machine
--------- ------------ ------ --------- -------- -------- -------
CCS_GEDAIPC_50 00004.05062 1 0 0 0.0 simple
(3) 結(jié)果說明:
列號 描述
1. Prog Name :隊(duì)列連接的服務(wù)的可執(zhí)行文件名
2. Queue Name :字符隊(duì)列名,是RQADDR參數(shù)或一個(gè)隨機(jī)值
3. #Serve :連接的服務(wù)數(shù)
4. Wk Queued :當(dāng)前隊(duì)列的所有請求的參數(shù)和
5. #Queued :實(shí)際請求數(shù)
6. Ave.Len :平均隊(duì)列長度
7. Machine :隊(duì)列所在機(jī)器的LMID
4查看客戶端信息pclt
(1) 命令: printclient 簡寫:pclt
-m machine 顯示LMID號為machine上的客戶端連接
-u username 顯示用戶名為username 的客戶端連接
-c ctlname 顯示用戶進(jìn)程為ctlname的客戶端連接
(2) 結(jié)果示例:
LMID User Name Client Name Time Status Bgn/Cmmt/Abrt
---------- --------------- --------------- -------- ------- -------------
simple ccsmis WSH 17:42:47 IDLE 0/0/0
simple ccsmis tmadmin 0:44:28 IDLE 0/0/0
(3) 結(jié)果說明:
列號 描述
1. 已經(jīng)登錄的客戶端機(jī)器的LMID
2. 用戶名,由tpinit()提供的
3. 客戶端名,由tpinit()提供的
4. 客戶端連接后經(jīng)過的時(shí)間
5. 客戶端狀態(tài)
6. IDLE——表示客戶端目前沒有任何交易在工作
7. IDLET——表示客戶端啟動了一個(gè)交易
8. BUSY——表示客戶端在工作中
9. BUSYT——表示客戶端正在交易控制下工作
10. 啟動/提交/中斷的交易數(shù)
5查看部分統(tǒng)計(jì)信息bbs
(4) 命令: bbstats 簡寫:bbs
> bbs
Current Bulletin Board Status:
Current number of servers: 335
Current number of services: 2324
Current number of request queues: 27
Current number of server groups: 11
Current number of interfaces: 0
6觀察某個(gè)節(jié)點(diǎn)的進(jìn)程信息default
(5) 命令:default –m
> default -m SITE13
SITE13> psr
Prog Name Queue Name Grp Name ID RqDone Load Done Current Service
--------- ---------- -------- -- ------ --------- ---------------
BBL 30004.00000 SITE13 0 22827 1141350 ..ADJUNCTBB
BRIDGE 836437 SITE13 1 0 0 ( IDLE )
GWADM 00021.00019 BGWGRP1+ 19 0 0 ( IDLE )
GWTDOMAIN 00021.00020 BGWGRP1+ 20 123826 0
GWADM 00022.00021 BGWGRP2+ 21 0 0 ( IDLE )
GWTDOMAIN 00022.00022 BGWGRP2+ 22 0 0 ( IDLE )
GWADM 00025.00027 GWGRP1_+ 27 4 200 ( IDLE )
7查看消息發(fā)送狀態(tài)pnw
(6) 命令:printnetwork 簡寫 pnw
> pnw SITE12
SITE12 Connected To: msgs sent msgs received
SITE14 61904 62319
SITE13 61890 62288
SITE11 15972 13564
8退出管理模式q
(7) 命令: quit 簡寫:q
C++ constructors are called to initialize class objects when those objects are created, and destructors are invoked when class objects are destroyed. For automatic (that is, local, non-static) variables that contain constructors and destructors, the constructor is called when the variable comes into scope and the destructor is called when the variable goes out of scope. However, when you call the tpreturn() or tpforward() function, the compiler performs a non-local goto (using longjmp(3)) such that destructors for automatic variables are not called. To avoid this problem, write the application so that you call tpreturn() or tpforward() from the service routine directly (instead of from any functions that are called from the service routine). In addition, one of the following should be true: