TUXEDO在自動(dòng)語(yǔ)音應(yīng)答系統(tǒng)中的使用
姜曉亮
2002/11/08
隨著企業(yè)經(jīng)營(yíng)觀念、服務(wù)意識(shí)的不斷提高,自動(dòng)語(yǔ)音應(yīng)答(IVR,Interactive Voice Response)系統(tǒng)得到了越來越廣泛的應(yīng)用,如電信企業(yè)提供的170話費(fèi)查詢系統(tǒng)、1861手機(jī)話費(fèi)查詢系統(tǒng)、手機(jī)充值卡系統(tǒng)、各大銀行提供的儲(chǔ)蓄業(yè)務(wù)查詢系統(tǒng)乃至航空公司提供的航班查詢系統(tǒng)等,都是使用IVR系統(tǒng)來實(shí)現(xiàn)的。由于不需要人工介入、同時(shí)具有全天候服務(wù)的特點(diǎn),有理由相信IVR還會(huì)在各個(gè)行業(yè)得到更廣泛的應(yīng)用。
IVR系統(tǒng)與中間件
通過IVR實(shí)現(xiàn)的業(yè)務(wù)都是用戶實(shí)時(shí)參與的,具有一定的實(shí)時(shí)性,每筆事務(wù)的信息量較小,所以,都屬于典型的聯(lián)機(jī)事務(wù)處理(OLTP)業(yè)務(wù)。隨著IVR單臺(tái)集成度的不斷提高,使語(yǔ)音呼叫的密度大大增加,形成了對(duì)IVR后臺(tái)業(yè)務(wù)數(shù)據(jù)庫(kù)的大量并發(fā)訪問,對(duì)后臺(tái)數(shù)據(jù)庫(kù)壓力也大大增加。
現(xiàn)在處理大量并發(fā)OLTP訪問的通用方式是利用中間件技術(shù),以減少后臺(tái)數(shù)據(jù)庫(kù)的負(fù)擔(dān),降低頻繁的數(shù)據(jù)庫(kù)連接與斷開帶來的系統(tǒng)開銷,縮短事務(wù)處理的時(shí)間,提高數(shù)據(jù)訪問的效率,同時(shí),利用交易中間件,還可以保證交易處理的完整性,避免可能引起的數(shù)據(jù)不一致。但在IVR系統(tǒng)中使用中間件和中間件的傳統(tǒng)使用方式有所不同。傳統(tǒng)上中間件的使用是單客戶端——單訪問,而在IVR中有可能是單客戶端——多并發(fā)訪問,這種不同給整個(gè)系統(tǒng)的實(shí)現(xiàn)帶來了挑戰(zhàn),只有采用特定的手段,才能使兩者緊密結(jié)合在一起,形成一個(gè)高性能的IVR系統(tǒng)。
當(dāng)前流行的優(yōu)秀中間件有BEA TUXEDO,IBM TXSeries,TONG LINK/EASY等產(chǎn)品,本文僅對(duì)BEA TUXEDO在IVR中的使用進(jìn)行闡述。
IVR系統(tǒng)的實(shí)現(xiàn)方式
下面是當(dāng)前流行的IVR實(shí)現(xiàn)方式(以單機(jī)900線的IVR為例):
1. 單線程實(shí)現(xiàn)
此方式利用了有限狀態(tài)機(jī)的原理,利用一個(gè)線程不斷地依次監(jiān)控話路的狀態(tài),并執(zhí)行相應(yīng)的操作,并完成其狀態(tài)的遷移。要使一次輪詢的時(shí)間足夠小,程序中執(zhí)行的單個(gè)操作以及狀態(tài)的遷移,都必須只占用極短的時(shí)間,也就是說,程序中只能使用非阻塞(異步)的操作方式。
2. N線程實(shí)現(xiàn)
該實(shí)現(xiàn)方式和單線程方式的原理是一樣的,只是基于系統(tǒng)穩(wěn)定和處理能力方面的考慮,利用三個(gè)(或N個(gè))線程分擔(dān)處理呼叫,這樣每個(gè)線程分擔(dān)300(900/N)線語(yǔ)音呼叫。同樣,程序中只能使用非阻塞(異步)的操作方式。
3. 多線程實(shí)現(xiàn)
呼叫處理上的多線程方式和前面介紹的單/N線程方式的實(shí)現(xiàn)原理有著本質(zhì)的區(qū)別,每當(dāng)有呼叫時(shí),系統(tǒng)就產(chǎn)生一個(gè)線程,用來監(jiān)控、跟蹤用戶操作的全過程,當(dāng)呼叫結(jié)束后,此線程也結(jié)束。由于線程間互不影響,線程內(nèi)部可以采用阻塞(同步)的方式進(jìn)行數(shù)據(jù)操作。
TUXEDO編程接口
TUXEDO服務(wù)器端為了保證與多個(gè)客戶端的通信,為每個(gè)客戶端建立一塊獨(dú)立的連接資源,稱為上下文(Context);而客戶端本身也分配了專用的資源,用來存儲(chǔ)發(fā)送/接收的數(shù)據(jù)。在新版的TUXEDO中,每個(gè)Context分別對(duì)應(yīng)一個(gè)User License。
需要特別注意的是,TUXEDO對(duì)每個(gè)應(yīng)用連接的訪問請(qǐng)求進(jìn)行了限制,具體來說,就是在一個(gè)Context上,未完成的訪問請(qǐng)求數(shù)目不能超過50個(gè),如果到達(dá)了50個(gè),后續(xù)的請(qǐng)求就會(huì)返回“Elimit”的錯(cuò)誤,直到請(qǐng)求隊(duì)列長(zhǎng)度小于50為止。
1.單線程與多線程模式
在TUXEDO中,涉及單線程還是多線程的關(guān)鍵API是tpinit,主要作用是使Server端分配相應(yīng)的資源,并建立連接。涉及到的API定義如下:tpinit(),tpgetctxt(),tpsetctxt()。
(1)單線程/進(jìn)程
在單線程/進(jìn)程模式下,通過調(diào)用tpinit,使Server端為每個(gè)Client端建立一個(gè)獨(dú)立的Context。如圖1所示,每個(gè)客戶端都利用一個(gè)單獨(dú)的連接與服務(wù)器進(jìn)行通信,獨(dú)享一個(gè)請(qǐng)求隊(duì)列。
在單線程/進(jìn)程的模式下,TUXEDO API的使用不需要任何專門設(shè)置:
tpinit( (TPINIT *)NULL) //建立連接
(2)多線程
在多線程模式下,調(diào)用tpinit就Server端為每個(gè)線程建立一個(gè)獨(dú)立的Context。如圖2所示,每個(gè)線程利用一個(gè)單獨(dú)的連接與服務(wù)器進(jìn)行通信,獨(dú)享一個(gè)請(qǐng)求隊(duì)列。
在多線程的模式下,TUXEDO API的使用按以下步驟進(jìn)行:
Ⅰ.在父進(jìn)程中分配tpinit參數(shù)空間:
tpinitbuf = tpalloc(TPINIT, NULL, TPINITNEED(0));
Ⅱ.在父進(jìn)程中設(shè)置多線程(多上下文)標(biāo)記:
tpinitbuf->flags = TPMULTICONTEXTS;
Ⅲ.在線程中建立與Server連接,分配獨(dú)立Context資源: tpinit(tpinitbuf);
Ⅳ.在線程中保存Context資源句柄:tpgetctxt(&ctxt, 0);
Ⅴ.在線程中設(shè)置此線程使用的Context資源:tpsetctxt(ctxt, 0);
Ⅵ.線程中繼續(xù)其他API使用,使用方式不受影響。
注:TUXEDO7.1(含)以后的版本,才支持此多線程模式。
(3)偽多線程
所謂偽多線程模式,是指整個(gè)應(yīng)用利用了多線程機(jī)制,在每個(gè)線程中也調(diào)用tpinit建立了與TUXEDO Server端的應(yīng)用連接,但是,實(shí)際上Server端并沒有為每個(gè)線程建立一個(gè)獨(dú)立的Context,而是所有線程共享一個(gè)Context資源。如圖3所示,所有線程都利用一個(gè)共享的連接與服務(wù)器進(jìn)行通信,共享一個(gè)請(qǐng)求隊(duì)列。
2.同步/異步調(diào)用模式
TUXEDO的請(qǐng)求/響應(yīng)方式有同步和異步兩種。同步方式中,請(qǐng)求方要一直等待到有響應(yīng)后,再執(zhí)行其他操作,也稱為阻塞方式; 異步方式中,請(qǐng)求方發(fā)送出請(qǐng)求后,立即得到一個(gè)響應(yīng)句柄,繼續(xù)執(zhí)行其他操作,在合適的時(shí)候,再利用響應(yīng)句柄,得到此請(qǐng)求的響應(yīng)結(jié)果,也稱為非阻塞方式。
涉及到API定義如下: tpcall(),tpacall(),tpgetreply()。其中,tpcall是同步調(diào)用方式,tpacall是發(fā)起異步請(qǐng)求,tpgetreply是得到異步請(qǐng)求的結(jié)果。
需要注意的是,只有將tpacall和tpgetreply的參數(shù)flags設(shè)置為TPNOBLOCK,才能實(shí)現(xiàn)真正的非阻塞方式,否則,僅僅能夠?qū)崿F(xiàn)發(fā)送請(qǐng)求和取結(jié)果的異步分離,不能保證請(qǐng)求和取結(jié)果兩個(gè)動(dòng)作本身的非阻塞化。
前面我們提到,TUXEDO對(duì)每個(gè)Context上未完成的訪問請(qǐng)求數(shù)目進(jìn)行了限制,不能超過50個(gè),這個(gè)限制對(duì)于同步/異步方式同樣有效,即未完成的tpcall的數(shù)目,或者已經(jīng)tpacall成功,但是未用tpgetreply成功取回結(jié)果的數(shù)目,都不能超過50個(gè)。
IVR與TUXEDO的結(jié)合
1. IVR單線程實(shí)現(xiàn)
在單進(jìn)程/線程IVR中,由于只有一個(gè)進(jìn)程/線程,所以,利用TUXEDO的單線程/進(jìn)程方式即可,考慮到數(shù)據(jù)訪問的速度不可能一直穩(wěn)定在毫秒級(jí),所以,必須利用TUXEDO真正的異步調(diào)用模式,保證整個(gè)IVR系統(tǒng)輪詢和狀態(tài)遷移的時(shí)效性。
這里要注意900線的IVR存在一個(gè)Context只能對(duì)應(yīng)50個(gè)未完請(qǐng)求的限制。但900線IVR中,超過50個(gè)并發(fā)TUXEDO請(qǐng)求的可能性是存在的,而且在系統(tǒng)繁忙階段,一旦系統(tǒng)性能稍有下降,后臺(tái)數(shù)據(jù)庫(kù)操作時(shí)間超過3~5秒,在這段時(shí)間內(nèi),累積的tpacall請(qǐng)求超過50個(gè)的可能性非常大。
因此,對(duì)應(yīng)一個(gè)大規(guī)模的IVR系統(tǒng),如果利用單線程來實(shí)現(xiàn),在其中又結(jié)合了TUXEDO, 由于不能突破50個(gè)的限制,很難提供高效、穩(wěn)定的實(shí)現(xiàn)方案。
2. IVR N線程實(shí)現(xiàn)
在N線程 IVR中,可以利用TUXEDO的單線程和多線程方式,甚至可以利用偽多線程方式,同樣,必須利用TUXEDO真正的異步調(diào)用模式。
如果利用TUXEDO單線程或者偽多線程方式,數(shù)字對(duì)比仍然是“900∶50”,和單線程IVR一樣的問題還會(huì)出現(xiàn)。如果我們利用TUXEDO多線程方式,數(shù)字對(duì)比就是“900∶N*50”,這樣,就可以解決單線程IVR中遇到的不能突破50個(gè)請(qǐng)求的限制問題。因此,對(duì)應(yīng)一個(gè)大規(guī)模的IVR系統(tǒng),如果利用N線程實(shí)現(xiàn),在其中結(jié)合使用TUXEDO多線程方式,由于將限制擴(kuò)大到了N*50,所以,系統(tǒng)繁忙階段,也能夠保證提供出高效、穩(wěn)定的實(shí)現(xiàn)方案。
3. IVR多線程實(shí)現(xiàn)
在多線程IVR中,同樣可以利用TUXEDO的單線程、多線程、偽多線程方式,根據(jù)我們對(duì)多線程IVR的分析,各線程相對(duì)獨(dú)立,互不影響,利用TUXEDO的同步調(diào)用模式就可以了。
如果利用TUXEDO單線程或者偽多線程方式,我們?nèi)匀粫?huì)遇到“請(qǐng)求”限制問題。如果利用TUXEDO多線程方式,則可以解決“請(qǐng)求”限制問題,但是,各線程頻繁地TPINIT、TPTERM會(huì)占用系統(tǒng)資源,而且多線程生成的多Context,并發(fā)占用了大量的license,如果license數(shù)量是60,那么這時(shí)遇到的問題將是license限制,購(gòu)買大量的license也就意味著投資的增加,否則,系統(tǒng)繁忙階段,就不能提供穩(wěn)定的服務(wù)。
通過分析,我們發(fā)現(xiàn),每線IVR對(duì)應(yīng)一個(gè)線程,占用一個(gè)Context,獨(dú)享50個(gè)請(qǐng)求的限制,非常浪費(fèi),可以考慮多個(gè)線程共享一個(gè)Context。
我們可以這樣實(shí)現(xiàn): 在父進(jìn)程中通過9次tpinit可得到9個(gè)Context訪問句柄,將900線IVR分成9組,每組100線,每100線共享一個(gè)Context,在這100線各自對(duì)應(yīng)的線程中,先調(diào)用tpsetctxt,指定此線程利用的Context,這樣就形成“100∶50”的比例關(guān)系,完全可以保證系統(tǒng)在繁忙階段提供高效的服務(wù)。IVR多線程實(shí)現(xiàn)方式如下圖所示:
在多線程的模式下,TUXEDO API的使用需要專門步驟:
(1) 在父進(jìn)程中分配tpinit參數(shù)空間:
tpinitbuf = tpalloc(TPINIT, NULL, TPINITNEED(0));
(2) 在父進(jìn)程中設(shè)置多線程(多上下文)標(biāo)記:
tpinitbuf->flags = TPMULTICONTEXTS;
(3) 在父進(jìn)程中建立與Server連接,分配獨(dú)立Context資源:tpinit(tpinitbuf);
(4) 在父進(jìn)程中保存Context資源句柄:
tpgetctxt(&ctxt1, 0);
(5) 重復(fù)N次步驟(3)和(4)。
(6) 在某組IVR線程中都設(shè)置線程使用的共享Context資源:tpsetctxt(ctxtN, 0);
(7) 線程中繼續(xù)其他API使用,使用方式不受影響。
結(jié)論
由于IVR系統(tǒng)實(shí)現(xiàn)方式的不同,TUXEDO中間件使用方式的不同,系統(tǒng)規(guī)模的不同,為我們的系統(tǒng)設(shè)計(jì)提供了眾多組合的可能,同時(shí),也只有了解這些不同的實(shí)現(xiàn)方式,才能在眾多組合中選擇出有效方案。
通過以上介紹,我們知道,從功能上說,大容量IVR系統(tǒng)與TUXEDO等中間件進(jìn)行結(jié)合是一種趨勢(shì)。從系統(tǒng)實(shí)現(xiàn)上,我們也可以相信,IVR與TUXEDO一定可以提供一種有效的實(shí)現(xiàn)方式組合,架構(gòu)出高效、穩(wěn)定、投資節(jié)省的IVR系統(tǒng)。
計(jì)算機(jī)世界網(wǎng)(www.ccw.com.cn)
相關(guān)鏈接: