snbhsmt_log

ネットワークとコンピュータ、その他いろいろ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Tomcat の DB 接続プールを JMX で監視

Tomcat の標準のデータベース接続プールは Commons DBCP の BasicDataSource 。 この BasicDataSource の numIdle がアイドル状態の接続数で numActive が アクティブ状態の接続数を表す。 この値は JMX 経由で取得できる。

環境 : Java SE 5 Update 12 / Tomcat 5.5.23

jconsole を利用。

$ export CATALINA_OPTS="-Dcom.sun.management.jmxremote.port=8180 \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.authenticate=false"
$
$ catalina.sh start
$
$ jconsole &
jconsole で Tomcat 5.5 の DB 接続プールを表示

或いは manager アプリの jmxproxy サーブレットを利用。
qry リクエスト・パラメータに MBean 名を指定。
http://localhost:8080/manager/jmxproxy?qry=Catalina:type=DataSource,*

OK - Number of results: 1

Name: Catalina:type=DataSource,path=/db7,host=localhost,class=javax.sql.DataSource,name="jdbc/FooDB"
modelerType: org.apache.tomcat.dbcp.dbcp.BasicDataSource
password: **********
defaultAutoCommit: false
maxIdle: 30
minEvictableIdleTimeMillis: 1800000
driverClassName: org.postgresql.Driver
username: postgres
url: jdbc:postgresql://127.0.0.1:5432/postgres
testOnBorrow: true
maxWait: 10000
testWhileIdle: false
numIdle: 0
maxActive: 100
numActive: 0
maxOpenPreparedStatements: -1
timeBetweenEvictionRunsMillis: -1
poolPreparedStatements: false
initialSize: 1
accessToUnderlyingConnectionAllowed: false
testOnReturn: false
logAbandoned: false
numTestsPerEvictionRun: 3
defaultTransactionIsolation: -1
removeAbandonedTimeout: 300
removeAbandoned: false
defaultReadOnly: false
minIdle: 0
スポンサーサイト

Tomcat 6 の複数インスタンス用クラスパス

Windows XP SP2 と CentOS 5.1 なマシンに、 Tomcat 6.0.16 と、ついでに Java SE 6 Update 4 もインストールしておいた。

Tomcat のスクリプトをざっと読む。 java.endorsed.dirs が $CATALINA_HOME/endorsed/ になっている。 だけど初期状態ではこのディレクトリは存在しない。

Tomcat 6 になってクラスローダが整理され、 $CATALINA_HOME/common/, $CATALINA_HOME/server/, $CATALINA_BASE/shared/ が $CATALINA_HOME/lib/ にまとめられている。 $CATALINA_BASE を指定して複数インスタンス環境で利用しているので、 shared が無くなってしまうのは困る。 なので、各インスタンス用にクラスパスを以下の様に拡張してしまう。

  1. $CATALINA_BASE/ に lib ディレクトリを作成 (lib という名前でなくても良い) 。
  2. $CATALINA_BASE/conf/catalina.properties の common.loader システム・プロパティを 以下の様に書き換える。
common.loader=${catalina.home}/lib,${catalina.home}/lib/*.jar,${catalina.base}/lib/*.jar

これで、$CATALINA_BASE/lib ディレクトリ中の全ての jar ファイルが、 common クラスローダのクラスパスに追加される。

Tomcat の Log4j 設定ファイルはシステム・プロパティで設定

Tomcat 5.5 に Commons Logging + Log4j を 利用するウェブアプリを配備すると、ワーニング・メッセージが出力されて そのコンテキストのログは全てコンソールに出力されてしまう。 Log4j 設定ファイルを log4j.configuration システム・プロパティに 設定すると解決した。

出力されるメッセージは以下。

log4j:WARN No appenders could be found for logger (org.apache.commons.digester.Digester.sax).
log4j:WARN Please initialize the log4j system properly.
Tomcat 5.5 本体のログ出力に JDK14Logging、Log4j のどちらを用いる 設定であろうと、WEB-INF/lib に commons-logging.jar と log4j.jar が 存在し、ウェブアプリのコード中に Log4j の初期化処理を記述せず Logger.getLogger() の様に単に Logger を取得して利用している場合に この現象が発生するようだ。

よく解らないが、Webapp クラスローダより優先される階層で Log4j の初期化がされているので、Webapp クラスローダのクラスパスに置いている Log4j 設定ファイルを見つけられない様な感じだ。

という事は、Log4j がどのクラスローダ階層で初期化されようと見つけられる場所に Log4j 設定ファイルを置けば良いので、 log4j.configuration システム・プロパティで指定する。

JAVA_OPTS=-Dlog4j.configuration=file:///path/to/log4j.properties
この方法で、ワーニングが出力される事も、デフォルトの出力先であるコンソールに ログ出力されてしまう事も無くなった。

  • Apache Tomcat 5.5.23
  • Log4j 1.2.14

Tomcat 5.5 は logging.properties を必ず読む

Tomcat 5.5 のログ出力に Log4j を利用する様にしても logging.properties で設定したログファイルは作成される。 だから、Log4j を利用する場合でも、 Logging API 関連の設定をしておく。

org.apache.commons.logging.impl.LogFactoryImpl#getLogClassName() によると commons-logging.jar と log4j.jar があれば Logging API の LogManager はインスタンス化されず logging.properties は読まれない筈なのだが、 おそらく階層構造のクラスローダの何処かで Log4j のクラスを見つけられない状況が発生しているのだろう。

という事で、Tomcat 5.5 のログ出力に Log4j を使っていて、 しかも無駄なファイルを作成したく無い場合は logging.properties から FileHandler の定義を削除する。 或いは catalina.sh は、$CATALINA_HOME/bin/tomcat-juli.jar が存在すると ClassLoaderLogManager を使用する為のシステム・プロパティを 環境変数 JAVA_OPTS に指定するので、 tomcat-juli.jar をリネームするのも有効だ。

  • Tomcat 5.5.23
  • Commons Logging 1.0.4
  • Log4j 1.2.14

Tomcat 5.5 は JDK 1.4 で使用

Tomcat 5.5 を JDK 1.4 で動かす場合、アーカイブ中の RUNNING.txt にあるように、 別途 apache-tomcat-5.5.*-compat.* ファイルをダウンロードしてインストールする。 このアーカイブには以下の 3 つのファイルが含まれるので、これを Tomcat のインストール・ディレクトリを基準とした同じパスにコピーするだけ。

  • bin/jmx.jar
  • common/endorsed/xercesImpl.jar
  • common/endorsed/xml-apis.jar

そういえば Tomcat 5.5.20 + JDK 1.4.2_13 で起動した時、 以下のメッセージが catalina.out に出力されていたが、 すぐ JDK 1.5 に移行するつもりなので放っておく。

Created MBeanServer with ID: 1f6f0bf:10e919613c5:-8000:baxter:1

Tomcat 5.5 で Log4j の XML 形式設定ファイルを利用

Tomcat 5.5 でログ出力に Log4j 1.2.x を利用していて、 設定を XML 形式の log4j.xml ファイルで行うと、設定内容によっては エラーが発生する。 その理由と対応を考えた。

log4j:WARN Continuable parsing error 133 and column 80
log4j:WARN Attribute value "org.apache.catalina.core.ContainerBase.[Catalina].[localhost]" of type ID must be a name.

Tomcat 5.5 から Host や Context に対応するロガー名として以下の様に ブラケットで囲んだ名前を利用出来る様になった。

<logger name="org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager]">
        :
</logger>
しかし Log4j 1.2.x の log4j.dtd によると logger 要素の name 属性の 属性タイプは ID であり、そこに文字 '[', ']' や '/' は記述できない。 よって上記の様なロガー名を指定すると XML 検証エラーとなる。
<!ELEMENT logger (level?,appender-ref*)>
<!ATTLIST logger
  name          ID      #REQUIRED
  additivity    (true|false) "true"  
>
よって、この様なロガー名を指定したい場合は log4j.properties ファイルで設定しなければならない。

しかし、どうしても log4j.xml で設定したい場合は、 log4j.dtd を書き換えてしまうという方法がある。 log4j.dtd は log4j*.jar の中の org/apache/log4j/xml ディレクトリに 存在するので、これを以下の様に属性タイプ CDATA に書き換えてしまう。

<!ELEMENT logger (level?,appender-ref*)>
<!ATTLIST logger
  name          CDATA   #REQUIRED
  additivity    (true|false) "true"  
>
十分検証した訳では無いけれど、これでエラーは出なくなる。

ちなみに Log4j 1.3.x では DTD を用いない様なので、 このエラーは元々発生しないらしい。

Tomcat 5.5 の ClassLoaderLogManager

Tomcat 5.5 が標準で利用するログマネージャ org.apache.juli.ClassLoaderLogManager クラスは、 Java 標準の Logging API のログマネージャ java.util.logging.LogManager から幾つかの点が拡張されている。

まず、同じクラス名のハンドラを、名前を付けて複数定義できる様になっている。 数字で始まるハンドラは、ピリオドで区切られた 2 番目以降のトークンを ハンドラの FQCN として解釈する。 よって最初のトークンを変える事によって 同じハンドラのインスタンスを複数定義できる。

Tomcat 5.5 に標準で含まれる logging.properties には 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler の様に org.apache.juli.FileHanlder ハンドラが複数定義されていて、 複数のファイルにログ出力する様になっている。

次に、クラス・ローダ毎にログを管理する様になっている。 よって、ハンドラやロガー・ツリーがクラス・ローダ毎に存在する。 初期化も各クラス・ローダ毎に java.util.logging.LogManager と ほぼ同じ様に行われる。 なので shared/classes に logging.properties を置けば ウェブアプリ共通のログを制御できるし、 foo/WEB-INF/classes に置けば foo ウェブアプリのログのみを制御できる。

クラス・ローダ毎に logging.properties を置く場合、 以下の様にルート・ロガーのハンドラを定義しないでおく。 なぜかは解らないが、そうしないとログが 2 行づつ出力されてしまう様だ。

handlers = 1foo.org.apache.juli.FileHandler

#.handlers = 1foo.org.apache.juli.FileHandler

1foo.org.apache.juli.FileHandler.level = FINE
1foo.org.apache.juli.FileHandler.directory = ${catalina_base}/logs
1foo.org.apache.juli.FileHandler.prefix = foo.

jp.example.webapp.foo.level = FINE

Tomcat のセッション ID の長さ

Tomcat 5.5.x のセッション・マネージャでは sessionIdLength と いう属性でセッション ID の長さを変えられるのですが、5.0.28 のソースを見ていたら 同属性の setter が有ることに気がついた。 どうやら以下の様に 5.0.x でもセッション ID の値は可変な様だ。

Context 要素内に以下を記述して Tomcat を起動。

<Manager sessionIdLength="24" />

リクエストの結果、JSESSIONID クッキーの値が 24 bytes (16 進 48 桁) に。

HTTP/1.1 200 OK
Set-Cookie: JSESSIONID=27A5D3DEFE578524D81062D33FCD0816854C05E1E73595E4; Path=/
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 282
Date: Sat, 22 Apr 2006 06:30:43 GMT
Server: Apache-Coyote/1.1
Connection: close

Top|Next »

HOME

Author:snbhsmt
Google Profiles

http://www.ksky.ne.jp/~snbhsmt/

全ての記事を表示する

この人とブロともになる

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。