Servlet 3.0実装以外のTomcat 7の新機能とは
連載第1・2回の「Tomcat 7も対応したServlet 3.0の6つの主な変更点」でTomcat 7の紹介としてServlet 3.0に関する機能について説明しました。今回はServlet仕様のアップデート以外によるTomcat 7の新機能について紹介していきます。
Tomcat 7の変更点の全てがServlet 3.0によるものではありません。Webアプリケーションのバージョン管理機能やメモリリーク防止と検知機能、エイリアス(alias)サポート、Tomcatをプログラムに組み込むための軽量APIの提供など、Tomcat 7ではServlet仕様のアップデート以外にも、さまざまな新機能の追加やコードの改善を行っています。
今回は、その新機能のうち、20個を厳選して紹介していきます。
- Webアプリのバージョン管理「Parallel deployment」
- メモリリークの可能性があるクラスを初期化
- さまざまな参照をクリアしてメモリリーク防止
- メモリリークの探知機能「Find leaks」
- さまざまなTomcatの実行方法が追加
- Apacheと同様なエイリアス(aliases)をサポート
- JNDIリソースのクローズ処理サポート
- コネクタ実装の統一
- CSRFを防止するフィルタ
- Tomcat版「mod_expires」でキャッシュの有効利用
- 長時間処理しているリクエストを検知
- Webクローラによるセッション大量生成を防止
- 仮想クラスローダ機能
- Tomcatのロギング機能に新クラスが追加
- ライフサイクルアーキテクチャの変更
- アクセスログの機能追加
- セッション固定攻撃対策
- セッションアクセス時間の仕様準拠
- ValveからFilterへの移行
- 「META-INF/context.xml」のコピー
7になっても変わっていないところ
まずは、Tomcat 7の新機能を見る前に、今までと変わっていないところも多く存在しますので、簡単に紹介していきます。
■ ディレクトリ構成
Tomcatのインストール時のデフォルトのディレクトリ構成はTomcat 6から変更ありません。以下についてはTomcat 6と同じです。
- インストール後のデフォルトのディレクトリ構成
- 設定ファイル(server.xml、context.xmlなど)の格納場所
- ログ出力ディレクトリ
- 起動スクリプト格納ディレクトリ
■ クラスローダ階層
クラスローダの階層もTomcat 6のころと同様で、変更ありません。
■ リクエスト処理のアーキテクチャ
Tomcat 4時代から採用されているリクエスト処理のCatalinaアーキテクチャは変更なしで、そのまま採用しています。Tomcatが受け付けたリクエストは、リクエスト処理パイプラインによってServletまで到達し処理されます。
■ クラスタリング(セッションレプリケーション)
若干のインターフェイスの改良はありますが、基本的には同じ仕様です。
「All-to-All」「primary-secondary」の2つのレプリケーション方式が利用可能となっています。
■ DBコネクションプール
今までどおりApache Commons DBCPを使用し、バージョンはDBCP 1.4系(JDBC 4用)を採用しています。Tomcat独自のjdbc-poolを利用する場合は別途ビルドが必要です。jdbc-poolは近いうちに同梱されるかもしれません。
では、Tomcat 7の新機能について紹介していきます。
【1】Webアプリのバージョン管理「Parallel deployment」
「Parallel deployment」は、TomcatにおけるWebアプリケーションのバージョン管理機能です。ポイントは以下の5つです。
- 同じコンテキストパスのアプリケーションが複数の異なるバージョンを持てる
- 古いバージョンのセッションを持つユーザーは、そのバージョンのWebアプリケーションを実行
- セッションを持たないユーザーは最新バージョンのWebアプリケーションを実行
- Webアプリケーションのバージョンは##バージョンで指定。test##001.warとかsample##001とか
- ユーザーは実行するアプリケーションのバージョンを意識しない
以下のような動作になります。
バージョンを持たない(初期バージョン)のWebアプリケーションを「AP」とした場合、APでセッションを作成したユーザーはそのセッション(Session A)を保持するAPでサービスを継続します。
その後、AP##001の新しいバージョンのアプリケーションがデプロイされると、新しいユーザーはSessionをAP##001に作成します。Session Aを持つユーザーは、そのまま引き続きAPを利用します。
さらに、AP##002がデプロイされた場合も、新規ユーザーは最新バージョンを、既存ユーザーは自分の保持するセッションを持つバージョンのアプリケーションを利用します。
つまり、アプリケーションのバージョンが上がっても、ユーザーがセッションを保持する場合は、実行されるアプリケーションはそのセッションを持つバージョンのアプリケーションになります。
■ Tomcatが自動で行うバージョン管理
上記のようなバージョン管理はTomcatが自動で行っており、ユーザーは自分が実際に利用しているアプリケーションのバージョンを意識しません。つまり、ユーザーはバージョンを意識することなく、今までどおりのパスで、「http://【ホスト】/【AP】/【XXX】」とリクエストするだけで、Tomcatがセッションを基に処理すべきバージョンのアプリケーションを選んで実行してくれます。
■ コンテキスト分のメモリを利用するので、注意
なお、Parallel deploymentによりバージョン管理機能を利用すると、サービスを継続させながら自由にアプリケーションのバージョンが上げられますが、バージョンを上げるたびにコンテキストを配置するため、その分多くメモリを利用します。注意が必要です。
■ 不要なバージョンは削除する必要があるので、注意
また、現在のTomcatでは管理するセッションがなくなった古いバージョンのアプリケーションの自動削除は行われないので、システム管理者はアプリケーションの保持するセッションの数をチェックし、不要なバージョンのアプリケーションは削除するなどの運用対処も必要になります。
【2】メモリリークの可能性があるクラスを初期化
Javaランタイム環境でシングルトンなクラスをロードするのにコンテキストクラスローダを使用し、コンテキストクラスローダの参照を保持するようなクラスは、コンテキストクラスローダがWebAppクラスローダであった場合にメモリリークを引き起こす可能性があります。
このような問題に対する回避策は、メモリリークを引き起こす可能性のあるクラスをWebAppクラスローダにロードさせずに、あらかじめCommonクラスローダでクラスをロードしてしまうことです。
Tomcat 7では、この回避策を実現するために、JreMemoryLeakPreventionListenerを提供します。JreMemoryLeakPreventionListenerはTomcatのライフサイクルリスナとして実装されており、Tomcatは起動時にJreMemoryLeakPreventionListenerに初期化イベントを通知します。このときのコンテキストクラスローダはCommonクラスローダなので、JreMemoryLeakPreventionListenerは、その初期化イベント処理で上記のようなメモリリークを引き起こす可能性のあるクラスを初期化することで、メモリリークを回避します。
JreMemoryLeakPreventionListenerは
中には、メモリリークかどうか分かりにくいものも存在しますが、現在どのようなメモリリーク防止機能があるかは、公式ドキュメントに記載しています。
Tomcat 7では、多くのメモリリークの防止と検知機能を提供します。また、【2】を含め次ページで紹介する、メモリリークの防止と検知の機能のうち大部分は、Tomcat 6.0にバックポート(反映)済みです。
Copyright © ITmedia, Inc. All Rights Reserved.