SIP アプリケーションの開発

     前  次    新しいウインドウで目次を開く     
コンテンツの開始位置

SIP アプリケーションの要件とベスト プラクティス

以下の節で、Oracle Communications Converged Application Server にデプロイするアプリケーションを開発するための要件とベスト プラクティスについて説明します。

 


Oracle Communications Converged Application Server の分散型アプリケーションの開発の概要

典型的なプロダクション環境では、SIP アプリケーションはエンジン層クラスタを形成する Oracle Communications Converged Application Server インスタンスのクラスタにデプロイされます。SIP データ層内のサーバのクラスタは、アクティブな呼び出しについての呼状態のレプリケートされたインメモリ データベースを提供します。この環境でアプリケーションを確実に機能させるには、以下の節に書かれているプログラミングの作法と慣行に従い、デプロイ後のアプリケーションの複数のコピーがクラスタ環境で期待どおりに動作するようにしてください。

旧バージョンの Oracle Communications Converged Application Server のアプリケーションを移植しようとしている場合、以下で述べる規約や制約の多くは馴染みのないものかもしれません。というのも、以前の Oracle Communications Converged Application Server 実装ではクラスタ化をサポートしていなかったからです。あらためて言うまでもないことですが、アプリケーションを移植したら徹底的なテストとプロファイリングを行って問題を洗い出し、新しい環境で満足な結果が得られるようにしてください。

 


アプリケーションではスレッドを作成しない

Oracle Communications Converged Application Server はマルチスレッド アプリケーション サーバであり、ホストしているモジュールについてリソースの割り当て、同時実行性、およびスレッドの同期化を慎重に管理します。Oracle Communications Converged Application Server アーキテクチャを最大限に生かすには、SIP サーブレットおよび Java EE API の仕様に従ってアプリケーションのモジュールを構築してください。

SIP サーブレットなどのサーバサイド モジュール内に新たなスレッドを作成するようなアプリケーション設計は避けてください。

警告 : アプリケーションによるスレッドの生成が必要な場合、デッドロックが起こらないよう、慎重にセッション データへの同時アクセスを管理しなければなりません。少なくとも、SIP サーブレットのサービス メソッド内にスレッドを生成することは避けてください。代わりに、サービス メソッドの外で別々のスレッド プールを保持してください。そして、すべてのセッション データへのアクセスを同期するように注意してください。

 


サーブレットは非ブロッキングでなければならない

SIP および HTTP サーブレットは、メソッドが呼び出されるとき呼状態がロックされた状態になるので、SIP メソッドの本体でスレッドをブロックしないようにする必要があります。たとえば、サーブレット メソッドが SIP サーブレット コンテナに制御を返す前にデータの取得や書き込みを積極的に待機するような設計は避けてください。

 


すべてのアプリケーション データをセッションに格納する

アプリケーションを複数のエンジン層サーバ (レプリケートされた Oracle Communications Converged Application Server コンフィグレーション内) にデプロイする場合は、すべてのアプリケーション データをセッション属性としてセッションに格納する必要があります。レプリケートされたコンフィグレーションでは、エンジン層サーバはキャッシュされた情報を保持しないので、すべてのアプリケーションを SIP データ層サーバにあるセッション属性からデシリアライズする必要があります。

 


すべてのセッション データがシリアライズ可能でなければならない

SIP アプリケーション呼状態のインメモリ レプリケーションをサポートするためには、SIP サーブレット セッションに格納されるオブジェクトをすべてシリアライズ可能にする必要があります。オブジェクトがシリアライズ可能とみなされるには、オブジェクトのすべてのフィールドがシリアライズ可能か一時的なフィールドである必要があります。サーブレットでシリアライズ可能なオブジェクトとシリアライズ不可能なオブジェクトが組み合わせて使われた場合、Oracle Communications Converged Application Server はシリアライズ不可能なオブジェクトのセッション ステートをレプリケートすることができません。

 


setAttribute() を使用して「No-Call」Scope のセッション データの変更

SIP サーブレット コンテナは、SIP サーブレットの doxxx メソッドを呼び出す時、関連する呼状態が自動的にロックされます。しかし、アプリケーションは、「No-Call」Scope のセッション データを変更する場合もあります。No-call scope は、通常の doxxx メソッドの範囲外で呼状態データが変更されたコンテキストを参照します。たとえば、HTTP サーブレットが SIP セッション データを変更しようとする場合、またはサーブレットを呼び出す前にコンテナがロックした呼状態以外の呼状態を SIP サーブレットが変更しようとする場合、データは no-call scope に変更されます。

アプリケーションは常に、SIP セッションの setAttribute メソッドを使用して no-call scope の属性を変更する必要があります。同様に、セッション オブジェクトから属性を削除するには、removeAttribute を使用してください。セッションデータを更新するために setAttribute/removeAttribute が使用されるたびに、SIP サーブレット コンテナは関連する呼状態のロックを取得および解除します。(メソッドは、更新するオブジェクトを待ち行列化させ、直ちに制御を 返します。)これにより、1 回に 1 つのアプリケーションだけがデータを変更し、クラスタの SIP データ層ノード間で変更がレプリケートされることが確実になります。

その他の set メソッドを使ってセッションの内部でオブジェクトを変更した場合、Oracle Communications Converged Application Server はその変更をレプリケートできません。

Oracle Communications Converged Application Server コンテナは、setattribute を呼び出したに加えられた変更を呼状態に維持しません。たとえば、次のコード サンプルでは、setAttribute を呼び出すと呼状態が直ちに変更されますが、続いて modifyState() を呼び出すと、呼状態が変更されません。

  Foo foo = new Foo(..);
appSession.setAttribute("name", foo); // これは呼状態を保持します。
  foo.modifyState(); // この変更は保持されません。

その代わりに、次のように呼状態属性の値を変更してからsetAttribute を呼び出すようにしてください。

  Foo foo = new Foo(..);
foo.modifyState();
appSession.setAttribute("name", foo);

また、SIP サーブレット コンテナには、それぞれの setAttribute の呼び出しに対して呼状態がロックされるという点にも留意してください。たとえば、HTTP サーブレットで次のコードを実行する時、SIP サーブレット コンテナは呼状態のロックを 2 回ずつ取得して解除します。

appSess.setAttribute("foo1", "bar2");
appSess.setAttribute("foo2", "bar2");

このようにロックすると、1 つのスレッドだけが常に呼状態を変更することが確実になります。しかし、他のプロセスは順次更新の間に呼状態を変更することができます。次のコードは、no-call 状態を行なった場合、スレッド セーフと見なされません。

Integer oldValue = appSession.getAttribute("counter");
Integer newValue = incrementCounter(oldValue);
appSession.setAttribute("counter", newValue);

上記のコードをスレッドセーフ にするには、wlssAppSession.doAction メソッドを使用して囲む必要があります。これにより、呼状態へのすべての変更が、次のように単一のトランザクション ロック内で行われます。

wlssAppSession.doAction(new WlssAction() {
       public Object run() throws Exception {
         Integer oldValue = appSession.getAttribute("counter");
         Integer newValue = incrementCounter(oldValue);
         appSession.setAttribute("counter", newValue);
         return null;
       }
     });

最後に、doInvite() などの「doSipMethod」で呼の状態をロックした場合、デッドロック状況を回避するようにしてください。doSipMethod の手順が実行されると、Oracle Communications Converged Application Server コンテナは、すでに呼状態をロックしていることに注意してください。アプリケーション コードがメッソド内からの現在の呼状態にアクセスしようとすると、(たとえば、データ構造や属性に保存されているセッションへのアクセス)、ロックの発注結果はデッドロックになります。

コード リスト 3-1 は、デッドロックとなる例を示しています。コンテナによって callAppSession に関連付けられた呼のコードが実行されると、ロックの順が逆転して getApplicationSession(callId) とのセッションを取得しようとするとデッドロックの原因になります。

コード リスト 3-1 デッドロックを引き起こすセッション アクセス
WlssSipApplicationSession confAppSession = (WlssSipApplicationSession) appSession;
confAppSession.doAction(new WlssAction() {  
  // confAppSession がロックされています
  public Object run() throws Exception {
    String callIds = confAppSession.getAttribute("callIds");
    for (each callId in callIds) {
      callAppSess = Session.getApplicationSession(callId); 
      // callAppSession がロックされています
      attributeStr += callAppSess.getAttribute("someattrib");
    }
    confAppSession.setAttribute("attrib", attributeStr);
  }
}

com.bea.wcp.sip.WlssAction インタフェースの使用については、「SipApplicationSession の変更」を参照してください。

 


send() 呼び出しがバッファされる

SIP サーブレットが doInvite()doAck()doNotify() などの SIP リクエスト メソッド内で send() メソッドを呼び出す場合は、Oracle Communications Converged Application Server コンテナによってすべての send() 呼び出しがバッファされ、SIP リクエスト メソッドの復帰後にそれらが順に転送されるという点に注意してください。send() 呼び出しが即座に転送されることを前提にアプリケーションを設計しないでください。

警告 : リクエストや応答は制御が SIP サーブレット コンテナに返るまで送信されないので、send() を呼び出した後でアプリケーションが待機したりスリープしたりしないようにする必要があります。

 


SIP サーブレットを配布可能としてマークする

SIP サーブレットをクラスタ環境にデプロイすることを前提として設計およびプログラムした場合は、アプリケーションをエンジン層サーバのクラスタにデプロイするときに、サーブレットのデプロイメント記述子に distributable (配布可能) マーカー要素を入れる必要があります。distributable 要素を省略すると、Oracle Communications Converged Application Server はそのサーブレットをエンジン層サーバのクラスタにデプロイしません。

distributable 要素は必須ではなく、単一の組み合わせ層 (レプリケートされない) Oracle Communications Converged Application Server インスタンスにデプロイする場合は無視されます。

 


SipApplicationSessionActivationListener を慎重に使用する

SIP サーブレット 1.1 仕様は、SIP セッションがアクティブ化されるかパッシベーションされる場合アプリケーションにコールバックを提供する SipApplicationSessionActivationListener について説明します。レプリケートされた Oracle Communications Converged Application Server デプロイメントのみにコールバックが発生することに注意してください。単一サーバ デプロイメントは SIP データ層を使用しません。そのため SIP セッションはパッシベーションされません。

レプリケートされたデプロイメント Oracle Communications Converged Application Server は、セッションに対して SIP メッセージが処理される前後に SIP Session を何度もアクティブ化し、パッシベーションします。(RDBMS ベースの永続性がコンフィグレーションされない場合でも、通常、どのレプリケートされたデプロイメントにおいてもこれは発生します。)アクティブ化およびパッシベーションのこの定数サイクルは、頻繁なコールバックになるため、アプリケーションで SipApplicationSessionActivationListener の使用を控えます。

 


Java EE アプリケーションのベスト プラクティスに従う

他の Java EE API を使用したアプリケーションをデプロイする場合は、それらの API の基本的なクラスタ化ガイドラインに従ってください。たとえば EJB をデプロイする場合は、すべてのメソッドを多重呼び出し不変として設計し、デプロイメント記述子の中で EJB ホームをクラスタ対応として指定してください。詳細については、Oracle WebLogic Server 10g リリース 3 ドキュメントの「クラスタ化のベスト プラクティス」を参照してください。


  ページの先頭       前  次