詞語解釋
SLEE Service Logic Execution Environment 業(yè)務邏輯執(zhí)行環(huán)境
Service Logic Execution Environment -- 業(yè)務邏輯執(zhí)行環(huán)境
SLEE 是一個容器標準,目標是提供移動技術與企業(yè)技術之間的整合。該標準類似于 EJB,不過是用于各種面向事件的應用程序,例如 IP 電話服務、分布式交互模擬/監(jiān)控/控制等。Mobicents 是第一個而且是目前唯一開源并被 JAIN SLEE 1.0 認定的產品,它從交換協(xié)議構造上基于 JAIN-SIP。
前言
Mobicents 是一個專業(yè)開源的 VoIP 中間件平臺。Mobicents 是第一個而且是目前唯一開源并被 JAIN SLEE 1.0 認定的產品,它從交換協(xié)議構造上基于 JAIN-SIP。
JAIN SLEE 是一個以事件為驅動的中間件,采用了各個服務單元(Sbb)消息機制,減少了在事物處理上的等待延遲,其工作方式是從外部協(xié)議資源掃描事件狀態(tài),然后將這些事件遞交到各個處理單元去,可以以它為核心設計成網關和網守,軟交換上層的應用服務器,媒體服務器等多種設備,同時適配多種交換協(xié)議。
以下分成 10 個部分來對 Mbicents-SLEE 進行詳細介紹:
1. 資源適配器(Resource Adaptor)體系;
2. JAIN-SIP;
3. 事件和事件類型(Events),事件引導(Routing);
4. 行為實體(Activity)和行為實體上下文(Activity Context);
5. SBB部件和SBB實體;
6. 數據供應(Provisioned Data);
7. SLEE的一些工具(facility);
8. 服務和部署(Service and Deployment);
9. 應用范例(SIP代理服務器,信令網關);
10. 使用elipslee來進行SBB的開發(fā);
下面展示了Mobicents Docs中的一個體系分布圖:
圖1 . SLEE的體系分布圖
1> SBB 服務管理單元(Sbb Service Management):這個部分面向上層的應用,也就是 Service Block Building 的構造和部署的主要部分,其中包含了對象持久性(Persistence),類似 EJB 的CMP 一樣,對數據對象的持久性(包括生存期和數據庫連接等等)由 SLEE 容器自動完成的,SBB 分成 Sbb 實體和 Sbb 對象兩個組成。對整個 Sbb 的服務管理單元來說,包含有 Sbb 工廠,持久性管理,Sbb 對象池管理,服務部署者,這些對于實際的使用者而言是不可見的。用戶的應用部署文件是 sbb.jar,而用戶服務描述是 service.xml。
2> Sbb 運行環(huán)境(Sbb Runtime):Sbb 運行環(huán)境就是Sbb的執(zhí)行體,核心是事件導向單元--Event Router,(獲得事件并且分配導入到指定的 Sbb 中去),SLEE 端點管理(連接資源適配器產生事件送達端點),通過上下文(Context)方式來實現各個實體之間的聯(lián)系(參看圖7),和 Sbb服務管理單元之間的接口是 ActivityContext(以下為活躍實體或者行為實體上下文),用于表示獨立的事件接口;和資源適配器之間的接口是 Activity,也就是行為實體,具體事件的封裝,例如 SIP 的注冊事件(SIP Register),這個事件會引發(fā) Sbb 的相關注冊服務(例如 RegisteraSbb);另一個接口是 SLEE Activity,這個是 SLEE 內部的行為實體,例如一些內部的工具產生的行為實體,例如定時器事件(Timer Event)和用于調試的 Trace 事件。
3> SLEE 的一些工具:和 J2EE 中的工具一樣,提供了一些工具來使用,工具在 SLEE 中的定義是一些標準的功能組件,他們的提供了一些預定義的接口為應用提供服務,其中包括了Adress,Profile,Alarm,Naming。
4> 資源適配器(RA),用于具體的協(xié)議在SLEE上的封裝,例如(SCAP,SS7,SIP,MGCP,H.323)當然也可以是自己的私有協(xié)議,封裝的方式可以參看Mobicents官方網站的一些介紹,協(xié)議和SLEE Run-time的接口就是具體的行為實體,也就是事件的封裝, 用戶定義的資源適配器部署文件是RA.jar在本文中SIP資源適配器的部署文件是sip-local-ra.jar和sip-type-ra.jar。
一. 資源適配器(Resource Adaptor)體系
1.Mobicents資源適配器的概述以及定義和應用模式:
備注:Mobicents 中的資源適配器提供了非常方便的接口以便實現各種協(xié)議資源在 SLEE 上的組裝,目前在 1.0a 和 1.0b中都只完成了 SIP 協(xié)議和 TCAP 協(xié)議,事實上后者的意義在于將 SIP 模擬作為 NSP 層而采用的應用層協(xié)議。
資源適配器主要是指的網絡設備和協(xié)議棧本身,和狀態(tài)機的有連接協(xié)議,例如我們在下面將詳細介紹的JAIN-SIP 以及其他支持JAVA語言的呼叫代理協(xié)議, JCC API,Parlay/OSA 等。
資源適配器分成三個范疇,
a. 資源適配器類型(Resource adaptor type);
b. 資源適配器對象;
c. 資源適配器實體(entity);
2. 協(xié)議棧的資源在 SLEE 上的綁定:
在 Mobicents1.0a 上綁定了兩個資源實體就是 JAIN-SIP 的資源實體(SIpRA),和 JAIN SLEE TCK,下面我們根據它的第三方范例 (Third-Party) 注冊機(Registar)來簡單介紹它的資源綁定模式:
首先是協(xié)議棧描述,就是 SIP 在 Sbb 服務上的描述,在 sbb-jar.xml 文件中會體現,這個文件是 SBB 的部署文件,可以理解為 J2EE 中的 ejb-jar.xml 文件。
如Registrar中的:
//JAIN SIP的資源適配器類型
在JNDI中的實體上下文工廠的綁定,SBB的開發(fā)者通過lookup來調用
slee/resources/jainsip/1.1/acifactory
定義了SBB所依靠的一個定義資源適配器對象名稱在JNDI上綁定的類型
slee/resources/jainsip/1.1/provider
定義了resource-adaptor-object-name中表示的資源實體對象SIPRA
SIPRA
其中:
資源適配器對象名稱就是
資源適配器實體的名稱
call %JBOSS_HOME%inSleeCommandInterface.bat -createRaEntity "ResourceAdaptorID[jainsip#NIST#1.1]" SIPRA
類型名稱是:
3.協(xié)議棧工廠的調用 :
在Sbb中調用lookup() 方法時都會執(zhí)行一次新查找獲得資源實體工廠,這里會返回工廠實例SipFactoryProvider,
fp = (SipFactoryProvider) sbbEnv.lookup("slee/resources/jainsip/1.1/provider");
SIP協(xié)議工廠,用于生產SIP的消息體(Message),SIP的頭(Header),SIP的JAIN-SIP的ServerTransaction/ClientTransaction(交易的狀態(tài)機,和每次會話--Cseq對應),SIP消息發(fā)送發(fā)送者和偵聽事件的偵聽點。
4.行為實體上下文工廠的調用:
org.mobicents.slee.resource.sip.SipActivityContextInterfaceFactory
查找一個行為實體上下文接口工廠:
acif = (SipActivityContextInterfaceFactory)
myEnv.lookup("slee/resources/jainsip/1.1/acifactory")
SBB需要對資源實體活動體上下文接口工廠進行訪問獲得行為實體的接口,例如發(fā)送一個SIP的消息的有狀態(tài)消息(INVITE消息)那么sbb就需要獲得一個行為實體上下文接口,與創(chuàng)建的Sbb和這個行為實體接口綁定,維持這個有狀態(tài)會話。
關于行為實體的概念,是SLEE中的重要的概念,對于它的理解可以看作對應于一個SIP的會話狀態(tài)機,一般用SIP消息中的Branch ID作為一個"種子"來生成一個行為實體的狀態(tài)機,根據這個會話將不同的事件導向到對應的SBB中,在后續(xù)將詳細介紹,的上下文(ActivityContextInterface)是可以在Sbb間共享的,通過共享可以獲得消息的參數,如via,to,from,contact,CallID,Cseq;在SLEE中規(guī)定定義一些Set/Get方法來對這些參數進行訪問,參看注冊機中的RegistrarActivityContextInterface中的Set/Get接口方法。
二.JAIN-SIP的簡單介紹
1.什么是JAIN-SIP:
綜合網絡的Java 應用編程接口(JAIN,Java API for Integrated Networks)是一組基于Java技術的API,這些接口將業(yè)務可移植性、網絡聚合以及安全的網絡接入引進電話網和數據網絡,使得在Java平臺上快速開發(fā)下一代電信產品和服務成為可能,在Mobicents中以Jain-sip作為Resource Adaptor。
在JAIN SIP API體系結構中,為所有SIP消息的報頭定義了類,并借助提供者/監(jiān)聽者接口,將用于處理報文的JavaBeans體系結構的接口定義為事件。
Jain-SIP是一個標準的JAVA的SIP協(xié)議棧的interface,它分成以下幾個部分:
a. 標準的協(xié)議棧的接口;
b. 標準的SIP消息接口;
c. 標準的SIP消息狀態(tài)機和事件的觸發(fā)。
2. 從JAIN-SIP到SLEE中的事件傳導機制:
以下仍然以Registar為例子簡要介紹SLEE中對SIP消息(或者是事件)的管理以及處理句柄的調用。見圖2,分成事件和協(xié)議兩個部分:
事件部分:也就是RFC3261中的事件信息, REGISTER,INVITE等,EventRouter將事件導向到對應的的SBB中的事件處理回調中去(onRegistar),processinitialevents被EventRouter調用,目的是找到處理對應事件的SBB,RegisterSbb是處理對象的SBB。
協(xié)議部分:SIP Stack也就是協(xié)議棧的部分, SipResourceAdaptor是Resource Adaptor的SIP實例化,Event表示了當前的SIP會話的行為實體,從這里可以獲得Jain-SIP的服務端會話交易用于處理偵聽消息的處理句柄(在下面會有介紹),Event Type是JAIN-SIP消息類型,EventObject是傳遞到SBB實體時候對JAIN-SIP消息進行的封裝。
圖2.一個注冊機的事件交易過程
3.JAIN-SIP中的重要類介紹:
1> Siplistener
概述:
這個類代表SIP協(xié)議的負責偵聽的應用程序端,這個接口定義了一個偵聽端,接收處理從SipProvider提交的SIP事件消息,是一個抽象的偵聽線程。
結構:
每個SIPStack或每個IP地址對應一個的Siplistener,而Siplistener與SipProvider的關系是一對多的關系。
2> SipFactory
SIPFactory是一個單類,用單一方式得到這個SipStack應用的執(zhí)行權。SIPFactory單一的實例能用得到實例的方法(或者Singleton)而被得到。通過在SIPFactory里調用合適構造方法,一個代表被叫端的對象能從SIPFactory得到。創(chuàng)造一個被叫的SipStack,這樣應用將可以調用SipStack中的方法。
3> ServerTransaction
概述:
ServerTransaction可以通常被理解為一個會話狀態(tài)機,SipProvider用來處理接收SIP事件和消息序列,將接收到消息發(fā)送到SipListener(偵聽方法)的processRequest或者processResponse回調,通過用戶代理服務器發(fā)送回應信息給應用程序。這個類讓應用程序能發(fā)送一個回應對應SipListener收到的請求。
方法:
ServerTransaction中的方法:
sendResponse
應用希望發(fā)送一個響應時候,它創(chuàng)立一個來自MessageFactory創(chuàng)造的回應,然后回應傳送到ServerTransaction的sendResponse方法。
4> ClientTransaction
概述:
ClientTransaction應用可以理解為發(fā)送INVITE信息到UAS。ClientTransaction也用從SipListener接收到的回應進行匹配。和ServiceTransaction相對應。
方法:
ClientTransaction的方法:
Request createAck()
通過ClientTransaction創(chuàng)造一個關于當前的請求的正確應答。
void sendRequest()用于發(fā)送創(chuàng)建的請求消息。
這個類的調用意味著上層的應用是UAC。
圖3. JAIN SIP 結構和狀態(tài)機體系
圖4 JAIN-SIP,Resource Adaptor以及SbbEntity之間調用關系
回頁首
三. 事件和事件類型(Events),事件引導(Routing):
1. 事件和事件類型:
在SLEE中和資源適配器中,事件代表外部到達的消息,向外部發(fā)送的消息,某些狀態(tài)的遷移(例如定時器的時間到),其他的SBB使用Activity Context共享狀態(tài)。這就減少了SBB實體間直接對事件的調用,其他的SBB實體可以對事件達到同時處理,這個是和EJB最大的不同的地方。
2. 事件源:
a 外部的協(xié)議棧資源(SS7 stacks, SIP stacks,記費系統(tǒng) ...,Profile觸發(fā))
b SLEE的服務容器內的部件(定時器、服務觸發(fā)、數據源觸發(fā))
c 自定義的觸發(fā)源(自定義事件)
3.SLEE中的事件描述:
在有多個資源的時候,這些資源所觸發(fā)的事件都是放在event-jar.xml和slee-event-jar.xml兩個文件中的, 而SBB所感興趣的事件,則放在sbb-jar.xml中定義了,以及還包括了一些Sbb需要知道的消息細節(jié),例如消息方向,觸發(fā)順序和初始化參數:
initial-event表示初始事件,也就是事件會觸發(fā)實例化一個根Sbb,Root Sbb,就是說這個消息可能是一個消息狀態(tài)機中的第一個消息。Root Sbb定義在后續(xù)章節(jié)會更加詳細的看到。
event-direction表示事件是發(fā)出(Fire)還是接收(Receive)來觸發(fā)SBB.
event-type-ref這里表示的相關事件的類型單元,其中event-type-name為事件的名字。
4.SLEE中的事件處理過程:
在SBB中的事件處理句柄是在事件用"On"+ event-name表示,例如在注冊機例子中的RegiterEvent的處理句柄為OnRegisterEvent。
帶入參數:
"on"+
行為實體
SBB對象作為一個事件消費者通過行為實體了解事件,activity是帶入處理句柄的一個參數,是代表行為實體的接口activity interface,關于行為實體的一些來歷在前面做了介紹。從行為實體接口可以獲得從對端發(fā)送的消息;從一個Mobicents中的Activity可以獲得一個行為實體的調用--ServerTransaction,
另外一個帶入的參數是這個SBB實體感興趣的消息,這個消息是被SLEE自動導入到SBB中去的,這個消息事件是JAIN-SIP中javax.sip.RequestEvent包的消息類,從這個類中可以得到SIP消息的一些具體信息。
圖5 Sbb和活躍實體以及上下文之間的關系圖
回頁首
四.行為實體(Activity)和行為實體上下文(Activity Context)
1.行為(Activity):
在SLEE中對行為如下定義:一個相關事件流的抽象,也是一個根據狀態(tài)變化而發(fā)出事件的有限狀態(tài)機
2. 實體上下文(Activity Context)
SLEE中定義一個ActivityContext是資源實體在SLEE中的表現,SBB實體從ActivityContext中獲得事件,可以把它理解為一個事件總線,SBB要獲得事件需要綁定到事件總線上去,SBB實體根據它綁定的不同的實體上下文獲得事件觸發(fā)相應的動作,并且做出相應的響應動作;而實體上下文接口(ActivityContextInterface)就是也就是SBB對實體訪問的接口,在使用過程當中Sbb一般會根據定義自己的狀態(tài)在ActivityContextInterface上增加一個封裝。
3.范例:
下面我們看以下SIP Registrar中實體和實體上下文的例子:
1> 對于一個JAIN-SIP的協(xié)議棧實體來說,實體對象是ServerTransaction和ClientTransaction(參看圖5),這兩個交易是針對特定呼叫的,每個呼叫指定一個特定對象。
一個新的SIP呼叫--Register消息進入SLEE,這個呼叫被某個Sbb所感興趣,
2> SIP呼叫實體傳遞一個SIP的消息(REGISTER)通過ActivityContext傳遞到SBB實體中去,由onRegisterEvent(RequestEvent event, ActivityContextInterface ac)來進行處理,
3> 從ActivityContextInterface獲得實體ServerTransaction:
ServerTransaction serverTransactionId = (ServerTransaction)ac.getActivity();
4> 從SBB中根據這個狀態(tài)機創(chuàng)建一個新的SIP呼叫,并且發(fā)送這個請求:
this.clientTransaction = sipProvider. getNewClientTransaction(request);
clientTransaction.sendRequest();
5> 為了接收這個呼叫中一些消息的內容,需要綁定當前的SBB實體到ActivityContext接口上,為了將當前SBB行為實體上下文和SIP的行為實體上下文接口結合起來,SLEE規(guī)范中提供了一個asSbbActivityContextInterface方法將SIP(或者其他)的行為實體的接口作為參數帶入到SBB的行為實體上下文中,才可以作為提供了一個SBB可以訪問的共享行為實體上下文:
ActivityContextInterface aci=SipActivityContextInterfaceFactory.getActivityContextInterface()
RegistrarActivityContextInterface regACI = asSbbActivityContextInterface(aci)
//以下是對SIP消息頭的設定,將該特定的SIP消息和ActivityContextInterface綁定起來,
便于Sbb實體進//行跟蹤,例如針對該消息的超時事件,這個在注冊機例子中有詳細的使用過程,
regACI.setSipAddress(sipAddress);
regACI.setSipContactAddress(sipContactAddress);
// callId and cseq used to identify a particular registration
regACI.setCallId(callId);
regACI.setCSeq(cseq);
regACI.attach(getSbbLocalObject());
五.SBB部件和SBB實體
1. SBB實體定義:
1> SBB定義為服務組件,封裝了服務邏輯和相關的觸發(fā)狀態(tài)。
2> SBB組件需要包含:
a> Sbb組件產生或者是接收的事件。
b> 單個實例化的狀態(tài):每個實例化域的狀態(tài)都被收錄到SLEE集中管理的CMP容器
c> 事件處理句柄: Sbb組件中包含的,每個它所接收到的事件類型的一個事件處理方法。
d> 本地接口:Sbb中定義一個Sbb本地接口,它定義有可能同步被調用的Sbb組件(是在同一個SBB Tree上生成的Sbb才可調用的接口,下面也將詳細介紹)的操作。
e> 子關系成分:SBB成分可能包括零個或者多個子SBB組件
f> 可共享性:SBB組件通過Activity Context的方式與其他SBB組件共享狀態(tài),SBB組件定義。
g> 一個JAVA接口(Activity Context Interface),這個接口定義為了得到和設置這些特性所進行的安全訪問操作。
例子:
在Mobicents中有一個簡單的SIP代理網關范例JainSipProxySbb可以參看,和前面所說的RegistrarSbb做為它的子Sbb,可以通過他們來了解整個Sbb構造。
2. 根SBB和子SBB
a.SBB 實體(Sbb Entity)
SBB實體是SBB組成的一個實例。SBB實體是一個代表著實例持久性狀態(tài)的實體。
b.SBB子實體和根SBB實體的定義
在運行時間內,SBB實體可能創(chuàng)造多個SBB子實體。由于SBB實體可能被創(chuàng)造,所以它是一個單一的父目錄。以圖6為例SBB實體子目錄是一個被管理的非循環(huán)的樹形表。
圖6詳細說明了父和子Sbb之間的關系,它也顯示了SLEE是所有根SBB實體合理的父親。
在SLEE中定義,在父的SBB訪問子SBB采用"獲得子SBB關系對象"的方法,父的SBB實體使用getSBBLocalObject從SbbContext對象中,獲得一個SBB的本地對象,父SBB實體也將這個本地的SBB對象傳遞到的子SBB中去,例如某些情況下,在子SBB的本地接口中定義一個方法給父SBB用來傳遞消息到子SBB中去。
下面我們用一個簡單的子SBB的例子來說明這個問題,請參看ProxyBaseProxySbb.java 在這里父 SBB 是 BaseProxySbb 中處理各種 SIP 呼叫的消息,其中對 Register 事件的消息是由子 SBB Registera 來進行處理這個 SIP 消息的,換句話來說,有一個子的 SBB 應用嵌入在父 SBB BaseProxySbb 處理中。
1> 父 Sbb 獲得子 Sbb 的關系:
public void onRegisterEvent(RequestEvent event, ActivityContextInterface ac) {
getDefaultSbbUsageParameterSet().incrementNumberOfRegister(1);
trace(Level.INFO, "Received REGISTER request, class="+event.getClass());
try {
// is local domain?
//在父SBB中了使用了一個方法來創(chuàng)建子的SBB關系,然后并且通過這個子關系創(chuàng)建子SBB的本地對象,這個
//本地對象提供了子SBB可以調用的方法,而且這個子SBB在sbb-jar.xml
中需要對這個獲得子SBB的方法進行
//定義
ChildRelation relation = getRegistrarSbbChild();
… …
2> 子Sbb在sbb-jar.xml中的定義
子SBB在sbb-jar.xml中需要對這個獲得子SBB的方法進行定義:
com.opencloud.slee.services.sip.proxy.JainSipProxySbb
父SBB使用這個方法來創(chuàng)建子SBB實體,
定義了子SBB,這里表示最后調用的子SBB為RegisteraSbb
定義了獲得子關系的方法名字,調用這個方法可以得到SBB子關系,通過調用子關系可以創(chuàng)建這個子SBB的本地對象
…
3> 創(chuàng)建一個子 Sbb 的調用過程:
SBB 的開發(fā)者的 SBB 調用方法一般如下,例如對當前 Reigster 事件的 ChildRelation 創(chuàng)建(creat)方法的調用,得到一個新的 SBB 實體,在調用過程中 Registera 的 sbbCreate 將被調用,這里和一個常見的 SBB 實體創(chuàng)建過程基本相同,返回的是一個以 SbbLocalObject 接口的 SBB 實體:
Public class RegistrarChildRelation implements ChildRelation {
Public sbblocalobject creat() … {
SbblocalObject local=RegisteraSbbLocalObject();
Return local ;}
}
4> 一個應用中的創(chuàng)建并且使用子 SBB 的方法:
調用子關系的創(chuàng)建方法,得到子 SBB 的實體
… …
SbbLocalObject child = relation.create();
//將當前的子SBB綁定到當前的行為實體上下文上去;
// attach child to this activity
ac.attach(child);
//把父實體從當前的上下文上分離出去;
// detach myself
ac.detach(getSbbLocalObject());
// 這樣后續(xù)的消息處理都被重定向到RegisterSbb上去了。
…. …
} catch (Exception e) {
trace(Level.WARNING, "Exception during onRegisterEvent", e);
}
}
從上述例子也可以看到事件優(yōu)先權的問題,在事件傳送過程中,父SBB實體總是在它的子SBB實體前接收同樣的事件。SBB實體的事件傳遞優(yōu)先權決定了同級別SBB實體接收事件的順序,另外在SLEE的各個實體關系中,SBB實體的事件傳送優(yōu)先權可能被改變。
3. 事件傳送優(yōu)先權
對于實體序列來說。父SBB實體總是在它的子SBB實體前接收同樣的事件。對于優(yōu)先級的定義大家可以參看規(guī)范中的8.5.7部分,要改變優(yōu)先級的時候會在SbbLocalObject接口的setSbbPriority方法。
4. SBB 實體之間的并行刪除:
SBB實體可以刪除,通過在SbbLocalObject 接口或ChildRelationObject接口調用刪除的方法。當執(zhí)行刪除時候,SLEE將會刪除SBB的實體和所有SBB父實體后代。
5. SBB 對象
SBB對象是SBB所擴展的抽象類SLEE之一個實例,和SBB實體所不同的是SBB的實體是邏輯的實體,而SBB對象則是一個JAVA的對象,可以被實際調用的。
6. SBB 本地接口和 SBB 本地對象
每個SBB有一個SBB本地接口。SBB的SBB本地接口是一個指定的SBB本地界面,它是由SBB開發(fā)者根據SbbLocalObject接口來進行擴展的。
SBB對象通過SbbLocalObject同步地調用目標SBB實體的SBB對象,因此可以理解SbbLocalObject就是一個Sbb對象的實例,這樣使用者可以通過GetSbbLocalObect方法獲得相關的目標對象,并且得到它的調用方法。本質上,SBB本地對象是一個應用SBB本地對象接口和代表目標SBB實體的執(zhí)行對象。當SBB對象在SbbLocalObject上調用SBB開發(fā)者定義的方法時,在Sbb抽象類中的相關方法將被Sbb對象進行調用。另外,Sbb本地對象可以在遠程過程調用的時候作為一個客戶存根對象。本質上來說Sbb的本地接口從提供了對SbbLocalObject的調用能力,通過SbbLocalObject訪問到相對應的SBB實體,這個很有點和EJB的本地接口類似。
7.SBB 的生命對象周期
當 SLEE 采用 newIstance 創(chuàng)建一個 SBB,這個時候 sbb 對象生命周期就開始了,這個時候緩沖Sbb對象,調用setsbbContext將sbbContext(也就是Sbb的上下文)對象傳入Sbb對象中,此時SIP消息工廠對象或者是地址工廠,以及SIP棧的提供者(SipProvidor)這些的對象的創(chuàng)建都在setSbbContext回調中進行。
當完成了實例化的過程以后,sbb對象將進入對象池,每個Sbb組件都有自己的對象池,例如RegistraSbb對象會進入自己的對象池中,但這個時候Sbb對象還不和任何Sbb實體相關聯(lián)。
當一個Sbb接收到一個事件并且開始進程處理過程,而某個業(yè)務邏輯調用主動調用這個服務的時候,首先會創(chuàng)建Sbb的實體(sbbEntity)例如在序列圖上看到的EnventRouteImpl這個SLEE這個內部的類就是執(zhí)行這樣的動作,在EnventRouteImpl中,首先實體暫時不和任何對象相互關聯(lián)的,幾個方法可以調用讓Sbb對象將從對象池進入Ready狀態(tài),SbbCreate和SbbActivate,前者是在使用ChildRelation對象中的create的方法或者是事件產生的時候才被調用,后者是一個sbb對象需要調用一個現有的Sbb實體上的某個方法的時候才這樣做,這種情況往往是一個沒有Sbb對象對應一個Sbb實體而進入準備狀態(tài)的時候。
對于一個處于Ready狀態(tài)的Sbb對象,它已經和具體的某個Sbb實體相關聯(lián)了,這個時候Sbb對象可以和Sbb實體之間同步暫態(tài)和穩(wěn)態(tài)的數據了,例如一個數據庫之間的同步。需要調用 SbbLaod 方法和SbbStore 方法。SbbLaod方法用數據庫中的數據刷新變量的值,SbbStore方法把變量的值寫入到數據庫中,和EJB的規(guī)范一樣,Sbb的開發(fā)者,也就是客戶端是不能直接調用 SbbLoad 方法和SbbStore 方法。
涉及到具體的業(yè)務處理的方法,SLEE要在業(yè)務處理方法調用之前調用 SbbLoad 方法刷新數據,業(yè)務處理方法執(zhí)行之后,SLEE 容器又立即調用 SbbStore 方法把數據存儲到數據庫中。,開發(fā)人員在業(yè)務處理方法中不必刷新和存儲實例變量的值,如果有興趣瀏覽SLEE的源代碼,可以看到,在一個事件到來的階段,一旦一個Sbb實體和某個Sbb對象關聯(lián)以后,將調用SbbLoad,而調用刪除或者是Roll Back方法的時候,將調用SbbStore。
刪除對象的方法EJB的生命周期非常相似,這里就不介紹了。
8.SLEE 如何刪除 SBB 實體子目錄
SLEE用附屬點(attachment count)的機制來刪除SBB實體樹,它不再附屬于任何一個行為實體,它將不再接收事件,也就被刪除了,這個機制也就是JAVA垃圾回收機制的一種擴展。
9. Sbb 的持久穩(wěn)定狀態(tài):
Sbb采用CMP域(CMP field)定義了它的穩(wěn)定狀態(tài),CMP將持久保存的管理交給SLEE,SLEE規(guī)范中定義的CMP的體系是基本上基于Java EJB2.0規(guī)范中,它們之間的不同可以參看規(guī)范的6.5章節(jié)。
10.服務的定義(service.xml):
在SLEE里被展開的服務展開描述定義一個展開/管理的配置文件?梢詤⒖碢roxy中的service.xml
圖7. 本圖表示了一個外部資源如何將一個消息轉交給Sbb處理的過程,從圖中可以看到SLEE的端點獲得了事件以后傳遞到核心事件處理系統(tǒng)(Event Routing)中,然后轉交給事件處理的回調過程。
六.數據供應(Provisioned Data)和Profile(數據簡表)
圖8。數據供應的基本組成,從圖上看SBB從Profile Table中得到各個Profile接口,而Profile從Profile Mbean服務器獲得具體的數據內容,從Profile Management Client的角度上來看,來看是可讀寫的,而從Sbb獲得配置的角度上看,是只讀的。
1.數據供應(profile):
在SLEE中供應數據表現為闡述數據模型的profile,數據模型將profile集群到profile表中(profile table),Profile中的接口給則定義了應用程序調用的方式,一個Profile的規(guī)則包括了接口,類,和部署描述單元,用戶采用這個規(guī)則訪問profile,獲得數據信息。
2.關于Profile規(guī)格的一些元素和各自的關系:
1> 從Sbb視角上看范例和執(zhí)行流程;
我們可以下載OpenCloud的Slee的參考設計
a. 在創(chuàng)建SBB的過程中。sbbCreate中首先通過調用JNDI 的 lookup() 方法執(zhí)行查找,獲得簡表接口的實例--簡表的工具Profilefacility;
b. 利用Profilefacility簡表工具中的getProfileByIndexedAttribute方法,這個方法是Profile工具中定義的,只要應用了Profilefacility接口就可以使用到這個方法獲得相應的簡表。
帶入的參數中第一個String profileTableName是一個Profile的表名,參數的第二個String attributeName是表中profile,例如在一個表中有address,mail,name這三個Profile,第三個參數就是attributeValue,也就是指具體的特性值,例如某個連接呼叫對應的目的地址值。返回的就是PorfileID也就是每個Porfile的鑒別符。
c. 根據profileid調用getProfile從profile表中獲得profile,我們在上面介紹過一個Profile通過兩個接口繼承,這兩個接口是AddressProfileCMP,和ResourceInfoProfileCMP,SLEE是從Resource Info Profile表的各個接口中獲得資源適配器實體的相關信息,地址簡表在本例中的繼承擴展了另外的一些接口,例如用于對呼叫前轉(Call Forwarding)的地址進行設定或者提。ㄊ褂胹etForwardingAddress和getForwardingAddress的兩個方法來管理)
d. 獲得了profile后就可以調用profile接口中定義好的方法來訪問Profile資源了,例如設定或者獲得呼叫前轉地址。
2> 從管理視角上看Profile的管理過程:
ProfileManagement;一個Profile的管理,對于一個管理客戶端來說,會有一個管理客戶端(Profile Management Client)的接口,這個接口可以被網絡管理代理所調用。通過這個接口可以設定或者是獲得Profile的特性,SLEE對Profile管理對象進行實例化的時候,Profile管理對象將會緩沖,而且成為一個實時的運行對象,通過Porfile CMP接口調用持久化域中的設定和獲得的方法(Set/Get)來執(zhí)行對Profile的訪問,這個和Sbb開發(fā)者的使用是一致的。
3> ProfileMbean接口:
Profile規(guī)范中規(guī)定了采用Profile中的ProfileManagementbean類來提供管理者對Profile的訪問,更確切的說,外部的管理者調用ProfileMbean對象,ProfileMbean對象調用Profile緩沖的ProfileManagement對象,另外要注意的一點是Profile MBean類可以應用在任何JMX規(guī)范的MBean類型上,但是必須要在Mbean服務器上已經注冊的接口才可以(也就是用CreateProfile創(chuàng)建的Mbean,這里可以把Profile Mbaen理解為JMX Mbean接口的應用)
ProfileMbean的接口可以參看規(guī)范156頁的介紹;
七. 服務和部署(Service and Deployment)
總結上面所述我們總結一下基本的服務的部署模式:
和EJB類似,SBB的部署過程是基本相同的,只是服務性質服務描述上不一致,部署描述可以參看EJB的onMessage EJB的部署,部署者這個角色范例在SLEE的部署中同樣有定義,開發(fā)者必須實現所有接口的抽象實例,一般這些實例包括:
a. 生命周期內的各個回調方法;
b. 事件(包含某些SLEE內部工具產生的事件,例如TIMER)處理句柄的方法;
c. 發(fā)送消息,和獲得profile的一些抽象方法等等;
d. 獲得子SBB的方法;
e. 訪問Sbb中CMP域的一些方法;
f. 可共享的數據,例如行為實體等;
在部署服務期間所要定義的的XML文件和發(fā)布方法。
1> META-INF/sbb-jar.xml:sbb的jar文件,包含了: SBB描述符表示的是SBB的接口,類以及子類的關系,Activity Context的描述,
2> META-INF/event-jar.xml:Mobicents所感興趣的消息,這里主要是SIP消息。 SBB開發(fā)者對事件的描述部分,我們在前面已經看到了很多介紹,在部署階段,描述事件類型的Java類文件就是用該文件來進行。
3> META-INF/slee-profile-spec-jar.xml:用于對profile的類型進行定義。 在SLEE規(guī)范中定義,Profile的jar文件可以包裝一個或者多個Profile規(guī)范。
4> service.xml:定義服務。服務描述文件是表示所部署的SBB服務的文件。
5> 部署文件: deployable-unit.xml:用于對jar執(zhí)行文件進行部署,定義事件和定義服務,SBB,資源和profile將裝入SLEE。
6> resource-adaptor-type-jar.xml:用于對資源適配器類型部署的描述。
7> 使用SleeCommandInterface來完成組件的部署任務:
對于部署和應用在Mobicents中,使用了SleeCommandInterface工具,JBOSS主要是使用JMX框架的,各個組件之間采用JMX進行通訊,各個服務組件(Mbean)都以插件的方式掛接在MBean服務器上,SleeCommandInterface工具中使用了jmx/rmi/RMIAdaptor的Mbean作為服務接口,在下面我們將以創(chuàng)建實體類的方法來介紹一下掛接資源適配器的過程,其他的服務部署和這個也是類似的。
本質上SLeeCommandInterface是一個用于對JAIN SLEE容器在命令行下的部署,啟動服務,創(chuàng)建資源適配器的任務.通常而言,要啟動SLEE容器,要部署和啟動資源適配器,然后是部署和啟動SLEE,關于"SLEE命令"大家可以參看源代碼。
啟動資源適配器是由DeploySipRA.sh來進行,而在范例中啟動網關是由DeploySipProxy.sh來完成.
部署一個SIP資源適配器首先要部署(-deploy)兩個JAR文件,一個是 sip-ra-type.jar另外一個是sip-local-ra.jar,在創(chuàng)建SIP資源適配器時候,在Mobicents的根目錄下運行ant siptype和ant sipra就可以生成他們,前者包含了SIP事件和Activity的一些定義側重于資源,的后者包含了協(xié)議本身的實現
。
下一步是-createRaEntity,也就是創(chuàng)建SIP的資源適配器, resource-adaptor-jar.xml中定義了資源配置器的jar文件,和resource-adaptor-type-jar.xml不同的地方在于,前者是直接面向特定某個資源配置器的類文件,例如這里指明了。
org.mobicents.slee.resource.sip.SipResourceAdaptor
告訴了SLEE資源配置器的調用入口的類,也就是SIP協(xié)議的封裝,那么給誰調用呢,回到前面說的createRaEntity創(chuàng)建實體命令來,上面說了通過JMX的框架來完成調用創(chuàng)建的過程,首先在初始化SleeCommandInterface的過程當中,RemoteMbeanServer已經被定義為jmx/rmi/RMIAdaptor,而JNDI中的URL是SBB開發(fā)者定義的,在Mobicents中對資源適配器進行管理的是ResourceAdaptorMBean接口,而它的Mobicents中的實例化ResourceAdaptorMBeanImpl繼承了JBOSS中的StandardMBean.這個接口提供了createResourceAdaptorEntity方法來創(chuàng)建資源適配器的實體,這個接口的實例化的過程帶入的參數是當前在resource-adaptor-jar.xml中指定的SIP協(xié)議的封裝,并且使用createResourceAdaptorEntity來創(chuàng)建實體SIPRA,實體在SLEE中是以ResourceAdaptorEntity類來表示的,其部署文件中會調用該類的方法來完成進一步的實施.
最后一步,就是要使用(激活)實體SIPRA了,使用命令-activateRaEntity來進行,和上面的創(chuàng)建實體的過程一樣,同樣是利用ResourceAdaptorMBean接口的來完成的,而方法則是使用了activateResourceAdaptorEntity方法來激活,經過一系列的方法的封裝之后,最后會調用SipResourceAdaptor的start方法,創(chuàng)建偵聽者,消息工廠,地址工廠的實例。
八.應用范例(SIP代理服務器,信令網關)
我們下面以SIP代理服務器(JainSipProxy)為例子來闡述一個基本SIP應用建立的過程:
事件接收:
1. 首先是SLEE接收到一個SIP消息.
2. 這個事件是一個初始化事件--intial-event
3.如果initial-event-select-variable中規(guī)定的事件是 ActivityContext,表示初始化事件帶入的參數,
4. 當資源適配器發(fā)送一個消息到一個新的活躍實體上下文后,一個對應的服務將會初始化,Event Router可能也會創(chuàng)建一個新的子Sbb來進行處理。
5. 一個活躍實體上下文將會以一對一的方式對應一個事件,也就是Activity。
6. SIP的資源適配器將會把這個活躍實體定義為一個專門的SIP狀態(tài)機(SIP Transaction)當中網關維持的SIP會話狀態(tài)。
服務邏輯
JAIN SIP協(xié)議棧將會接收SIP消息,事件接收到以后,通過消息處理器發(fā)送到SLEE的事件引導部分EnventRouteImpl進行,這個時候,Sbb對象將要進入Ready狀態(tài)了,調用SbbCreate回調將被調用。
對于初始化的事件來說,initial-event-select表示第一個事件觸發(fā)時候將要加入的參數,我們來看這個參數在這里是Activity Context,也即是JAIN SIP事件發(fā)送到上面去的上下文,這個時候通過EnventRouteImpl選舉到convergence names,你可以理解它為一個事件的回調句柄,也就是事件的消費者,在SBB事件處理回調會調用這個句柄,并且把ActivityContext作為參數帶入。
例如這個時候事件INVITE使用onInviteEvent消息處理句柄,這個是有狀態(tài)的服務,需要代理維持狀態(tài),例如INVITE消息以及后續(xù)的Trying,Ringing,OK等消息,無狀態(tài)的如ACK消息,有狀態(tài)的消息,意味著要創(chuàng)建一個狀態(tài)機維持后續(xù)消息的狀態(tài),也就是ClientTransction和ServerTransction。這兩個狀態(tài)機都是維持會話的,而無狀態(tài)呼叫,可以消息序列的最后一個消息。
掃碼付費即可復制
X