biz-Stream Web Service Server(以降、WSSと記述します)は、Version4.5.0から、 クラスタリング環境における動作をサポートするようになりました。
クラスタリング環境のシンプルな構築例として、1台のApacheをディスパッチャーとして使用し、複数のWSSサーバを構築、Apache経由でそれぞれのWSSにJOBを振り分ける事で、負荷分散を行う例をご説明します。
リポジトリをDB上(MySQL)に構築する事が出来る仕様になったため、DBサーバは複数のWSSで共有する環境を1台、用意します。
処理が分散され、各WSSサーバで行われた事を確認するには、サーバのログを確認する等、様々な方法がありますが、今回は2台のWSSのローカルに、同じ名前で異なる内容のレイアウトをそれぞれ配置し、一つのアプリケーションを連続で実行しても、処理したサーバによりPDFの表示内容が異なるようにします。
上記のようなテスト環境を図で示すと、このようになります。

Apacheをディスパッチャーとして使用し、Tomcatと連携する設定については、「Webサービスサーバユーザガイド」の「第7章 クラスタリング」に記述されていますので、ここでは省略します。
ディスパッチャー経由でWSSに対して連続してJOBを実行するテストツールはSeleniumや前回ご紹介したsoapUI等、何でも構わないのですが、今回は製品に同梱されているWSS_Sample1.javaをカスタマイズして、手軽な動作確認を行います。
以下①~⑤のように、WSS_Sample1.javaをカスタマイズします。
- 《 カスタマイズした WSS_Sample1.java 》
-
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.axiom.om.OMElement; import org.apache.axis2.Constants; import org.apache.axis2.client.Options; import org.apache.axis2.client.ServiceClient; import org.apache.axis2.addressing.EndpointReference; import org.apache.axis2.transport.http.HTTPConstants; import org.apache.axis2.transport.http.HttpTransportProperties; import org.apache.axiom.om.OMAbstractFactory; import org.apache.axiom.om.OMAttribute; import org.apache.axiom.om.OMFactory; import org.apache.axiom.om.OMNamespace; import java.util.Iterator; import org.apache.axiom.om.impl.traverse.OMChildrenIterator; /** * サンプルプログラム1: PDFを生成しリポジトリに登録するサンプルプログラムです。 * * @author Copyright 2001-2006 Brainsellers.com Corp. All Rights Reserved. * @version 1.0.0 * @since 1.0.0 * */ public class WSS_Sample1 extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { // **********変数宣言********** String inputFile = null; // 入力ファイルパス名 String outputFile = null; // 出力ファイル名 String wsUrl = null; // WebサービスサーバURL ServiceClient client = null; // Webサービスクライアント OMFactory fac; // 送信SOAPメッセージ OMNamespace ns; // 送信SOAPメッセージNameSpace protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { for (int i = 0; i < 20; i++) { //(1)実行回数指定 // **********定数設定********** inputFile = "C:/TestLayout.xml"; //(2)レイアウトファイルパス(今回のテスト用にレイアウトファイルを変更) outputFile = "/test_" + i + ".pdf"; //(3)生成PDFファイル名(実行する毎にPDF名が変わるように変更) wsUrl = "http://WSS-Dispacher/axis2/services/bizstream"; //(4)サービスURL(ディスパッチャーのホスト名を指定) // **********Webサービスクライアント/オプション設定********** EndpointReference endPoint = new EndpointReference(wsUrl); Options options = new Options(); options.setTo(endPoint); // リポジトリへの出力の場合"generateOutput"と指定する options.setAction("urn:bizstream/generateOutput"); options.setProperty(Constants.Configuration.ENABLE_MTOM, Constants.VALUE_TRUE); options.setTransportInProtocol(Constants.TRANSPORT_HTTP); // コンテンツ生成サービスにアクセスするための認証の設定 HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator(); auth.setUsername("bizuser1"); auth.setPassword("bizuser1"); auth.setPreemptiveAuthentication(true); options.setProperty(HTTPConstants.AUTHENTICATE, auth); // タイムアウトの設定 options.setTimeOutInMilliSeconds(10 * 1000); client = new ServiceClient(); client.setOptions(options); // **********SOAPメッセージ生成********** fac = OMAbstractFactory.getOMFactory(); ns = fac.createOMNamespace( "http://schemas.brainsellers.com/webservices/bizstream/2006-10", "bsws"); // SOAPメッセージ各要素/属性の定義 OMElement outputProcess = fac.createOMElement("generateOutputRequest", ns); OMElement output = fac.createOMElement("output", ns); OMElement type = fac.createOMElement("pdf", ns); // 生成ファイルの種類(pdf)指定 OMElement filename = fac.createOMElement("file", ns); OMElement layoutDefinition = fac.createOMElement("layoutDefinition", ns); OMElement layoutData = fac.createOMElement("layoutData", ns); filename.addAttribute("name", outputFile, null); // 生成ファイルのファイル名指定 type.addChild(filename); output.addChild(type); outputProcess.addChild(output); layoutDefinition.addAttribute("uri", inputFile, null); // 生成ファイルのレイアウトファイル名指定 layoutData.addChild(layoutDefinition); outputProcess.addChild(layoutData); // **********処理SOAPメッセージ送受信********** OMElement msg = client.sendReceive(outputProcess); // **********受信SOAPメッセージ解析********** String localname = null; String pdfURI = null; OMChildrenIterator outputChildren = (OMChildrenIterator) msg .getChildren(); for (; outputChildren.hasNext();) { OMElement outputChild = (OMElement) outputChildren.next(); localname = outputChild.getLocalName(); // ファイル生成先リポジトリの場所の特定 if (localname.equals("file")) { for (Iterator atts = outputChild.getAllAttributes(); atts .hasNext();) { OMAttribute att = (OMAttribute) atts.next(); if (att.getLocalName().equals("uri")) // アトリビュートがuriならリンクを作る { pdfURI = att.getAttributeValue(); // 登録先リポジトリURL取得 } } } } // **********処理結果画面********** response.setContentType("text/html; charset=iso-2022-jp"); PrintWriter writer = response.getWriter(); writer.println("<html><head>"); writer.println("<title>WSS_Sample1</title></head>"); writer.println("<body>"); writer.println("<h1>PDF生成</h1>"); writer.println("LocalName = " + msg.getLocalName()); writer.println("<br>"); writer.println("<a href=\"" + pdfURI + "\">" + pdfURI + "</a>"); writer.println("<br>"); writer.println("</body>"); writer.println("</html>"); writer.close(); } //(5)追加挿入 } }
- (1)50行目: 実行回数を設定(連続20回)。
- (2)52行目: テスト用に作成したレイアウトを指定(WSS1とWSS2のそれぞれのC:/に同じ名前のXMLを配置しますが、内容は異なります)。
- (3)53行目: 元の設定だと同名のPDFが上書きされてしまうので、生成したファイル名を実行する毎に変わるよう設定。
- (4)54行目: ディスパッチャーのホスト名を指定
- (5)140行目: (1)の挿入に伴い、ClassBodyを完了するため追加します。
カスタマイズしたサーブレットを、Eclipseやアプリ用サーバ上で実行し、ブラウザでディスパッチャー上からWSSのリポジトリを表示させると、20個のPDFが生成されています。
※もちろん、振分先であるWSS1、WSS2、どちらのURLから確認しても同じファイルが表示されます。
そして、PDFの内容を確認するとtest_0、test_1・・・と、交互に内容が入れ替わっており、
WSS1、WSS2がJOBを等分で振り分けられ、処理を行った事が明示的に確認出来ます。

※この、振分の比率はディスパッチャーの設定ファイルで変更する事が出来ます。
以上、極シンプルなWSSのクラスタリング機能の基本動作確認方法を紹介させて頂きました。