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
Tomcat解読.xls
 Tomcat解読.xls
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アプリケーションを参照できる。
