naobe @ ウィキ
Tomcat
最終更新:
Bot(ページ名リンク)
-
view
OpenSourceに戻る
バージョンと標準
Tomcatバージョン | servlet | jsp |
6.0 | 2.4 | 2.0 |
5.5 | 2.3 | 2.0 |
ソースプログラム
Tomcat6.0.3.5ソース解読
苦労しました。大筋は合っていると思う。
Tomcat解読.xls

起動
Bootstrap#startからCatalina#startを呼び出す。Server#startを実行し、Server.xmlで設定したポート番号でsocketのstreamからreadする。readした文字が"SHUTDOWN"なら停止処理を実行する。
server.xmlからデフォルトのポート番号は、8005になる。
<Server port="8005" shutdown="SHUTDOWN">
public class Catalina extends Embedded { public void start() { ((Lifecycle) getServer()).start(); if (await) { await(); stop(); } public void await() { getServer().await(); } public final class StandardServer public void await() { awaitSocket = new ServerSocket(port, 1, InetAddress.getByName("localhost")); while (!stopAwait) { ServerSocket serverSocket = awaitSocket; Socket socket = null; StringBuilder command = new StringBuilder(); try { InputStream stream = null; socket = serverSocket.accept(); socket.setSoTimeout(10 * 1000); // Ten seconds stream = socket.getInputStream(); // Read a set of characters from the socket int expected = 1024; // Cut off to avoid DoS attack while (expected < shutdown.length()) { if (random == null) random = new Random(); expected += (random.nextInt() % 1024); } while (expected > 0) { int ch = -1; try { ch = stream.read(); } catch (IOException e) { log.warn("StandardServer.await: read: ", e); ch = -1; } if (ch < 32) // Control character or EOF terminates loop break; command.append((char) ch); expected--; } // Match against our command string boolean match = command.toString().equals(shutdown); if (match) { break; } }
停止
Bootstrap#stopServerからCatalina#stopServerを呼び出す。
ソースは以下になっている。Serverのポート番号からソケットを作成して、"SHUTDOWN"という文字を送信している。
ソースは以下になっている。Serverのポート番号からソケットを作成して、"SHUTDOWN"という文字を送信している。
public class Catalina extends Embedded { public void stopServer(String[] arguments) { ・・・・ s = getServer(); try { if (s.getPort()>0) { String hostAddress = InetAddress.getByName("localhost").getHostAddress(); Socket socket = new Socket(hostAddress, getServer().getPort()); OutputStream stream = socket.getOutputStream(); String shutdown = s.getShutdown();// "SHUTDOWN" for (int i = 0; i < shutdown.length(); i++) stream.write(shutdown.charAt(i)); stream.flush(); stream.close(); socket.close(); } else { log.error(sm.getString("catalina.stopServer")); System.exit(1); } } catch (IOException e) { log.error("Catalina.stop: ", e); System.exit(1); }
レルム
レルムとは、ユーザ、パスワード、ロールをまとめたもの。ユーザDBのエントリに相当する。UserDatabaseRealm、JDBCレルム、DataSourceレルム、JNDIレルムがある。web.xmlのセキュリティ設定で制限されたURLをアクセスするときに認証するためのユーザ、パスワード、ロールを定義したもの。web.xmlでは、URLとHTTPメソッドに対してロールを割り当てる。
UserDatabaseRealm
JNDIを介してアクセスするがデフォルトでは$CATALINA_BASE/conf/tomcat-user.xmlを使う。
$CATALINA_BASE/conf/server.xmlに以下を設定する。
$CATALINA_BASE/conf/server.xmlに以下を設定する。
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
<Engine>直下に設定すると、Tomcat内の全ての仮想ホストで共通の設定になる
<Host>直下に設定すると、仮想ホスト内で共通の設定になる。
<Context>直下に設定すると、WEBアプリケーション内で共通の設定になる。
<Host>直下に設定すると、仮想ホスト内で共通の設定になる。
<Context>直下に設定すると、WEBアプリケーション内で共通の設定になる。
- web.xmlで制限をかけたURLにアクセスすると、認証(BASIC,DIGEST,FORM)を行う。
- 認証に成功すると、ユーザを内部に保管して、指定したURLに移動する。
- BASIC認証の場合は、ブラウザを閉じる(TCPコネクションclose ?)までユーザをキャッシュする(認証を行わない)。
- FORM認証の場合は、セッションタイムアウトになるまでユーザをキャッシュする。キャッシュされたユーザはセッションの直列化をまたがって保存されない(APサーバ停止によるセッションの保管のことでしょう)。
tomcat-users.xmlの設定例
<tomcat-users> <user name="tomcat" password="tomcat" roles="tomcat" /> <user name="role1" password="tomcat" roles="role1" /> <user name="both" password="tomcat" roles="tomcat,role1" /> </tomcat-users>
データソース
Tomcat6.Xの内部データソースは、org.apache.tomcat.dbcp.dbcp.BasicDataSource。これは、org.apache.commons.dbcp.BasicDataSourceと同じもの。
http://www.flsi.co.jp/Java_text/vol140.htm 参照
http://www.flsi.co.jp/Java_text/vol140.htm 参照
設定
項目 | 内容 |
---|---|
親を優先とするクラスローダの移譲 | web.xmlのcontextのdelegate属性にtrueを設定する |
セッションタイムアウト | conf/web.xmlのsession-configタグを修正するとすべてのWEBアプリケーションに影響する。WEBアプリケーションのweb.xmlを修正すると、WEBアプリケーションのみ影響する。単位は分。 |
サーバ化
【参考】
http://miyazaki.ddo.jp/linuxserver/tomcatautostart.html
http://www.atmarkit.co.jp/fjava/rensai4/safetomcat_01/safetomcat_01_1.html
http://miyazaki.ddo.jp/linuxserver/tomcatautostart.html
http://www.atmarkit.co.jp/fjava/rensai4/safetomcat_01/safetomcat_01_1.html
【環境】
tomcat バージョン:6.0
OS: CentOS 5.5
tomcat バージョン:6.0
OS: CentOS 5.5
専用ユーザ作成
#adduser -d tomcatインストールディレクトリ -s /sbin/nologin tomcat
所有者の変更
#chown -R tomcat tomcatインストールディレクトリ #chmod -R g-r,g-w,g-x tomcatインストールディレクトリ
JAVA_HOME設定
$TOMCAT_INSTALL/binsetenv.shに以下を設定
JAVA_HOME=JAVAホームディレクトリ JRE_HOME=JAVAホームディレクトリ
commons-daemon
commons-daemon概要
Javaは、signalに対応していないため、サーバの急なシャットダウンなどのタイミングでサーバリソース(TCP接続、DBとのコネクションなど)の正規の終結処理ができない。CとJavaを組み合わせてこれに対応したもの。UNIXとWindowsで異なるモジュールを提供する。UNIX版は、jsvc。
commons-daemonのインストール
- commons-daemon-1.0.5-src.tar.gz
- commons-daemon-1.0.5.jar
- commons-daemon-1.0.5-src.tar.gzを展開し以下を実行。
[hoge@athlon4 tmp]$ cd commons-daemon-1.0.5-src [hoge@athlon4 commons-daemon-1.0.5-src]$ cd src/ [hoge@athlon4 src]$ cd native/ [hoge@athlon4 native]$ cd unix/ [hoge@athlon4 unix]$ sh support/buildconf.sh [hoge@athlon4 unix]$ ./configure *** Current host *** checking build system type... i686-pc-linux-gnu checking host system type... i686-pc-linux-gnu checking cached host system type... ok *** C-Language compilation tools *** checking for gcc... gcc checking for C compiler default output file name... a.out checking whether the C compiler works... yes checking whether we are cross compiling... no checking for suffix of executables... checking for suffix of object files... o checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes checking for gcc option to accept ANSI C... none needed checking for ranlib... ranlib checking for strip... strip *** Host support *** checking C flags dependant on host system type... ok *** Java compilation tools *** checking for sablevm... NONE checking for kaffe... NONE checking for javac... /usr/java/jdk1.6.0_21/bin/javac /usr/java/jdk1.6.0_21/bin/javac checking wether the Java compiler (/usr/java/jdk1.6.0_21/bin/javac) works... yes checking for jar... /usr/java/jdk1.6.0_21/bin/jar gcc flags added checking for cap_init in -lcap... yes *** Writing output files *** configure: creating ./config.status config.status: creating [[Makefile]] config.status: creating Makedefs config.status: creating native/Makefile *** All done *** Now you can issue "make" [hoge@athlon4 unix]$ make clean (cd native; make clean) make[1]: ディレクトリ `/home/hoge/tmp/commons-daemon-1.0.5-src/src/native/unix/native' に入ります rm -f arguments.o debug.o dso-dlfcn.o dso-dyld.o help.o home.o java.o location.o replace.o locks.o signals.o ../jsvc jsvc-unix.o libservice.a make[1]: ディレクトリ `/home/hoge/tmp/commons-daemon-1.0.5-src/src/native/unix/native' から出ます [hoge@athlon4 unix]$ make (cd native; make all) make[1]: ディレクトリ `/home/hoge/tmp/commons-daemon-1.0.5-src/src/native/unix/native' に入ります gcc -g -O2 -DOS_LINUX -DDSO_DLFCN -DCPU=\"i386\" -Wall -Wstrict-prototypes -DHAVE_LIBCAP -I/usr/java/jdk1.6.0_21/include -I/usr/java/jdk1.6.0_21/include/linux -c jsvc-unix.c -o jsvc-unix.o gcc -g -O2 -DOS_LINUX -DDSO_DLFCN -DCPU=\"i386\" -Wall -Wstrict-prototypes -DHAVE_LIBCAP -I/usr/java/jdk1.6.0_21/include -I/usr/java/jdk1.6.0_21/include/linux -c arguments.c -o arguments.o gcc -g -O2 -DOS_LINUX -DDSO_DLFCN -DCPU=\"i386\" -Wall -Wstrict-prototypes -DHAVE_LIBCAP -I/usr/java/jdk1.6.0_21/include -I/usr/java/jdk1.6.0_21/include/linux -c debug.c -o debug.o gcc -g -O2 -DOS_LINUX -DDSO_DLFCN -DCPU=\"i386\" -Wall -Wstrict-prototypes -DHAVE_LIBCAP -I/usr/java/jdk1.6.0_21/include -I/usr/java/jdk1.6.0_21/include/linux -c dso-dlfcn.c -o dso-dlfcn.o gcc -g -O2 -DOS_LINUX -DDSO_DLFCN -DCPU=\"i386\" -Wall -Wstrict-prototypes -DHAVE_LIBCAP -I/usr/java/jdk1.6.0_21/include -I/usr/java/jdk1.6.0_21/include/linux -c dso-dyld.c -o dso-dyld.o gcc -g -O2 -DOS_LINUX -DDSO_DLFCN -DCPU=\"i386\" -Wall -Wstrict-prototypes -DHAVE_LIBCAP -I/usr/java/jdk1.6.0_21/include -I/usr/java/jdk1.6.0_21/include/linux -c help.c -o help.o gcc -g -O2 -DOS_LINUX -DDSO_DLFCN -DCPU=\"i386\" -Wall -Wstrict-prototypes -DHAVE_LIBCAP -I/usr/java/jdk1.6.0_21/include -I/usr/java/jdk1.6.0_21/include/linux -c home.c -o home.o gcc -g -O2 -DOS_LINUX -DDSO_DLFCN -DCPU=\"i386\" -Wall -Wstrict-prototypes -DHAVE_LIBCAP -I/usr/java/jdk1.6.0_21/include -I/usr/java/jdk1.6.0_21/include/linux -c java.c -o java.o gcc -g -O2 -DOS_LINUX -DDSO_DLFCN -DCPU=\"i386\" -Wall -Wstrict-prototypes -DHAVE_LIBCAP -I/usr/java/jdk1.6.0_21/include -I/usr/java/jdk1.6.0_21/include/linux -c location.c -o location.o gcc -g -O2 -DOS_LINUX -DDSO_DLFCN -DCPU=\"i386\" -Wall -Wstrict-prototypes -DHAVE_LIBCAP -I/usr/java/jdk1.6.0_21/include -I/usr/java/jdk1.6.0_21/include/linux -c replace.c -o replace.o gcc -g -O2 -DOS_LINUX -DDSO_DLFCN -DCPU=\"i386\" -Wall -Wstrict-prototypes -DHAVE_LIBCAP -I/usr/java/jdk1.6.0_21/include -I/usr/java/jdk1.6.0_21/include/linux -c locks.c -o locks.o gcc -g -O2 -DOS_LINUX -DDSO_DLFCN -DCPU=\"i386\" -Wall -Wstrict-prototypes -DHAVE_LIBCAP -I/usr/java/jdk1.6.0_21/include -I/usr/java/jdk1.6.0_21/include/linux -c signals.c -o signals.o ar cr libservice.a arguments.o debug.o dso-dlfcn.o dso-dyld.o help.o home.o java.o location.o replace.o locks.o signals.o ranlib libservice.a gcc jsvc-unix.o libservice.a -ldl -lpthread -lcap -o ../jsvc make[1]: ディレクトリ `/home/hoge/tmp/commons-daemon-1.0.5-src/src/native/unix/native' から出ます [hoge@athlon4 unix]$
- 作成されたjsvcのownerをtomcatに修正して${TOMCAT_HOME}/binにコピー
- /etc/init.dに起動スクリプト作成
# # source function # . /etc/init.d/functions # # That is for Tomcat-5.0.x (Apache Tomcat/5.0) # # Adapt the following lines to your configuration JAVA_HOME=/usr/java/jdk1.6.0_21 CATALINA_HOME=/opt/apache-tomcat-6.0.29 TOMCAT_USER=tomcat # for multi instances adapt those lines. TMP_DIR=/tmp PID_FILE=/var/run/jsvc.pid LOCKFILE=/var/lock/subsys/tomcat CATALINA_BASE=$CATALINA_HOME CATALINA_OPTS= CLASSPATH=\ $JAVA_HOME/lib/tools.jar:\ #$CATALINA_HOME/bin/commons-daemon.jar:\ $CATALINA_HOME/bin/commons-daemon-1.0.5.jar:\ $CATALINA_HOME/bin/bootstrap.jar case "$1" in start) echo -n "Starting jsvc: " # # Start Tomcat # $CATALINA_HOME/bin/jsvc \ -user $TOMCAT_USER \ -home $JAVA_HOME \ -Dcatalina.home=$CATALINA_HOME \ -Dcatalina.base=$CATALINA_BASE \ -Djava.io.tmpdir=$TMP_DIR \ -wait 10 \ -pidfile $PID_FILE \ -outfile $CATALINA_HOME/logs/catalina.out \ -errfile '&1' \ $CATALINA_OPTS \ -cp $CLASSPATH \ org.apache.catalina.startup.Bootstrap # # To get a verbose JVM #-verbose \ # To get a debug of jsvc. #-debug \ RETVAL=$? if [ $RETVAL = 0 ]; then echo_success touch $LOCKFILE else echo_failure fi echo ;; stop) # # Stop Tomcat # $CATALINA_HOME/bin/jsvc \ -stop \ -pidfile $PID_FILE \ org.apache.catalina.startup.Bootstrap RETVAL=$? if [ $RETVAL = 0 ]; then echo_success rm -f $PIDFILE $LOCKFILE else echo_failure fi echo ;; *) echo "Usage tomcat start/stop" exit 1;; esac
プロセス
上記の設定でjsvcを起動すると、オーナがrootのプロセスとtomcatのプロセスが常駐する。指定のポート番号をlistenしているのは、tomcatのプロセス。
Tomcatのクラスローダ
以下、Tomcat6の場合。
クラスローダ | 対象ロケーション | 説明 |
---|---|---|
WEBアプリケーション | WEB-INF/classes,WEB-INF/lib | 他のWEBアプリケーションからは使われないクラスローダ |
Shared | <tomcat>/shared/lib, <tomcat>/shared/lib/*.jar。<tomcat>/conf/catalina.propertiesのshared.loaderに設定する。設定がなければcommonローダと同じ。 | WEBアプリケーションが共用するクラスローダ |
Catalina | <tomcat>/conf/catalina.propertiesのserver.loaderに設定。設定がなければcommonローダと同じ。 | Tomatの実行に使用される。WEBアプリケーションから使えないクラスローダ |
common | <tomcat>/lib,<tomcat>/lib/*.jar <tomcat>/conf/catalina.propertiesのcommon.loaderに設定されている。 | TomcatとWEBアプリケーションの両方から使われるクラスローダ |
委譲の優先順位
- ブートストラップ・クラスローダ
- システム・クラスローダ
- Webアプリケーション自身のクラスローダ
- Commonクラスローダ
- Sharedクラスローダ
WEBアプリケーション
<Tomcat>/webapps下にディレクトリを作成すると、そのディレクトリ名のWEBアプリケーション(コンテキストパスがディレクトリ名)が追加される。
任意のディレクトリをWEBアプリケーションに追加するには、conf/server.xmlに以下を設定。
<Server > <Service> <Engine> <Host> <Context path="/naobe" docBase="c:/webapps/naobe" debug="0" reloadable="true" > </Context>
c:/webapps/naobe以下のディレクトリ構成は以下。
WEB-INF +-- web.xml +-- classes | +-- パッケージ、クラスファイル +-- lib
docBaseは、Tomcatインストールディレクトリからの相対ディレクトリも指定可能。
http://localhost:8080/naobeでWEBアプリケーションを参照できる。
http://localhost:8080/naobeでWEBアプリケーションを参照できる。