リモートアクセスでの IIOP セッションプール

ドミノの IIOP を使用したリモートアクセスですが、JDBC などと同様に IIOP セッションの取得、つまり Session オブジェクトの取得は相対的に重たい処理になります。

ただ、リモートアクセスの場合はローカルアクセスと違って、この Session オブジェクトを使いまわすことができます。
たとえばサーブレットの場合、init メソッドで IIOP セッションを作っておいて必要に応じてそれを共有使用する、ということがリモートアクセスの場合は可能です。

これをちょっとすすめて、IIOP セッションをプールして使いまわすようなかたちのクラスを考えてみました。

IIOP セッションのプール

こちらが IIOP セッションをまとめて取得して、リクエストに応じてそのセッションオブジェクトをわたす、といったクラスです。

import lotus.domino.*;

public class IIOPSessionPool {
private static final String NO_SESSIONS =
"No sessions available in pool.";

private Session pool[];
private long idletimeout = 3600000;
private long timeout = 10000;
private long timeStart;
private String _server;
private String _user;
private String _password;

public IIOPSessionPool(String server, String user,
String password, int sessions) throws NotesException {
pool = new Session[sessions];
_server = server;
_user = user;
_password = password;

initializePool(server, user, password);
}

private void initializePool(String server,
String user,
String password) throws NotesException {
try {
for (int i = 0; i < pool.length; i++) {
pool[i] = NotesFactory.createSession(server, user, password);
System.out.println("Session objects Created");
}

} catch (Exception c) { }
}

public synchronized Session getSession() throws NotesException {
Session ses = null;

// timout の時間内に getSession の結果が返るようにチェック
timeStart = System.currentTimeMillis();
while ((System.currentTimeMillis() - timeStart) < timeout) {
for (int i = 0; i < pool.length; i++) {
if (pool[i] != null) {
ses = pool[i];
pool[i] = null;
System.out.println("Session #" + i + " Returned (getSession)");
break;
}
}

if (ses != null) {
break;
}

if (ses == null) {
initializePool(_server, _user, _password);
int i = 0;
ses = pool[i] ;
pool[i] = null;
System.out.println("Session #" + i + " Returned (getSession)");
break;
// もともとは timeout で結果が返せない場合は "NO_SESSIONS" 例外
// throw new Exception(NO_SESSIONS);
}

}
return ses;

}

public synchronized void returnSession(Session session) {
for (int i = 0; i < pool.length; i++) {
if (pool[i] == null) {
pool[i] = session;
System.out.println("Session #" + i + " Returned (returnSession)");
break;
}
}
}

public void closePool() {
for (int i = 0; i < pool.length; i++) {
try {
pool[i].recycle();
} catch (NotesException e) {}
}
}
}

上記の IIOPSessionPool クラスは、クラスパスのあるところに置きます。
今回は、この後に使用するテスト用とサンプルのサーブレットと同じ WAS の default_app Web モジュールに置いています。

この使い方としては IIOPSessionPool クラスを作成して、getSession メソッドでプールから IIOPセッションを取得、必要な処理が終わったら returnSession メソッドでプールに返却する、という流れになります。

IIOPSessionPool isp;
Session session;

// セッションプールオブジェクトの作成
String server = "asdomino";
String user = "User";
String password = "Password";
isp = new IIOPSessionPool(server, user, password, 10);


// セッションをプールから取得
session = isp.getSession();

// セッションを使った処理
String p = session.getPlatform();
System.out.println("Current Platform : " + p);
msg = "Current Platform : " + p + "<BR>";

// セッションをプールに返却
isp.returnSession(session);

// 本当の最後にはセッションプールオブジェクトをクローズ
isp.closePool();

プールからセッションがなくなってしまった時の動き方

こちらはテスト用のサーブレットです。
実行結果はこんなかんじです。

returnSession をしていませんので、セッションプールからセッションを使っていくばっかりになっています。
これでセッションが足りなくなった時のセッションプールの動きを見てみます。

import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;
import lotus.domino.*;

public class SessionPoolTestServlet extends HttpServlet {

IIOPSessionPool isp;
Session session;

public SessionPoolTestServlet() {}

public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
doService(req, res); }

public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
doService(req, res); }

public void init()
throws ServletException {
super.init();
System.out.println("init");

try {
System.out.println("Going to create session");
String server = "asdomino";
String user = "User";
String password = "Password";
isp = new IIOPSessionPool(server, user, password, 10);
System.out.println("IIOPSessionPool Created");
}
catch (Exception e) { e.printStackTrace(); }
}

public void doService(HttpServletRequest req, HttpServletResponse res)
{
System.out.println("doService");

String msg = null;

try {
System.out.println("Going to getSession");
session = isp.getSession();
System.out.println("Session is got");

String p = session.getPlatform();
System.out.println("Current Platform : " + p);
msg = "Current Platform : " + p + "<BR>";

String nv = session.getNotesVersion();
System.out.println("Current Domino Version: " + nv);
msg = msg + "Current Domino Version: " + nv + "<BR>";

sendResponse(res, msg);

//isp.returnSession(session);

}
catch (NotesException e) {
System.out.println("Exception when create session");
msg = e.id + " " + e.text + "occured";
e.printStackTrace(); }
}

public void sendResponse(HttpServletResponse res, String entity) {
try {
PrintWriter pw = null;
res.setContentType("text/html; charset=Cp943c");
pw = res.getWriter();
pw.println("<html><body>");
pw.println(entity);
pw.println("</body></html>");
}
catch (Exception e) { e.printStackTrace(); }
}

public void destroy()
{
System.out.println("destroy");

try {
System.out.println("Going to close session pool");
isp.closePool();
System.out.println("IIOPSessionPool Closed");
}
catch (Exception e) { e.printStackTrace(); }
}

}

このサーブレットの実行後、ドミノのコンソールで show tasks を実行してみる、IIOP セッションが 10 できているのが確認できます。

IIOPSessionPool クラスも、テスト用のサーブレットも動きの確認のために要所要所にメッセージを出力させています。

最初にサーブレットの init メソッドの中で IIOPSessionPool クラスが初期化され、IIOPSessionPool クラスが IIOP セッションを指定された数 (10) 作成しているのがわかります。

続けてサーブレットの中でセッションの取得が行なわれています。

テスト用サーブレットを続けて実行しています。
getSession で 2つめ、3つめのセッションがセッションプールから取られていっているのがわかります。

もともと作成されたプールのサイズが 10 なので、セッションを 10 個取られてしまうとセッションがリクエストされても返せません。
そういう場合は IIOPSessionPool オブジェクトはおなじサイズで新しいセッションを作成するようになっています。

新しいセッションが作成されているのが確認できます。

ドミノコンソールを見るとセッションの数が 20 に増えています。

セッションの追加のタイミングだけは若干時間がかかりますが、後は本当にすぐレスポンスが返ってきます。

サーブレットでの使用例

こちらが正しいサンプルですね。

import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;
import lotus.domino.*;

public class SessionPoolServlet extends HttpServlet {

IIOPSessionPool isp;
Session session;

public SessionPoolServlet() {}

public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
doService(req, res); }

public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
doService(req, res); }

public void init()
throws ServletException {
super.init();
System.out.println("init");

try {
System.out.println("Going to create session");
String server = "asdomino";
String user = "User";
String password = "Password";
isp = new IIOPSessionPool(server, user, password, 10);
System.out.println("IIOPSessionPool Created");
}
catch (Exception e) { e.printStackTrace(); }
}

public void doService(HttpServletRequest req, HttpServletResponse res)
{
System.out.println("doService");

String msg = null;

try {
System.out.println("Going to getSession");
session = isp.getSession();
System.out.println("Session is got");

String p = session.getPlatform();
System.out.println("Current Platform : " + p);
msg = "Current Platform : " + p + "<BR>";

String nv = session.getNotesVersion();
System.out.println("Current Domino Version: " + nv);
msg = msg + "Current Domino Version: " + nv + "<BR>";

sendResponse(res, msg);

isp.returnSession(session);

}
catch (NotesException e) {
System.out.println("Exception when create session");
msg = e.id + " " + e.text + "occured";
e.printStackTrace(); }
}

public void sendResponse(HttpServletResponse res, String entity) {
try {
PrintWriter pw = null;
res.setContentType("text/html; charset=Cp943c");
pw = res.getWriter();
pw.println("<html><body>");
pw.println(entity);
pw.println("</body></html>");
}
catch (Exception e) { e.printStackTrace(); }
}

public void destroy()
{
System.out.println("destroy");

try {
System.out.println("Going to close session pool");
isp.closePool();
System.out.println("IIOPSessionPool Closed");
}
catch (Exception e) { e.printStackTrace(); }
}

}

結果のログの途中の部分ですが、毎回セッションをプールに戻していますので、同じセッションオブジェクトが使われています。

考慮点

セッションは WebSphere 側のプログラムが終了した時点か、ドミノの IIOP セッションのアイドルタイムアウトで終了します。

ドミノサーバーはアクティブな IIOP セッションがあると DIIOP タスクを終了できないので、そのあたりは運用やプログラムで考慮してみてください。

[Top Pageに戻る]

Ads by TOK2