WebSphere IMS Connector V6.2 開發計費應用

CloudSpace發表於2009-04-15

IBM WebSphere IP Multimedia Subsystem (IMS) Connector 簡介

IBM WebSphere IP Multimedia Subsystem (IMS) Connector V6.2(以下簡稱WebSphere IMS Connector)是IBM 面向電信行業服務提供平臺(Service Delivery Platform,SDP)的重要組成部分。在 IMS 架構中,它作為一箇中介伺服器,起到連線 SIP 應用程式與 IMS 核心網元的作用。 WebSphere IMS Connector V6.2 通過一系列 Web Service 介面,提供了對 OCS、CCF、HSS、CSCF 網元的支援,為使用者提供了離線/線上計費、使用者資訊管理等功能。

WebSphere IMS Connector 作為 IBM SDP 平臺最重要的 Enabler 之一,為使用者提供了離線計費(Rf)、線上計費(Ro)、使用者資訊管理(Sh)等功能。V6.2 是當前的最新版本,與上一版本最大的區別是增加了對線上計費的支援。

WebSphere IMS Connector 的架構如圖 1 所示。其中 WebSphere Application Server (WAS) 是 IBM 的 J2EE 應用程式伺服器軟體,它在 V6.1版本中以聚合容器的方式處理 SIP 和 Web 應用程式,即使用相同的容器處理這兩種應用程式構件。這種實現方式的優點是,SIP 應用程式可以訪問 Web 容器資源,如 HTTP 會話和 JNDI 物件,反之,Web 應用可以訪問 SIP API。聚合 SIP 和 Web 容器還允許建立聚合的 HTTP/SIP Web 服務。


圖 1. IBM WebSphere IMS Connector V6.2 架構

構建在 WAS 之上的 WebSphere IMS Connector 充分利用了聚合容器的優點,它以 Web 服務的方式為上層應用程式提供了訪問 Home Subscriber Server (HSS) 和 Charging Function 的能力,它是 SIP 應用程式與電信核心網路基礎設施間的橋樑。同時,Web 服務的實現方式使得 WebSphere IMS Connector 可以方便地作為 SDP 平臺的 Enabler 與其他系統整合,並且無需考慮底層通訊協議的複雜性,顯著降低了程式設計的難度。

此外,IMS Service Control (ISC) 介面元件定義了執行在 WAS 上的 IMS 應用程式與 Call Session Control Function (CSCF) 的通訊方式。它提供了基於標準的連線功能,使得部署在 WAS V6.1 上的 J2EE 應用程式與電信世界中現有的 SIP 裝置進行通訊和聯網。ISC 介面隱藏了與各種 CSCF 電信網路組成元素連線的複雜性。IBM 與多個網路裝置提供商開展了合作,以確保 WebSphere IMS Connector與 IMS 核心網路組成元素的互操作性。

WebSphere IMS Connector V6.2 計費介面

WebSphere IMS Connector 以 Web 服務的方式提供了離線計費(Rf)和線上計費(Ro)介面,並在底層實現了 Diameter 協議棧,使兩個計費介面都能夠以 Diameter 訊息的方式與 IMS 核心網元進行互動,見圖 2。應用開發人員可以使用 JAX-RPC 方式呼叫這些 Diameter Web 服務,而無需瞭解底層 Diameter 協議的複雜性。


圖 2. WebSphere IMS Connector V6.2 計費介面

這裡提到的 Diameter 是繼 RADIUS 協議之後的下一代身份驗證、授權和記帳(Authentication, Authorization, and Accounting,AAA)協議。在 IMS 體系結構中,Diameter 被廣泛用於在 IMS 實體間交換 AAA 資訊。

離線計費介面

離線計費的執行使用了 3GPP TS32.225 和 TS32.299 中定義的 Rf 介面,該介面用於執行非實時的計費操作,也即後付費方式。具體的呼叫方式是:當 Rf Web 服務介面接到IMS應用程式的呼叫請求後,會構造相應的計費請求(Accounting Request,ACR)訊息,傳送到 Charging Collection Function (CCF)報告賬戶資訊,以生成計費記錄(Charging Data Records,CDR),同時將計費應答(Accounting Answer,ACA)返回給 IMS 應用程式。

離線計費可以分為基於事件的計費(Event-based Charging)和基於會話的計費(Session-based Charging)這兩種方式。

離線計費 Rf Web 服務介面提供以下計費操作:

  • startRfAccounting(),用於啟動計費會話,AVP(Attribute Value Pair)中包含 START_RECORD 值,通常發生在當應用程式接收到初始 SIP INVITE 的 200 OK 訊息時。
  • interimRfAccounting(),用於更新會話,AVP 中包含 INTERIM_RECORD 值,通常發生在當應用程式傳送 SIP RE-INVITE 或 UPDATE 訊息時。
  • stopRfAccounting(),用於停止計費會話,AVP 中包含 STOP_RECORD 值,通常發生在當應用程式接收到一個 SIP BYE 訊息時。
  • eventRfAccounting(),基於事件的計費,AVP中包含 EVENT _RECORD 值,用於離散事件的一次性計費。
  • accountingRaw(),用於構造自定義的 AVP 值。

對 Rf Web 服務呼叫以上操作時,WebSphere IMS Connector 會將呼叫請求封裝為 Diameter 訊息,並將其傳遞到 CCF 進行記錄。這樣,開發人員並不需要具有 Diameter 協議的全面知識,而是通過在程式碼中進行幾個簡單的 Web 服務呼叫就可以完成這些工作。

線上計費介面

線上計費的執行使用了 3GPP TS 32.225 和 TS32.299 中所定義的 Ro 介面,該介面用於將計費資訊提供給 Online Charging System (OCS),從而能夠在使用者使用網路資源之前進行實時的計費操作,也即預付費方式。 Ro 介面同樣允許執行基於事件的計費和基於會話的計費。

線上計費 Ro Web 服務介面提供以下計費操作:

  • sendCCInitial(),用於啟動計費會話,AVP 中包含 START_ REQUEST 值,通常發生在當應用程式傳送 SIP INVITE、NOTIFY、MESSAGE、REGISTER、SUBSCRIBE、REFER 和 PUBLISH 訊息時。
  • sendCCUpdate(),用於更新會話,AVP 中包含 INTERIM_ REQUEST 值,通常發生在當應用程式收到 SIP INVITE、RE-INVITE 或 UPDATE 的200 OK 確認訊息時。
  • sendCCTermination(),用於停止計費會話,AVP 中包含 STOP_ REQUEST 值,通常發生在當應用程式異常中止 SIP 會話或收到 SIP BYE 時。

除此之外,Ro 介面還有一些高階功能,例如使用者許可權控制等等。 Ro Web 服務的工作方式與 Rf Web 服務一樣,但不是連線到 CCF,而是連線到 OCS 伺服器,進行線上計費。


開發計費程式

本節將以 Rf Web 服務介面為例,詳細介紹如何基於 WebSphere IMS Connector 開發簡單的離線計費程式,在後續的章節中將對該程式做一些改進。

可以使用任何 J2EE 開發工具,例如 Eclipse,來開發計費程式;為了更為方便地進行開發,建議使用 IBM Rational Application Developer (RAD) 整合開發工具或者是隨 WAS 產品附送的 Application Server Toolkit (AST);本文將以 RAD V7 為平臺進行後續介紹。

首先,在 RAD 裡新建一個 Java Project,然後,將所需 jar 包新增到該專案的構建路徑中去,如圖 3:


圖 3. 專案構建路徑

其中 com.ibm.ws.webservices.thinclient_6.1.0.jar 是開發 Web Service 客戶端所必需的庫檔案,它位於[RAD_INSTALL_PATH]\runtimes\base_v61\runtimes\ 目錄下;DHADiameter*.jar 是開發Diameter計費客戶端所必需的庫檔案,它們位於 WebSphere IMS Connector 產品安裝包(DHAImsConnectorInstallPackage_6.2.0.tar)的\installableApps\ImsConnector\client\tooling.zip 中。

接著,在這個 Java Project 中新建一個 Java Class,並在其建構函式中初始化 Rf Web 服務呼叫端點,具體參見程式碼清單1。本文涉及的程式碼片段可從文章末尾給出的連結下載。


清單 1. 初始化服務呼叫端點

// Create a new locator
DiameterRfService_SEIServiceLocator locator = new DiameterRfService_SEIServiceLocator();
URL endpointURL = 
 new URL("http://localhost:9080/DHADiameterRfWebService/services/DiameterRfService");
// Get Rf service
DiameterRfService_SEI service = locator.getDiameterRfService(endpointURL);
// Start a session based accounting
startRfAccounting(service, destinationRealm, 0, acctInterimInterval);
interimRfAccounting(service, destinationRealm, 1);	 
stopRfAccounting(service, destinationRealm, numberOfIntervals + 1);

其中 endpointURL 是 Rf Web 服務所在的 URL,通過 locator 可以獲取呼叫 Rf 介面所需要的 Stub 類(service),接著就可以在這個 service 例項上呼叫 Rf 介面的各個計費方法。如果 Rf Web 服務所在的WAS開啟了全域性安全性設定,那麼需要在服務呼叫點,即 service 例項,設定相應的使用者名稱和密碼。本段程式碼中發起了一個基於會話的計費請求,它首先呼叫 startRfAccounting 方法啟動一個計費會話;接著呼叫 interimRfAccounting 方法,以一定的時間間隔迴圈更新這個會話的計費資訊;最後呼叫 stopRfAccounting 方法結束這個會話。這三個計費方法詳見清單2。這些計費方法根據傳入的計費引數,呼叫 buildAccInfo 方法來構造計費資訊,並以這些資訊為引數呼叫相應的 Rf Web 服務,完成計費請求。這裡的計費資訊只包含了基本的計費引數,可以根據實際需要進行新增。


清單 2. 計費方法

// Start accounting
public static RfAccountingResults startRfAccounting(DiameterRfService_SEI service, 
 String destinationRealm, int recordNumber, int acctInterimInterval) throws Exception {
 RfAccountingInfo acct = buildAccInfo(destinationRealm, recordNumber);
 RfAccountingResults results = service.startRfAccounting(acct);
 return results;
}
// Interim accounting
public static RfAccountingResults interimRfAccounting (DiameterRfService_SEI service, 
 String destinationRealm, int recordNumber) throws Exception {
 RfAccountingInfo acct = buildAccInfo(destinationRealm, recordNumber);
 RfAccountingResults results = service.interimRfAccounting(acct);
 return results;	
}
// Stop accounting
public static RfAccountingResults stopRfAccounting(DiameterRfService_SEI service, 
 String destinationRealm, int recordNumber) throws Exception {
 RfAccountingInfo acct = buildAccInfo(destinationRealm, recordNumber);
 RfAccountingResults results = service.stopRfAccounting(acct);
 return results;	
}

非同步呼叫計費介面的 Adapter

IMS應用程式在處理 SIP 信令的時候有很高的效能要求,因此,在程式中發起計費請求時也需要儘快返回以處理後續操作。然而,IMS 中的計費網元,特別是 CCF,不是為了實時響應使用者操作而設計的,它們的響應速度普遍比較慢;如果採用同步呼叫的方式,很可能導致 IMS 應用程式阻塞在計費介面呼叫上,無法處理後續操作,最終導致客戶端超時。解決方法就是使用非同步呼叫介面。

目前 WebSphere IMS Connector 所提供的操作介面都是同步呼叫方式的 Web 服務介面。為了使IMS應用程式更高效地使用 WebSphere IMS Connector 所提供的 Web 服務介面,本節以 Rf 介面為例實現了非同步呼叫Rf介面的介面卡——AsyncRfAdapter。通過 AsyncRfAdapter 的適配,可以實現對 Rf 介面的非同步呼叫,從而顯著改善 IMS 應用程式的整體效能。

AsyncRfAdapter 的設計

要實現 Rf 介面的非同步呼叫,最簡單的方式是在呼叫前新建一個子執行緒,由子執行緒負責呼叫 Rf 介面。然而,如果每次呼叫都新建一個子執行緒,在高併發的情況下將導致 JVM 中存在上千個執行緒,JVM 疲於排程這些執行緒而無法正常運作。因此,需要採用執行緒池的方式複用執行緒,使執行緒的數目處於可控範圍內,同時也減少了建立銷燬執行緒所帶來的開銷。

此外,基於會話的計費要求計費訊息的傳送要符合時序邏輯,例如,在一個計費週期內,必須首先傳送 START_RECORD 訊息,接著傳送 INTERIM_RECORD,最後傳送 STOP_RECORD,這對執行緒同步提出了重大挑戰。要滿足這一要求,需要利用 FIFO 佇列對將要傳送的訊息進行排序,並且還要利用執行緒同步機制和回撥機制保證佇列中的訊息當且僅當其前驅訊息被處理完畢之後才能傳送。本文提出了非同步 Diameter 訊息介面卡 AsyncRfAdapter,其架構如圖4所示,它通過改進的多 FIFO 佇列和單執行緒池的方式,在保證計費訊息時序和效能的前提下,實現了對 Rf 介面的非同步呼叫,呼叫結果通過回撥函式輸出。


圖 4. AsyncRfAdapter 架構圖

每個連線到 AsyncRfAdapter 的 IMS 應用程式,都獨佔擁有自己的 FIFO 佇列,可以向佇列提交計費請求,所有的佇列都連線到唯一的一個工作執行緒池,執行緒池裡的執行緒通過呼叫 Rf 介面來處理各個佇列裡的計費請求,並且利用執行緒同步和回撥機制實現每個 FIFO 佇列內各元素的依次順序處理以及結果的獲取。

AsyncRfAdapter 的實現

AsyncRfAdapter 由以下幾個 Java 類組成:

1. DiameterMessage

用於封裝 Diameter 訊息,程式碼見清單3。


清單 3. DiameterMessage 類
import com.ibm.diameter.charging.util.*;
public class DiameterMessage {
 public int acrType;
 public RfAccountingInfo acrInfo;
 public DiameterMessage(int acrType,RfAccountingInfo acrInfo){
 this.acrType=acrType;
 this.acrInfo=acrInfo;
 } 
}

其中 acrType 用於描述計費訊息型別,info 用於描述 Diameter 訊息中所要包含的計費資訊。

2. DiameterListener

Diameter 非同步呼叫監聽器,用於接收回撥請求;要求實現 diameterCallback 回撥函式介面,見清單4。


清單 4. DiameterListener 介面
public interface DiameterListener {
public void diameterCallback(DiameterEvent event);
}

3. DiameterEvent

Diameter 非同步呼叫事件介面,用於獲取非同步呼叫結果;要求實現 getWorkResult 結果獲取介面,見清單 5。


清單 5. DiameterEvent 介面
import com.ibm.diameter.charging.util.RfAccountingResults;
public interface DiameterEvent {
 public RfAccountingResults getWorkResult();
}

4. DiameterWork

Diameter 非同步呼叫工作單元,實現了 Runnable DiameterEvent 介面,它將根據計費訊息的型別呼叫不同的離線計費 Web 服務,見清單 6。


清單 6. DiameterWork 類
public class DiameterWork implements Runnable,DiameterEvent{
 public DiameterWork(DiameterRfService_SEI serviceRef,
 DiameterMessage dm,DiameterListener dl) {
 this.serviceRef=serviceRef;
 this.dm=dm;
 this.dl=dl;
 }
 public void run(){
 switch(dm.acrType){
 case AccountingRecordType.START_OFFLINE_ACCOUNTING:
 this.results=serviceRef.startRfAccounting(dm.acrInfo);
 case AccountingRecordType.INTERIM_OFFLINE_ACCOUNTING:
 this.results=serviceRef.interimRfAccounting(dm.acrInfo);
 case AccountingRecordType.STOP_OFFLINE_ACCOUNTING:
 this.results=serviceRef.stopRfAccounting(dm.acrInfo);
 }
 dl.diameterCallback(this);
 }
 public RfAccountingResults getWorkResult() {
 return this.results;
 }
}

5. AsyncDiameter

非同步 Diameter 訊息處理執行緒池實現類,所有客戶端傳送的 Diameter 訊息都將由此執行緒池的執行緒非同步處理。可以通過建構函式對執行緒池的大小、佇列長度等工作引數進行配置。


清單 7. AsyncDiameter 類
public class AsyncDiameter {
 public AsyncDiameter(int min_pool,int max_pool,int timeout,int qSize){
 if(executor==null){
 queue=new LinkedBlockingQueue(qSize);
 executor=new ThreadPoolExecutor(min_pool,max_pool,timeout,TimeUnit.SECONDS,queue);
 }
 }
 public void asyncSend(DiameterRfService_SEI ep,DiameterMessage dm,DiameterListener dl){
 executor.execute(new DiameterWork(ep, dm, dl));
 }
 public int getQueueSize(){
 return queue.size();
 }
}

6. DiameterHandler

AsyncRfAdapter 的主實現類。首先,在建構函式中對 Rf Web 服務呼叫端點以及 AsyncDiameter執行緒池進行初始化。每個 DiameterHandler 例項使用連結串列儲存需要傳送的 Diameter 訊息,並且用可重入鎖對訪問連結串列的執行緒進行同步。一般情況下,使用 ReentrantLock 作為同步鎖可以獲得比 synchronized 更好的效能。同時,實現了 diameterCallback 回撥函式介面,以獲取 Diameter ACA 訊息。sendDiameter 方法用於對 Diameter 訊息進行排隊,並依次向處理執行緒池提交 Diameter 訊息。getRfSession 方法用於獲取當前計費會話的 ID。清單 8展示了DiameterHandler 類的程式碼片段。


清單 8. DiameterHandler 類
public class DiameterHandler implements DiameterListener{
 public void diameterCallback(DiameterEvent event) {
 event.getWorkResult();
 setState(DIAMETER_MESSAGE_SENT);
 this.sendDiameter(null);
 }
 public void sendDiameter(DiameterMessage dm){
 lock.lock();
 DiameterMessage firstDiameterMsg=queueingDiameterMessage(dm);
 lock.unlock();
 if(firstDiameterMsg!=null)
 sending(firstDiameterMsg);
 }
 private DiameterMessage queueingDiameterMessage(DiameterMessage dm){
 DiameterMessage firstMessage=null;
 if(dm!=null)
 list.add(dm);
 if((state==DIAMETER_MESSAGE_SENT)&&(list.isEmpty()==false)){
 firstMessage=(DiameterMessage)list.remove();
 state=DIAMETER_MESSAGE_SENDING;
 }
 return firstMessage;
 }
 private void setState(int state){
 lock.lock();
 this.state=state;
 lock.unlock();
 }
 private static String getRfSession(){
 return SessionIdFactory.getRef().getSessionId(origin_host.getBytes());
 }
}

Main 方法展示了客戶端呼叫 AsyncRfAdapter 傳送計費訊息的方法。由於採用非同步操作,客戶端沒有任何阻塞,有效保證了客戶端的實時性,同時呼叫結果可以通過回撥介面獲取。


清單 9. Main 方法
public static void main(String[] args) throws Exception {
 DiameterHandler dh=new DiameterHandler();
// start offline accounting
 RfAccountingInfo acrInfo=dh.buildAccInfo("ibm.com");
 DiameterMessage dm=new DiameterMessage(AccountingRecordType.START_OFFLINE_ACC,acrInfo);
 dh.sendDiameter(dm);
// interim offline accounting
 dm=new DiameterMessage(AccountingRecordType.INTERIM_OFFLINE_ACCOUNTING,acrInfo);
 dh.sendDiameter(dm);
// stop offline accounting
 dm=new DiameterMessage(AccountingRecordType.STOP_OFFLINE_ACCOUNTING,acrInfo);
 dh.sendDiameter(dm);
}

WebSphere IMS Connector 計費服務的效能優化

WebSphere IMS Connector 計費服務可以通過構建 WAS 伺服器叢集的方式實現水平及垂直擴充套件,從而達到電信級的效能與可靠性要求。對於單個伺服器節點而言,可以通過修改各個服務對應的 properties配置檔案和 WAS 的配置來提高效能和可靠性。

Properties 的配置

WebSphere IMS Connector 計費服務可優化的 Properties 引數如下:

1. maxWatchDogExpirations 引數

該引數指定了 WebSphere IMS Connector 與後端計費伺服器的心跳超時次數,預設為 2 次;超過 2 次沒有響應的後端伺服器將被標記為不可用,後續請求將不發往該伺服器。

2. watchDogTimeout 引數

該引數指定了 WebSphere IMS Connector 與後端計費伺服器的心跳超時時間,預設為 30 秒;如果 maxWatchDogExpirations 設為 1,那麼超過 30 秒還沒有響應的後端伺服器將被標記為不可用,後續請求將不發往該伺服器。

3. reconnectInterval 引數

重試時間間隔;預設值為 30 妙,指示當後端伺服器被標記為不可用時,經過 30 秒後重新嘗試建立連線。

4. maxPendingQueueLength 引數

訊息處理佇列的長度,如果佇列長度達到最大值,則後續訊息將被丟棄;預設值為 30,建議設定為15000,以滿足效能要求。

5. packetTimeout 引數

佇列內訊息超時時間,預設值為 30,表示存在處理佇列中超過 30 秒的訊息將被刪除;建議設定為 600。

6. maxPacketSize 引數

系統能處理的最大訊息大小;預設值為 10000 bytes,超過該大小的訊息將被丟棄,以保護伺服器不會超載。

WAS 的配置

作為執行 WebSphere IMS Connector 的基礎平臺,WAS 的配置優化如下:

1. JVM 堆大小

設定 WebSphere IMS Connector 所在 WAS 伺服器的 JVM 堆大小,必須額外考慮到各個服務模組所使用的訊息佇列所佔用的記憶體空間,其估算值為 maxPacketSize 與 maxPendingQueueLength 之積。通常情況下應設定在 512 MB 到 768 MB 之間,儘量不要超過 1GB,以免大幅度增加 GC 延時。可以通過建立 WAS 叢集的方式進一步擴充套件 JVM 堆大小。

2. DiameterThreadPool

該執行緒池用於處理 Web 服務入棧訊息。對該執行緒池的調整,應該通過 TPV 工具實時監控其工作狀態,如果池內執行緒使用率超過80%,則應考慮增加執行緒數目。執行緒池大小最大不應超過300,否則會降低 JVM 排程執行緒的效率。可以通過建立 WAS 叢集的方式進一步擴充套件執行緒池大小。

3. DiameterWorkManager

該 Asynchronous beans 工作管理器用於處理 Web 服務出棧訊息。可以根據需要調整工作超時及工作請求佇列大小。對 DiameterWorkManager 所屬執行緒池的調整方式同 DiameterThreadPool。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14789789/viewspace-589257/,如需轉載,請註明出處,否則將追究法律責任。

相關文章