The Jakarta Project

The mighty Tomcat - Meow!

Tomcat- 簡易ユーザガイド

このドキュメントは、Tomcatに関するいくつかの基本的な情報について説明します。 ここで説明する項目は、以下の通りです。

  1. Tomcatのバイナリ版のインストールについて
  2. Tomcatで使用するスクリプトについて
  3. Tomcatの主な設定ファイルであるserver.xmlについて
  4. 一般的なWebサーバとTomcatを連動させる方法について
  5. Webサイトの実運用でTomcatを使用する方法について
この情報が、これからTomcatを始める人の役に立つことを願っています。何かわからないことがある場合は、まず以下のことを(この順番で)試してください。

  1. Tomcat FAQを検索する。
  2. Tomcat メーリングリストの過去ログを検索する。
  3. tomcat-userメーリングリストに投稿する。

その質問に対する回答がまだ存在しない場合には、Tomcat FAQか、この文章に追加することを奨励します。 このドキュメントに関するコメントや提案があるならば、遠慮しないでTomcat メーリングリストに送ってください。

はじめに

Tomcatは、JSP環境を持ったServletコンテナです。 Servletコンテナは、ユーザのためにServletを管理したり、実行するランタイムシェルです。

Servletコンテナは、だいたい以下のように分類されます。

  1. スタンドアロン型Servletコンテナ
    これはJavaベースのWebサーバを使用した場合であり、Webサーバと一体化しています。 たとえば、JavaWebServerのServletコンテナ部分が、これに相当します。 スタンドアロン型は、Tomcatのデフォルトモードです。 しかし、大部分のWebサーバはJavaベースではないので、以下の2つのどちらかを選ぶことになるでしょう。
  2. プロセス内Servletコンテナ
    このServletコンテナは、WebサーバのプラグインとJavaのコンテナの実装の組み合わせです。 Webサーバプラグインが、Webサーバのアドレス空間内にJVMをオープンし、Javaコンテナをそこで実行します。 あるリクエストがServletを実行しなければならない場合には、プラグインがリクエストを受け取ってから、(JNIを使って)Javaコンテナに渡します。 プロセス内コンテナは、マルチスレッド・シングルプロセスのサーバに適していて、性能は良いのですが、スケーラビリティが制限されます。
  3. プロセス外Servletコンテナ
    このServletコンテナは、Webサーバのプラグインと、Webサーバの外で動作してるJVMで実行されているJavaコンテナの実装を組み合わせです。 WebサーバプラグインとJavaコンテナのJVMは、IPC機構(普通はTCP/IPソケットです)を使って通信します。 あるリクエストがServletを実行しなければならない場合には、プラグインはリクエストを受け取って、(IPCを使って)Javaコンテナに渡します。 プロセス外エンジンの応答時間は、プロセス内ほど良くはありませんが、(スケーラビリティや拡張性などの)多くの計測項目で良い結果が得られます。

Tomcatはスタンドアロンコンテナとしても(主に開発やデバッグ環境用です)、既存のWebサーバに付加しても(現在ApacheやIIS,Netscapeなどのサーバが サポートされています)使用できます。これは、Tomcatを配備しているときはいつも使用する方法を決めなければならないだろうことを意味し、また、オプ ションを2,3選択すると、Webサーバアダプターをインストールする必要があるでしょう。

TomcatとJservの違いは何ですか? Tomcat==Jservではないのですか?

これはよくある誤解です。JservはApacheで使用することを目的に作られたServletAPI2.0準拠のコンテナです。 Tomcatは完全にコードを書き直された、ServletAPI2.2とJSP1.1に準拠したコンテナです。

TomcatはJservで使われていたコード(特にJserv's Apache server adapterの部分)をいくつか使っています。 しかし、これがTomcatとJservの最後の類似点です。

Tomcatバイナリ版のインストール方法は?

とても簡単です。以下のようにするだけです。

以上で、Tomcatをスタンドアロン型(Type1)Servletコンテナを動かすことができます。

Tomcatの起動と停止

binディレクトリにあるスクリプトを使用して、Tomcatの起動と停止を行います。

Tomcatの起動

UNIX: bin/startup.sh

Win32: bin\startup

Tomcatの停止

UNIX: bin/shutdown.sh

Win32: bin\shutdown

Tomcatのディレクトリ構成

すでにTomcatバイナリ版配布をzipやtarでを展開しているとすると、以下のようなディレクトリ構成になります。

ディレクトリ名 説明
bin startup/shutdownなどのスクリプトが含まれています。
conf server.xml (Tomcatのメイン設定ファイル) とTomcat内で動作する様々な Webアプリケーションのデフォルト値を設定するweb.xmlなどのファイルが含まれています。
doc Tomcatに関する種々雑多なドキュメントが含まれています。
lib Tomcatで使われる様々なjarファイルが含まれています。 UNIX上では、このディレクトリ内のすべてのファイルがTomcatのCLASSPATHに追加されます。
logs Tomcatのログファイルが保存されます。
src Servlet APIのソースファイルが含まれています。 しかし、興奮しないでください。 すべてのServletコンテナで実装する必要がある空のインターフェイスと抽象クラスがあるだけです。
webapps サンプルアプリケーションが含まれています。

さらにTomcatは、以下のサブディレクトリを作成します。

work Tomcatが自動的に生成します。 Tomcatの動作中に、(コンパイル済みのJSPファイルのような)中間ファイルを置く場所です。 Tomcatの動作中にこのディレクトリを削除すると、JSPページを実行できなくなります。
classes CLASSPATHにクラスを追加するために、このディレクトリを作ることができます。 このディレクトリに追加したすべてのクラスは、TomcatのCLASSPATHに含まれます。

Tomcatのスクリプト

TomcatはJavaプログラムなので、いくつかの環境変数を設定すれば、コマンドラインから実行 することができます。 しかし、環境変数や、以下のようなコマンドライン引数をつけてTomcatを起動することは、エラー が発生しやすく、面倒です。 その代わりに、Tomcat開発チームは、Tomcatを簡単に起動したり、停止したりできるように数個の スクリプトを用意しています。

注: スクリプトはTomcatの起動や停止のための手軽な方法にすぎません。 Tomcatに正しいコマンドラインを指定するならば、CLASSPATHや、PATHやLD_LIBRARY_PATHなどの環境 変数をカズタマイズするように、スクリプトを変更することができます。

これらのスクリプトとはどんなものでしょう? 以下に、一般的なユーザにとってもっとも重要なスクリプトを示します。

スクリプト名 説明
tomcat メインスクリプトです。 CLASSPATHやTOMCAT_HOME、JAVA_HOMEを取り込んて、適切な環境を設定してから、適切なコマンド ライン引数でTomcatを起動します。
startup Tomcatをバックグラウンドで起動します。これは"tomcat start" のショートカットです。
shutdown Tomcatを停止します。これは"tomcat stop" のショートカットです。

ユーザにとって一番重要なスクリプトは、tomcat(tomcat.sh/tomcat.bat)です。 他のTomcatに関するスクリプトは、(異なるコマンドライン引数を設定するなど)tomcatスクリプトに対して 簡単に一つの作業をおこなうようなエントリポイントとして働きます。

tomcat.sh/tomcat.batスクリプトを調べると、以下のように動作しているのがわかります。

オペレーティングシステム 動作
Unix
  • 環境変数TOMCAT_HOMEが指定されていなければ、適当に推測します。
  • 環境変数JAVA_HOMEが指定されていなければ、適当に推測します。
  • 以下のものを含むようにCLASSPATHを設定します。
    1. ${TOMCAT_HOME}/classes ディレクトリ (存在する場合)
    2. ${TOMCAT_HOME}/libの全コンテンツ
    3. ${JAVA_HOME}/lib/tools.jar (このjarファイルはJSPファイルに 必要なjavacツールを提供します)
  • javaを、起動クラスであるorg.apache.tomcat.startup.Tomcatのtomcat.homeと 呼ぶjavaシステム環境を設定するために、コマンドライン引数をつけて実行します。 さらに、org.apache.tomcat.startup.Tomcatに、以下のようなコマンドライン引数を 渡すことができます。
    1. start/stop/runなどを実行するための操作。
    2. このTomcatプロセスが使用するserver.xmlのパス

    たとえば、ユーザが/etc/server_1.xmlとして存在するserver.xmlを用いて、バック グラウンドでTomcatを実行したい場合には、以下のコマンドラインを入力します。

    bin/tomcat.sh start -f /etc/server_1.xml

Win32
  • TOMCAT_HOMEとCLASSPATHの設定を保存します。
  • JAVA_HOMEがセットされているか確認します。
  • TOMCAT_HOMEがセットされているか確認します。 そして、セットされていなければ"."(カレントディレクトリ)をデフォルトにしてください。 TOMCAT_HOMEはservlet.jarの存在を確認するときに有効です。
  • 以下のようにCLASSPATHを設定します。
    1. %TOMCAT_HOME%\classes (存在しない場合でも)
    2. %TOMCAT_HOME%\libのjarファイル。可能なら%TOMCAT_HOME%\libの全jarファイルを 動的にインクルードします。不可能ならばant.jar, jasper.jar,jaxp.jar, parser.jar, servlet.jar, webserver.jarを静的にインクルードします。
    3. %JAVA_HOME%\lib\tools.jar (このjarファイルはJSPファイルに必要なツールである javacを含んでいます。JSPファイルにはjavacが必要です)
  • Java環境変数が設定されている状態で、%JAVA_HOME%\bin\javaを、起動クラスである org.apache.tomcat.startup.Tomcatのtomcat.homeと呼ぶjavaシステム環境を設定するために、 コマンドライン引数をつけて実行します。 さらに、org.apache.tomcat.startup.Tomcatに、以下のようなコマンドライン引数を渡すことが できます。
    1. start/stop/runなどを実行するための操作。
    2. このTomcatプロセスが使用するserver.xmlのパス。

    たとえば、ユーザがconf\server_1.xmlとして存在するserver.xmlを用いて、新しいウインドウで Tomcatを実行したい場合には、以下のコマンドラインを入力します。

    bin\tomcat.bat start -f conf\server_1.xml

  • 以前のTOMCAT_HOMEとCLASSPATHを保存しリストアします。

Win32版のtomcat.batはUNIX版のものに比べて堅牢でないように見えるかもしれません。 とりわけTOMCAT_HOMEやJAVA_HOMEの値を推測しないで、"."だけでTOMCAT_HOMEを推測しようとするので。 CLASSPATHは全ての場合というわけではありませんが、動的に構築されます。 TOMCAT_HOMEがスペース文字や、Win9xにおいてTOMCAT_HOMEが8.3のネーミング規則に沿わない場合、動的に 構築されることはありません。

Tomcatの設定ファイル

Tomcatの設定ファイルは、2個のファイルに基づきます。

  1. server.xml - Tomcatの全体的な設定ファイル。
  2. web.xml - Tomcatのコンテキストの設定。

この項では、これら2つのファイルについて説明します。 しかし、web.xmlの内部までは説明しません。 これについてはServlet APIの仕様で充分に説明されているので、Tomcatでweb.xmlを使用する方法について説明します。

server.xml

server.xmlは、Tomcatのメイン設定ファイルです。これには以下のような2つの目的があります。

  1. Tomcatのコンポーネントを初期化します。
  2. Tomcatに構成を指定します。これは、Tomcatをブートし、server.xml中で指定されているコンポーネントをイン スタンス化することで、それ自信を構築することです。
server.xmlの重要な要素を以下の表に示します。
要素 説明
Server server.xmlの最上位要素です。 Serverは1つのTomcatサーバを定義します。 一般にはそれほど気にかける必要はありません。 Server要素は、タイプLoggerとContextManagerの要素を含むことができます。
Logger この要素は、loggerオブジェクトを定義します。 どのloggerも、ログ出力を保存するログファイルへのパスとverbosityLevel(ログレベルを指定します)だけでなく、 それを特定できる名前を持っています。 現在の段階では、(ServletContext.log()を実行する)ServletやJSPファイル、Tomcatランタイムに対して、複数のloggerが使われています。
ContextManager ContextManagerは、ContextInterceptorとRequestInterceptor, Context, Connectorの設定と構造を定義します。 ContextManagerには、以下のような属性があります。
  1. デバッグメッセージをロギングするデバッグレベル
  2. Twebapps/, conf/, logs/およびすべての定義済みコンテキストのベース位置。 これは、TOMCAT_HOME以外のディレクトリからTomcatを起動するために使用します。
  3. 作業ディレクトリの名前
  4. Stack traceや、他のデバッグ情報がデフォルトでレスポンスに含まれるかどうかの設定
ContextInterceptor & RequestInterceptor これらのインタセプタは、ContextManagerで起こるイベントを監視します。 たとえば、ContextInterceptorはTomcatの起動停止イベントを監視し、RequestInterceptorはユーザリクエストが必要とする 様々なサービスを監視します。 Tomcatの管理者はこれらのインターセプタについて詳しく知っている必要はありませんが、開発者は、これがTomcatにどう 「グローバルな」タイプの操作(たとえば、セキュリティやリクエスト単位のログ)を実現されているのかを知っておくべきで す。
Connector Connectorは、Webサーバを経由するか、(スタンドアロン設定の場合には)ユーザのブラウザに直接送信するコネクションを 提供します。 Connectorオブジェクトは、Tomcatワーカスレッドと、様々なクライアントに接続しているソケットからの読み書き要求や返答を 管理します。 Connectorの設定には、以下のようなものがあります.
  1. handlerクラス
  2. handlerが監視するTCP/IPport番号
  3. handlerのサーバソケットのTCP/IPバックログ
このドキュメントの後の方で、Connector設定を使用する方法を説明します。
Context 各Contextは、Webアプリケーションを置くTomcatの階層パスを表します。 Contextには以下のようなものがあります。
  1. コンテキストがあるパス。絶対パスか、ContextManagerホームへの相対パスで指定できます。
  2. デバッグ情報をロギングする際のデバッグレベル
  3. リロードフラグ。 servletを開発するときは、変更した場合にTomcatにリロードさせるのが非常に便利です。 これによって、Tomcatを停止してから再起動しなくても、バグを修正したり、新しいコードをテストできます。 Servletのリロード機能を有効にするためには、reloadableフラグをtrueにしてください。 しかし、変化を検出するのは時間がかかります。 そのうえ、新しいservletは新しいクラスローダオブジェクト中にロードされるので、このクラスのリロードが、キャストエラー を引き起こすことがあります。 これらの問題を避けるために、reloadableフラグをfalseに設定することができます。これによってautoreloadの機能を無効にす ることができます。

追加情報がserver.xmlファイルに見つかるかもしれません。

Tomcatを他のディレクトリから起動する

Tomcatは、デフォルトではTOMCAT_HOME/conf/server.xml を設定として使用します。 デフォルトの設定では、TOMCAT_HOMEをcontextのベースとして使用します。

これは、"-f /path/to/serverxml"オプションを使用して別のサーバ設定ファイルを指定して、さらにコンテキストマネージャのホー ムプロパティを設定すれば、変更することができます。 以下のように、ホーム内に必要なファイルを準備する必要があります。

server.xml の ContextManagerのhomeプロパティが相対的なら、作業ディレクトリも相対的になります。

web.xml

web.xmlの詳細な説明とWebアプリケーション構造(ディレクトリ構成と設定を含みます)は、 Servlet API仕様の第9章、10章および14章で述べられていますので、ここではそれに関して書くつ もりはありません。

しかし、web.xmlに関しては、少しTomcatに関連した「特徴」があります。 Tomcatは、confディレクトリ中にデフォルトのweb.xmlを置いておけば、すべてのコンテキストに対してデフォルトのweb.xmlの値を定義します。 新しいコンテキストを構築する時には、Tomcatは基本設定としてデフォルトのweb.xmlを使用して、さらにアプリケーション専用のweb.xml(そのアプリケー ションのWEB-INF/web.xmlに置きます)を使用して、これらのデフォルト値を上書きします。

Apache WebサーバとTomcatを連動させる設定

今までは、サーバのアドオンとしては説明しないで、スタンドアロン型コンテナとして、それがどのように使用できるかについて説明してきました。 しかし、この形態には以下のような欠点があります。

  1. Tomcatは、静的なページを扱う場合にはApacheほど高速ではありません。
  2. Tomcatは、Apacheのように自由に設定を変更することはできません。
  3. Tomcatは、Apacheほど堅牢ではありません。
  4. 他のWebサーバで長い間開発をおこなってきたサイト、たとえばCGIスクリプト/Server API モジュール/perl/phpなどを使っているサイトがあります。 これらのサイトのすべてが、今までのソフトウェア資産を捨てたいとは思わないでしょう。

このような理由から、実際のサイトでは、静的なコンテンツを配信するためにApacheのようなWebサーバを使用して、Servlet/JSPのアドオンとして Tomcatを使用することを勧めます。

ここでは、徹底的にさまざまな設定を扱うつもりはありません。 代わりに。以下のことについて説明します。

  1. Webサーバとしての基本的な挙動を扱います。
  2. どのような設定が必要なのかを説明します。
  3. これらをApacheを使って説明します。

Webサーバの動作

簡単に説明すれば、WebサーバはクライアントからのHTTPリクエストを常に待っています。 リクエストが届いた時には、サーバはあらかじめ必要なコンテンツを用意しておくことで、リクエストに必要な処理をおこないます。 Servletコンテナを追加すると、この動作が少し変わります。つまり、Webサーバは以下の処理を実行する必要があります。

これに対して、アダプタは、これから処理するリクエストがリクエストURLのどのパターンを元にしていて、どこにリクエストを向けたらよいのかを知っておく必要があります。

ユーザが、バーチャルホストを使用するように設定したいと思っていたり、複数の開発者に同じWebサーバで異なるServletコンテナのJVMを動作 させるようにしたいと思っている時には、さらに問題は複雑になります。 この二つの場合については、後から説明します。

環境設定に必要なこと

誰でも思いつくような、もっとも明確な環境設定は、Servletコンテナの管理にあるServletのURLを明示することです。 これは明確なのですが、どのリクエストをServletコンテナに渡すのかを知っておかねばいけません。 Webサーバ/servletコンテナの連携のためには、さらに以下のような項目を設定する必要があります。

これらすべての情報が、Webサーバの環境設定か、アダプタだけが使用する設定ファイルに含まれていなければいけません。 次の章で環境設定のデモンストレーションをApacheを用いて行います。

Apacheの設定

この節では、ApacheとTomcatを連動させるように設定する方法と、あなたが使う必要がある設定指示子について説明します。 追加情報はjserv install page でも入手することができます。

Tomcatは、起動時に自動的にApache用の設定ファイルをTOMCAT_HOME/conf/tomcat-apache.confに生成します。 たいていの場合は、このファイルを特に変更する必要はなく、Apacheのhttpd.confに("Include TOMCAT_HOME/conf/tomcat-apache.conf"を追加して) 取り込むだけです。たとえば、AJPポートを8007以外にしたいというような要求がある場合には、このファイルをもとに編集して、別ファイル名で保存 して使うこともできます。ただし、自分自身でApacheの設定を管理する場合には、新しいコンテキストを追加するたびに、それをアップデートする必要があります。

Tomcat: 新たにコンテキストを追加したら、TomcatとApacheを再起動する必要があります。 Apacheを再起動しないで、環境を変更することはできません。 そして、TOMCAT_HOME/conf/tomcat-apache.conf ファイルはTomcatが起動する時に生成されるので、Apacheを起動する前にTomcatを起動しておく必要があります。 Tomcatは、起動するたびにTOMCAT_HOME/conf/tomcat-apache.confを上書きするので、カスタマイズした環境設定ファイルは、どこかに保存しておく必要があります。

Apache-Tomcatの環境設定は、Jservと同様にApacheコアの設定指示子を使用しますので、最初のうちはあなたを混乱させるかもしれませんが、以下の2つが設定を簡単にします。

それでは、tomcat.conf ファイルのサンプルを見てみましょう。

最小限のApache-Tomcatの設定
    
###########################################################
#      A minimalistic Apache-Tomcat Configuration File    #
###########################################################

# Note: this file should be appended or included into your httpd.conf

# (1) Loading the jserv module that serves as Tomcat's apache adapter.
LoadModule jserv_module libexec/mod_jserv.so

# (1a) Module dependent configuration.
<IfModule mod_jserv.c>

# (2) Meaning, Apache will not try to start Tomcat.
ApJServManual on
# (2a) Meaning, secure communication is off
ApJServSecretKey DISABLED
# (2b) Meaning, when virtual hosts are used, copy the mount
# points from the base server
ApJServMountCopy on
# (2c) Log level for the jserv module.
ApJServLogLevel notice

# (3) Meaning, the default communication protocol is ajpv12
ApJServDefaultProtocol ajpv12
# (3a) Default location for the Tomcat connectors.
# Located on the same host and on port 8007
ApJServDefaultHost localhost
ApJServDefaultPort 8007

# (4)
ApJServMount /examples /root
# Full URL mount
# ApJServMount /examples ajpv12://hostname:port/root
</IfModule>
            

設定プロセスは、以下で説明するように、大きく4つのステップに分かれているのがわかるでしょう。

  1. このステップでは、Apacheにjserv の共有オブジェクト(NTではdll)をロードします。 これはApacheではよく知られている指示子です。 ロードが成功し、それがmod_jserv.cという名前から作られたモジュールである場合には(1a)、Jserv-Tomcatの設定の残りを開始します。
  2. このステップでは、Jservの様々な初期パラメータを設定します。この初期パラメータは以下の通りです。
  3. このステップでは、デフォルトの通信パラメータをセットします。 基本的に、これはデフォルトで通信に使用するプロトコルはajpv12であり(これを変更してはいけません)、そしてTomcatのプロセスは同一マシン上で動作し、ポート8007で接続待ちしているという意味です。 TomcatがApacheが動作しているマシンとは別のマシンで動作している場合には、ApJServDefaultHostを修正するか、マウントするコンテキストのフルURLを設定します(次を参照)。 また、Tomcatコネクタが使用するポートを8007以外にする場合にも、ApJServDefaultPortを修正するか、コンテキストをマウントする時にフルURLを使用します。
  4. このステップでは、Tomcatにコンテキストをマウントします。 基本的に、これは/examplesで始まるすべてのWebサーバのパスは、Tomcatに転送されるという意味です。 このApJServMount の例は比較的簡単ですが、ApJServMountは、使用するプロトコルや、Tomcatプロセスが接続待ちしているホストについての情報を設定することもできます。 たとえば、以下の例は、ホスト"hostname" 上で動作し、ポート番号 "port"で接続待ちしているTomcatプロセスに、コンテキスト /examplesをマウントしています。
    ApJServMount /examples ajpv12://hostname:port/root
これで、あなたはサンプルファイルのいろいろな設定の指定を理解したと思いますが、どうやってApacheの設定に追加することができるのでしょうか? 1つの"簡単な"方法は、この内容をhttpd.confに書くことですが、これは非常に混乱をきたしやすいでしょう。 そこで、かわりにApacheのinclude指示子を用いるべきです。Apacheの設定ファイル(httpd.conf)の最後に以下の指示子を追加してください。
include <full path to the Tomcat configuration file>
たとえば、以下のように設定します。
include /tome/tomcat/conf/tomcat.conf
jserv モジュールをlibexec (Win32ではmodules)ディレクトリにコピーして、Apacheを再起動 (停止+起動) すれば、Tomcatの設定がApacheに追加されます。 これでTomcatに接続できるようになります。

Jserv モジュール(mod_jserv)の入手

前述のように、TomcatにApacheのリクエストをリダイレクトさせるためにはWebサーバアダプタが必要です。 Apacheに関しては、このアダプタはmod_jservを少し変更したものです。

ここを見て、あなたの使用しているOS(通常は、NT用があります)に適したmod_jservのプリビルド版が 存在すれば、それを使ってください。しかし、(OSが多すぎるとか、開発者が足りないとか、ライフサイクルが短かいなどの理由で)あなたが必要とするネイティブライブラリが まだないかも知れません。さらに、あなたがビルドしたApacheと特定のUNIX系OSにおける小さな違いが原因で、ダイナミックリンクエラーが発生するかもしれません。その場合 には、mod_jservをあなたのシステムでビルドしてみてください(手順はそれほど難しくはありませんから、混乱しないでください! )

UNIX上でのmod_jservのビルド

  1. Tomcatのソース配布をここからダウンロードします。
  2. 任意のディレクトリで解凍します。
  3. モジュールをビルドします。
Win32用のmod_jserv のビルドは、(すでにダウンロードできるDLLがあるので))あまり行わないと思います。それにもかかわらず、どうしてもビルドしたい場合には、 Visual C++をインストールして、以下のようにしてください。
  1. Tomcatのソース配布を、 ここからダウンロードします。
  2. 任意のディレクトリでUnzipします。
  3. モジュールをビルドします。
これでmod_jservはビルド完了です。

Apacheサーバにコンテキストの静的なファイルを処理させる

以前のApache-Tomcat設定ファイルは少し非効率的で、/examplesから始まる名前のリソースに対するすべてのリクエストをTomcatで処理するように指定 していました。本当にその必要があるのでしょうか? Servletコンテキストの一部として使用される(たとえばimagesや静的なHTMLのような)静的なファイルは多いので すが、このファイルをTomcatが処理する必要があるのでしょうか?

実際に、そうする理由があるかもしれません。たとえば、以下のような場合です。

  1. これらのリソースに対して、Tomcatの側でセキュリティを設定したいのかもしれません。
  2. 通信をモニタして、静的なリソースに対するユーザのリクエストを追跡したいかもしれません。
しかし、一般にこのような場合ではなければ、Tomcatが静的なファイルを持つことは、単にCPUを浪費するだけです。 かわりに、これらの静的なファイルをTomcatではなくApacheが処理するようにしなければいけません。

Apacheに静的なファイルを処理させるためには、以下の設定が必要です。

  1. Apacheに、すべてのServletのリクエストをTomcatに送るように指定しなければなりません。
  2. Apacheに、すべてのJSPのリクエストをTomcatに送るように指定しなければなりません。
そして、他のリクエストをApacheが処理するようにします。 その設定以下のようにをおこなっているサンプルのtomcat.confを見てください。

Apacheが静的なコンテンツを処理するApache-Tomcatの設定
    
######################################################################
#              Apache-Tomcat Smart Context Redirection               #
######################################################################
LoadModule jserv_module modules/ApacheModuleJServ.dll
<IfModule mod_jserv.c>
ApJServManual on
ApJServDefaultProtocol ajpv12
ApJServSecretKey DISABLED
ApJServMountCopy on
ApJServLogLevel notice

ApJServDefaultHost localhost
ApJServDefaultPort 8007

#
# Mounting a single smart context:
#
# (1) Make Apache know about the context location.
Alias /examples c:/jakarta-tomcat/webapps/examples
# (2) Optional, customize Apache context service.
<Directory "c:/jakarta-tomcat/webapps/examples">
    Options Indexes FollowSymLinks
# (2a) No directory indexing for the context root.
#    Options -Indexes
# (2b) Set index.jsp to be the directory index file.
#    DirectoryIndex index.jsp
</Directory>
# (3) Protect the WEB-INF directory from tampering.
<Location /examples/WEB-INF/>
    AllowOverride None
    deny from all
</Location>
# (4) Instructing Apache to send all the .jsp files under the context to the 
# jserv servlet handler. 
<LocationMatch /examples/*.jsp>
    SetHandler jserv-servlet
</LocationMatch>
# (5) Direct known servlet URLs to Tomcat.
ApJServMount /examples/servlet /examples

# (6) Optional, direct servlet only contexts to Tomcat.
ApJServMount /servlet /ROOT
</IfModule>
      

見ればわかりますが、この設定ファイルのばじめの方は、先ほどの例と同じです。 ただし、最後のステップ(コンテキストのマウント)は、一連のApacheと今から説明する ApJServ設定指示子で置き換えられています。

  1. このステップでは、Apacheにコンテキストの場所とバーチャルディレクトリへのエイリアスを指定します。 これによって、Apacheはこのディレクトリのファイルにアクセスできるようになります。
  2. このオプションのステップは、さらにコンテキストを処理する方法をApacheへ指定します。 たとえば、ディレクトリインデックス(リスト表示)を許可するかとか、特別なインデックスファイルを設定する かのようなことです。
  3. このステップでは、Apacheに対してWEB-INFディレクトリにクライアントがアクセスできないように指定します。 セキュリティ上の理由から、訪問者がWEB-INFディレクトリの内容を見れないようにすることは重要です。 たとえば、web.xmlは、侵入者にとって重要な情報を含んでいます。このステップが、コンテンツを訪問者から保護します。
  4. このステップは、jservのServletハンドラを使ったコンテキスト内の、すべてのJSPファイルを処理するようにApacheに指定します。 Servletハンドラは、デフォルトのホストとポートを基に、これらのリクエストをリダイレクトします。
  5. このステップは、特定のServletのURLをTomcatにマウントします。 ただし、使用したいServletのURLと同じ数だけ、マウント指示子を記述しなければならないことに注意してください。
  6. 最後のステップは、TomcatにServletのコンテキストのみを追加する場合の例です。
この設定の方が、最初の例よりもはるかに複雑でエラーが発生しやすいことは明白ですが、性能を向上させるためには実施する価値はあります。

複数のTomcatのJVMの設定

異なるJVMで異なるコンテキストを実行すると便利なことがあります。たとえば、以下のような場合です。

異なるコンテキストを異なるJVMで処理するように実装することは非常に簡単で、たとえば以下の設定ファイルがこの方法を示しています。

コンテキストのJVMごとのApache-Tomcatの設定
    
######################################################################
#             Apache-Tomcat with JVM per Context                     #
######################################################################
LoadModule jserv_module modules/ApacheModuleJServ.dll
<IfModule mod_jserv.c>
ApJServManual on
ApJServDefaultProtocol ajpv12
ApJServSecretKey DISABLED
ApJServMountCopy on
ApJServLogLevel notice

ApJServDefaultHost localhost
ApJServDefaultPort 8007

# Mounting the first context.
ApJServMount /joe ajpv12://joe.corp.com:8007/joe

# Mounting the second context.
ApJServMount /bill ajpv12://bill.corp.com:8007/bill
</IfModule>
            

この例でわかるように、ajpのフルURLをマウントすれば、いくつかのJVMを(異なるマシンで動作していても)使用できます。 実際には、このフルURLに、Tomcatプロセスが動作するホストとポートを指定します。

2つのTomcatプロセスを同一マシン上で実行させたい場合には、それぞれが異なる接続ポートを使用するように設定しなければいけません。 たとえば、2つのJVMがlocalhostで実行されるとすると、Apache-Tomcatの設定以下のようになります。

同じマシンで複数のJVMを使用するApache-Tomcatの設定
    
######################################################################
#      Apache-Tomcat with Same Machine JVM per Context               #
######################################################################
LoadModule jserv_module modules/ApacheModuleJServ.dll
<IfModule mod_jserv.c>
ApJServManual on
ApJServDefaultProtocol ajpv12
ApJServSecretKey DISABLED
ApJServMountCopy on
ApJServLogLevel notice

ApJServDefaultHost localhost
ApJServDefaultPort 8007

# Mounting the first context.
ApJServMount /joe ajpv12://localhost:8007/joe

# Mounting the second context.
ApJServMount /bill ajpv12://localhost:8009/bill
</IfModule>
            

上のファイルを見れば、同一マシン上の異なるポートを指定している2つの明示的なApJServマウントポイントがあることがわかります。 つまり、この設定をおこなうためには、さらにserver.xmlファイルの設定が必要になるのは明らかです。 このファイルのように異なるTomcatプロセスを動かす場合には、異なる<Connector>設定が必要です。 実際には、次のサンプルで示すように異なる<Connector>を持つ2つの異なるserver.xmlファイル(server_joe.xmlとserver_bill.xml)が 必要です。

Joeのserver.xmlファイル
    
<?xml version="1.0" encoding="ISO-8859-1"?>

<Server>
    <!-- Debug low-level events in XmlMapper startup -->
    <xmlmapper:debug level="0" />

    <!--  @@@
        Note, the log files are suffixed with _joe to distinguish
        them from the bill files. 
    -->

    <Logger name="tc_log" 
            path="logs/tomcat_joe.log"
            customOutput="yes" />

    <Logger name="servlet_log" 
            path="logs/servlet_joe.log"
            customOutput="yes" />

    <Logger name="JASPER_LOG" 
        path="logs/jasper_joe.log"
            verbosityLevel = "INFORMATION" />

    <!--  @@@
        Note, the work directory is suffixed with _joe to distinguish
        it from the bill work directory.
    -->
    <ContextManager debug="0" workDir="work_joe" >
        <!-- ==================== Interceptors ==================== -->

        ...
        
        <!-- ==================== Connectors ==================== -->

        ...

        <!-- Apache AJP12 support. This is also used to shut down tomcat.
          -->
        <!-- @@@ This connector uses port number 8007 for it's ajp communication -->
        <Connector className="org.apache.tomcat.service.PoolTcpConnector">
            <Parameter name="handler" 
       value="org.apache.tomcat.service.connector.Ajp12ConnectionHandler"/>
            <Parameter name="port" value="8007"/>
        </Connector>
        
        <!-- ==================== Special webapps ==================== -->

        <!-- @@@ the /jow context -->
        <Context path="/joe" docBase="webapps/joe" debug="0" reloadable="true" > 
        </Context>
    </ContextManager>
</Server>       
            

server_joe.xmlを見ると、<Connector>がポート8007に設定されているのがわかります。 一方server_bill.xml(次に示します)を見ると、<Connector>はポート番号8009に設定さ れています。

Billのserver.xmlファイル
    
<?xml version="1.0" encoding="ISO-8859-1"?>

<Server>
    <!-- Debug low-level events in XmlMapper startup -->
    <xmlmapper:debug level="0" />

    <!--  @@@
        Note, the log files are suffixed with _bill to distinguish
        them from the joe files. 
    -->

    <Logger name="tc_log" 
            path="logs/tomcat_bill.log"
            customOutput="yes" />

    <Logger name="servlet_log" 
            path="logs/servlet_bill.log"
            customOutput="yes" />

    <Logger name="JASPER_LOG" 
        path="logs/jasper_bill.log"
            verbosityLevel = "INFORMATION" />

    <!--  @@@
        Note, the work directory is suffixed with _bill to distinguish
        it from the joe work directory.
    -->
    <ContextManager debug="0" workDir="work_bill" >

        <!-- ==================== Interceptors ==================== -->

        ...
        
        <!-- ==================== Connectors ==================== -->

        ...

        <!-- Apache AJP12 support. This is also used to shut down tomcat.
          -->
        <!-- @@@ This connector uses port number 8009 for it's ajp communication -->
        <Connector className="org.apache.tomcat.service.PoolTcpConnector">
            <Parameter name="handler" 
       value="org.apache.tomcat.service.connector.Ajp12ConnectionHandler"/>
            <Parameter name="port" value="8009"/>
        </Connector>
        
        <!-- ==================== Special webapps ==================== -->
    
        <!-- @@@ the /bill context -->
        <Context path="/bill" docBase="webapps/bill" debug="0" reloadable="true" > 
        </Context>
    </ContextManager>
</Server>       
          

ポートの設定が、joeとbillの設定の唯一の違いではありません。 変更しなければならない4個所には、xmlファイル中に@@@マークをつけています。 これ違いは、2つのTomcatプロセスのログやワークスペースが互いに上書きしないために必要です。

そして、-f コマンドラインオプションを使用して、2つのTomcatプロセスを起動します。

bin\starup -f conf\server_joe.xml
bin\starup -f conf\server_bill.xml
こうすれば、異なるURLパスのプレフィクスに基づいて、Apacheからそれらにアクセスします。

バーチャルホストの設定

Tomcat Ver3.2では、バーチャルホストをサポートしています。実際には、バーチャルホストの設定は (直前の節で説明した)複数のJVMの設定ととても似ています。理由は簡単で、Tomcat 3.2では、それぞ れのバーチャルホストは異なるTomcatプロセスで実行されるように実装されているからです。

現在(Ver 3.2)のTomcatでは、バーチャルホストの認識には、(ApacheやNetscapeのような)Webサーバを使用しています。 Tomcatアダプタは、Webサーバのバーチャルホストサポートを使用して、あるバーチャルホストに対するリクエストを、 そのバーチャルホストのコンテキストを持っているJVMにリダイレクトします。これは、(たとえば)vhost1、vhost2という 2つのバーチャルホストがある場合に、2つのJVMを使用するということで、一方ではvhost1のコンテキストが動作し、もう 一方ではvhost2のコンテキストが動作します。これらのJVMは互いに他方の存在を知らないので、実際には、それらはバー チャルホストの概念を認識しているわけではありません。すべてのバーチャルホストのロジックは、Webサーバのアダプタ 内に閉じています。よりはっきりさせるために、次のApache-Tomcatコンフィグレーションを見てください。

バーチャルファイルサポートのApache-Tomcatの設定
    
######################################################################
#        Apache Tomcat Virtual Hosts Sample Configuration            #
######################################################################
LoadModule jserv_module modules/ApacheModuleJServ.dll
<IfModule mod_jserv.c>
ApJServManual on
ApJServDefaultProtocol ajpv12
ApJServSecretKey DISABLED
ApJServMountCopy on
ApJServLogLevel notice

ApJServDefaultHost localhost
ApJServDefaultPort 8007

# 1 Creating an Apache virtual host configuration
NameVirtualHost 9.148.16.139

# 2 Mounting the first virtual host
<VirtualHost 9.148.16.139>
ServerName www.vhost1.com
ApJServMount /examples ajpv12://localhost:8007/examples
</VirtualHost>

# 3 Mounting the second virtual host
<VirtualHost 9.148.16.139>
ServerName www.vhost2.com
ApJServMount /examples ajpv12://localhost:8009/examples
</VirtualHost>
</IfModule>
            

見ればわかりますが、ステップ1、2、3では、Apacheに2つのバーチャルホストを定義して、 それぞれのajpv12のURLに/examplesコンテキストをマウントしています。それぞれのajpv12の URLは、そのバーチャルホストを含んだJVMを示しています。2つのJVMの環境設定は、前の節で 解説した設定と非常によく似ていることからわかるように、2つの異なるserver.xmlファイル (それぞれのバーチャルホストプロセスのもの)が必要であり、Tomcatプロセスを-f コマンドラ イン引数で起動する必要があります。そうすれば、Apacheが異なるホスト名でアクセスされる たびに、アダプタが適切なJVMにリダイレクトするようにできるでしょう。

バーチャルホストサポートの改善の必要性
それぞれのバーチャルホストに異なるJVMを用いる実装は、非常に深刻なスケーラビリティの 問題が存在します。次のバージョンのTomcatでは、同一のTomcatのJVM上で、バーチャルホス トをサポートすることができるようになるでしょう。

実運用における設定のTips

デフォルトでは、Tomcatの配布には、Tomcatをはじめて使用するユーザにも使いやすく、操作が 理解しやすい("out of the box")ことを主な目的としている簡単な設定が含まれています。 しかし、この設定はTomcatを現実のサイトで用いるためにはベストではありません。たとえば、 実際のサイトでは、性能のチューニングや、(たとえば、パスの追加のような)サイト固有のセッ ティングが必要になるでしょう。そこで、この節では、Tomcatベースのサイトを公開する前にし なければならない最初のステップについて説明します。

バッチファイルの変更とカスタマイズ

前の節で、簡単に使えるように起動スクリプトが用意されていると述べました。しかし、以下の ような設定が必要な場合には、スクリプトを変更しなければいけないことがあります。

これらの変更の一部は、基本スクリプトを直接変更しなくても可能です。たとえば、Tomcatのスクリプトは、TOMCAT_OPTS という名前の環境変数を使用すれば、(メモリの設定のような)JVMに追加するコマンドライン引数を設定できます。 UNIXでは、".tomcatrc" というファイルをホームディレクトリに作成すれば、PATHやJAVA_HOME、TOMCAT_HOME、 CLASSPATH といった環境変数の情報をこのファイルから読み込みます。しかし、NTでは(UNIXでもJVMのコマンドラインのような変更を するときに)起動スクリプトの一部を書き換えなければいけません。
ためらわないで、やってみてください。

JVMのデフォルトの設定の変更

tomcatスクリプトのデフォルトのJVMの設定はすべてデフォルトに頼っていて、非常に単純です。 Tomcatの性能を向上するためには、以下の点について検討してください。

  1. JVMのメモリ設定を変更します。通常JVMは、まずある初期サイズ分のJavaヒープを確保して、 さらに必要なときに不足した分を割り当てます。それにもかかわらず、負荷が高いサイトでは、 より多くのメモリをJVMに与えれば、Tomcatの性能が向上します。 -Xms/-Xmx/-ms/-mxのようなコマンドライン引数を使用してJava ヒープの最小/最大サイズを設定 します(実際に性能が向上したかどうかを確認してください)。
  2. JVMのスレッドの設定を変更します。Linux用のSUN JDK1.2.2は、グリーンスレッドとネイティ ブスレッドの両方をサポートしています。一般に、ネイティブスレッドはI/Oがボトルネックになり やすいアプリケーションの性能を向上させるのが知られています。一方、グリーンスレッドは、マ シンの負荷がネイティブスレッドより少なくなります。これらの2つのスレッドモデルで実験して、 あなたのサイトにはどちらが良いか確認してください(たいていはネイティブスレッドの方が良いです)。
  3. スレッドに最適なJVMを選択します。数社のJVMベンダーがありますが、たとえばLinux用なら (2000/03/21の時点で) SUN JDK1.2.2とIBM JDK1.1.8という2つの製品レベルのJVMがあります。あなたの アプリケーションが特定のバージョンのJDKの機能を必要としない場合には、2つのJVMを使ってベンチ マークをおこなって、性能のよい方を選んでください。なお、私の(Gal Shachor)の個人的なテストでは、 IBMのJVMの方がSunのものより高速なようです(訳注: これはHotSpotをリリースする前の話なので、現在は 状況が異なります)が、自分自身でチェックして、数値がよい方にしてください。

コネクタを変更する

Tomcatのデフォルトのserver.xmlで設定されているコネクタは、次のserver.xmlの一部で設定されている2つの コネクタを含んでいます。

server.xmlの2つのデフォルトコネクタ
        <!-- (1) HTTP Connector for stand-alone operation -->
        <Connector className="org.apache.tomcat.service.PoolTcpConnector">
            <Parameter name="handler"
                value="org.apache.tomcat.service.http.HttpConnectionHandler"/>
            <Parameter name="port"
                value="8080"/>
        </Connector>

        <!-- (2) AJPV12 Connector for out-of-process operation -->
        <Connector className="org.apache.tomcat.service.PoolTcpConnector">
            <Parameter name="handler"
                value="org.apache.tomcat.service.connector.Ajp12ConnectionHandler"/>
            <Parameter name="port"
                value="8007"/>
        </Connector>
                

  1. ポート番号8080でHTTPリクエストを接続待ちしているコネクタです。 このコネクタは、スタンドアロンで使用する場合に必要です。
  2. ポート番号8007でAJPV12リクエストを接続待ちしているコネクタです。 このコネクタは、Webサーバと統合(プロセス外Servletコンテナとして統合)する場合に必要です。
AJPV12コネクタはTomcatがシャットダウンする際に必要です。しかし、HTTPコネクタはスタンドアロン 稼動が不要であれば取り除いて構いません。

コネクタでスレッドプールを使用する

Tomcatは、マルチスレッド化されたServletコンテナです。これはスレッドが、それぞれのリクエストを実行することを意味しています。 デフォルトでは、Tomcat3.2はリクエストが到達したときに新しいスレッドを生成し、それを起動してリクエストを処理します。 この挙動は、負荷の高いサイトにとっては、以下のような理由から問題があります。

これらの問題の解決策は、スレッドプールを使用することです。スレッドプールを使用しているServletコンテナでは、直接それらのスレッドを管理 する必要はありません。スレッドが必要になった時には、新しいスレッドを割り当てる代わりに、プールに問い合わせて、処理を終了した 時には、スレッドをプールに返します。現在、以下のような洗練されたスレッド管理技術を実装したスレッドプールを使用することができ ます。
  1. スレッドを"open"な状態に保持しておき、何度も再利用します。 これは絶え間なくスレッドを作成、破棄することに関連した問題を解消します。
  2. 同時に使用するスレッド数の上限を設定します。これは無制限なスレッド割り当てに関連した、リソース割り当て問題が発生するの を防ぎます。
上記の技術はいろいろな点で改良することができますが、それは単なる改良にすぎません。 というのは、スレッドプールの主な利点は、スレッドの再利用と、リソース消費を制限する並行性の上限を持っていることです。

Tomcatでスレッドプールを使用するのは簡単で、<Connector>設定で、PoolTcpConnectorを使用するだけです。 たとえば、以下のserver.xmlの一部は、ajpv12のプール化されたコネクタを定義します。

プール化されたajpv12コネクタ
        <!-- A pooled AJPV12 Connector for out-of-process operation -->
        <Connector className="org.apache.tomcat.service.PoolTcpConnector">
            <Parameter
                name="handler"
                value="org.apache.tomcat.service.connector.Ajp12ConnectionHandler"/>
            <Parameter
                name="port"
                value="8007"/>
        </Connector>
                

この設定はとても簡単で、以下のような(デフォルトの)挙動を指定しています。 デフォルトの設定は、平均10から40の並行リクエスト数の中程度の負荷のサイトに適しています。 あなたのサイトがこれとは違う場合には、(たとえば上限を減らすように)設定を変更するべきです。 server.xmlの<Connector>要素を使って、以下の示すようにプールを設定することができます。

スレッドプールの設定
        <!-- A pooled AJPV12 Connector for out-of-process operation -->
        <Connector className="org.apache.tomcat.service.PoolTcpConnector">
            <Parameter
                name="handler"
                value="org.apache.tomcat.service.connector.Ajp12ConnectionHandler"/>
            <Parameter
                name="port"
                value="8007"/>
            <Parameter
                name="max_threads"
                value="30"/>
            <Parameter
                name="max_spare_threads"
                value="20"/>
            <Parameter
                name="min_spare_threads"
                value="5" />
        </Connector>
                

これから、プールは次の3つの設定パラメータを持っていることがわかります。 プールの挙動を調整するために、上のパラメタを必要に応じて使用してください。

Servletオートリロードを無効にする

Servletオートリロードは、開発時には本当に便利です。 しかし、それは非常に(性能が低下するという点で)コストがかかるだけでなく、あるクラスローダがロードしたクラスが、 現在のクラスローダがロードしたクラスと同時に使用できない時に、あなたのアプリケーションに奇妙なコンフリクトが発生する可能性があります。

従って、クラスリロードがあなたの設定に本当に必要でないのなら、コンテキストのreloadableフラグは無効にすべきです。

著者

このドキュメントは、以下の人物が作成しました。

さらに、以下の人々に協力していただきました (アルファベット順)。

[訳注: これは角瀬和博が翻訳しました。日本語訳に対するコメントは、jajakarta-report@nekoyanagi.com宛に送って下さい。]

Copyright ©1999 The Apache Software Foundation
Legal Stuff They Make Us Say
Contact Information