Tomcat 7のParallel deploymentを試してみた。
@ITの技術者が知っておきたいTomcat 7の新機能20連発で、Tomcat 7の新機能としてWebアプリのバージョン管理「Parallel deployment」が取り上げられていました。
これがうまく動くようだと場合によっては運用面で非常に楽になるため、簡単に検証してみました。
準備
まずTomcat 7の最新版を以下からダウンロードします。今は7.0.16のようです。zip版のものをダウンロードしています。
http://tomcat.apache.org/download-70.cgi
ダウンロードしたファイルを今回は以下に展開しました。
C:\temp\apache-tomcat-7.0.16
これでTomcatの準備は完了です。
アプリケーション
アプリケーション概要
続いてデプロイするアプリケーションを作成します。セッションを持たないと意味がないため、無理やりセッションを使用するアプリケーションになっています。
アプリケーションの作りとしては、足し算アプリケーションで入力フォームを2つ表示しておき、「計算」ボタンを押すとセッションに格納された計算結果を表示するというものにします。入力画面と結果表示画面は同じ画面とし、繰り返し計算ができる画面とします。
サンプル1
以下サンプルを紹介しますがServletのみ変更していきます。
まずは入力・結果表示画面のindex.jspです。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>calc</title> </head> <body> <form action="add" method="post"> <input type="text" name="val1"> + <input type="text" name="val2"><br> <input type="submit" value="計算"><br> ${val1} + ${val2} = ${result} </form> </body> </html>
次に、AddServletです。AddServletは名前の通り入力した情報を加算するサーブレットですが、あえて掛け算としています。
package com.example; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class AddServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int val1 = Integer.parseInt(request.getParameter("val1")); int val2 = Integer.parseInt(request.getParameter("val2")); HttpSession session = request.getSession(); session.setAttribute("val1", val1); session.setAttribute("val2", val2); // 不具合!! session.setAttribute("result", val1 * val2); getServletContext().getRequestDispatcher("/") .forward(request, response); } }
最後に、web.xmlです。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>add</servlet-name> <servlet-class>com.example.AddServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>add</servlet-name> <url-pattern>/add</url-pattern> </servlet-mapping> </web-app>
サンプル2
サンプル2ではAddServletのみ変更しています。変更点は結果が掛け算だったものを足し算にしただけとなります。
package com.example; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class AddServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int val1 = Integer.parseInt(request.getParameter("val1")); int val2 = Integer.parseInt(request.getParameter("val2")); HttpSession session = request.getSession(); session.setAttribute("val1", val1); session.setAttribute("val2", val2); // 不具合!! session.setAttribute("result", val1 + val2); getServletContext().getRequestDispatcher("/") .forward(request, response); } }
デプロイ、実行
warファイルを作成しますが、今度はcalc##01.warという名前にして、TOMCAT_HOME/webappフォルダ以下に置きます。このようにバージョン管理するには、アプリケーション名##バージョン.warという命名規則になります。
アプリケーションをデプロイします。デプロイすると、コマンドプロンプトに以下のようにデプロイした旨表示されます。
そして、先ほどのブラウザとは違うブラウザか、「新規セッション」でブラウザを開きアプリケーションにアクセスし、2と5を入力します。そうすると、正しく計算された結果がでてきます。
この状態で最初にサンプル1を開いたブラウザで再度2と5を入力し計算します。そうすると結果は最初に行ったのと変わらず10と表示されます。このようにセッションが生存している間は古いバージョンで動作し、新しいセッションのものは新しいプログラムが動いていることが確認できます。
サンプル3
この状態でサンプル3を作ります。サンプル3もAddServletのみを変更します。変更点は今回は足し算を割り算にします。
package com.example; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class AddServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int val1 = Integer.parseInt(request.getParameter("val1")); int val2 = Integer.parseInt(request.getParameter("val2")); HttpSession session = request.getSession(); session.setAttribute("val1", val1); session.setAttribute("val2", val2); // 不具合!! session.setAttribute("result", val1 / val2); getServletContext().getRequestDispatcher("/") .forward(request, response); } }
そして、同様に別のブラウザ等でアプリケーションにアクセスし、2と5を入力します。そうすると、0と割られた結果が表示されます。
この状態でサンプル1、サンプル2を実行すると当初と同じ結果になっていることが確認できます。このように複数のバージョンを同時に生存させることができます。
複数バージョンが存在していてもユーザー側は意識する必要はなく、新しいセッションの場合には最新のバージョンのプログラムが使用されます。