そごうソフトウェア研究所

SOA、開発プロセス、ITアーキテクチャなどについて書いています。Twitterやってます@rsogo

JBoss ASのデプロイプロセスを眺めた

WebLogic Serverの会社にいたので、JBossは全然触ったことがなかったのですが、最近、使ってます。今日は、デプロイのプロセスを眺めていたので、メモしておきます。

デプロイ

デプロイはこのパスにwarファイルなどを置くことで簡単にできます。 {JBOSS_HOME}/standalone/deployments/

その時、置いたwarファイルに対して、isdeployingというファイルができる。

AppPot_1.1.4_3_jboss.war
AppPot_1.1.4_3_jboss.war.isdeploying

しばらくまってると、deployedファイルになり、デプロイ完了。ファイル名で分かるというのはシンプルで面白いやり方ですね。

AppPot_1.1.4_3_jboss.war
AppPot_1.1.4_3_jboss.war.deployed 

アンデプロイ

アンデプロイするときは、deployedファイルをundeployという名前に変えるだけ。 $ mv AppPot_1.1.4_2_jboss.war.deployed AppPot_1.1.4_2_jboss.war.undeploy

そうすると、undeployに加えて、undeployedファイルができて、実際にWebアプリのURLにアクセスしてみると404エラーが返ってくる

-rw-r--r--  1 ncdc        ncdc        13887481  6月  5 08:54 2014 AppPot_1.1.4_2_jboss.war
-rw-rw-r--  1 jboss       jboss             24  6月  5 08:54 2014 AppPot_1.1.4_2_jboss.war.undeploy
-rw-rw-r--  1 jboss       jboss             24  6月  5 10:08 2014 AppPot_1.1.4_2_jboss.war.undeployed

サーバサイドJavaのトラブル分析(APサーバースローダウン)

ここ1ヶ月くらいサーバーサイドのトラブル解決をよくやっていて、Javaのサーバーアプリのトラブルの分析のやり方を書いていきます。

先日発生したのはAPサーバーのスローダウンでした。ここでの原因は特殊なものだと思うので、その理由よりは分析のプロセスの方が大事かなと思っています。

チェックした内容

  • OSリソースの使用状況

sarを見ると該当の時間でuserのCPU使用率が90%を超えていました。 ioなどに問題はないので、アプリ層に問題がありそうです。

  • gcログ

FullGCが頻発していれば、CPUを使い切っていてスローダウンが発生するが、GCは大したことなかった。

  • topコマンドでプロセスごとのCPU使用量確認

APサーバー(WebLogic Server)のJavaプロセスが使っていることを確認。 でもどのサーバーアプリかは分からない。

  • アプリログ

特にエラーはない。ただし、処理開始・終了のログから処理速度が遅いことは確認

該当の時間にBroken pipeのエラーログが大量にでていた。

Caused By: javax.xml.stream.XMLStreamException: java.net.SocketException: Broken pipe

ただし、Broken pipeが発生するのはネットワークが正常のステップで切断されていない場合(例えば、通信経路にあるFirewallがタイムアウトで接続を切っていたり、クライアントアプリがタイムアウトで接続を閉じた場合など)なので本当の理由は別にあるはずです。

エラーの原因

WebLogic Serverのログをさらにさかのぼって確認すると次のようなログがでていました。

Error Log in case of JDBC Trace Log (MS SQL Server ...

「[STUCK] ExecuteThread: '11' for queue: 'weblogic.kernel.Default (self-tuning)'は"600"秒間ビジー状態になっています。これは、構成された時間(StuckThreadMaxTime)"600"秒を超えています。」というのはWebLogic Serverがあるスレッドが設定された時間(デフォルト600秒)の間、処理がスタックしていればスタック状態と見なすという挙動です。 スタック状態と見なした後は設定に依ってWebLogic Serverを再起動したりをすることができます。

スタックトレースを見ると「com.microsoft.sqlserver.jdbc.SQLServerResultSet」が「java.util.logging.Logger」を使っているところばかりです。 実はWebLogic Server、SQL Server間でエラーが以前発生していたので分析のためのJDBC Traceログを仕掛けていたのですが、その設定が中途半端に残っていました。実際のログは出力されていないが、出力するための設定ファイルを毎回見に行くという状態になっていました。

そのため、io負荷が異常に高ければ、ログ出力を疑ったと思うのですが、実際はioは問題になっておらず、CPUを使い切っているという症状となっていました。

重要なこと

分析に必要な情報がでていること

問題の再現手順が分からないことや、本番環境でしか発生しないなど発生させるのが難しい場合があります。 予め問題の分析に必要な情報が収集されていることが重要です。 設定面で言えば、GCログが出力されるようにセットしていることや、OSやミドルウェアのリソース使用状況が記録されている必要があります。

アプリケーションの設計では、適切なログが出力されるようになっていることも重要です。 エラーのスタックトレースが出力されていて、エラーの箇所が特定できること。 スローダウンが発生している際に、全ての処理が遅いのか、特定のAPIのみかなどが分かること。(そもそもサーバー側の処理時間が分かること)

根気よく効率良く情報を読むこと

まず問題を報告してくれた人に正確な情報を聞くこと。 問題が発生した日時、問題が発生する条件・手順。 後でログを詳しく見る際に、問題が発生した日時が分からないと作業量が膨大です。

自分はまず、関連するログをgrepで「FATAL」、「ERROR」、「Exception」などでざっと検索をかけます。 (プロジェクト終盤のテストのフェーズであれば、エラーの報告の有無に関わらず、毎日ログを検索して想定外のエラーが発生していないか確認します。本来、監視の対象にならないようなログがログレベルを間違って出力されているのもここで確認できます)

それで該当の時間帯にエラーのログが出力されていれば、そこから始めます。 ポイントとして、その後のログを見ていくのでは無く、時系列をさかのぼってログを見ていきます。 もっと前の時間に同じ、または別のエラーが発生していないかを確認します。 これはユーザーに見えているエラーの原因となるエラーがもっと前に発生していることがあるからです。

この例の場合、ユーザーから報告のあった時間にはBroken pipeのエラーがありますが、 もっと前のログを見ると、java.util.Logginのエラーがでています。

今回は問題になっていませんでしたが、作っているアプリの中に問題があった場合はGCログや、スレッドダンプの中身を詳細に見ていく必要があるので、適切なViewerやWebLogic Serverの場合、JRockit Mission Controlなどのツールを使えるようにしておきたいところです。

欲しいClassがどのjarファイルに入っているか探す

Enterprise Javaをやっていると必ずはまるJar地獄。 自分が使っているライブラリを、アプリケーションサーバーや、3rdパーティーのライブラリが使っていて、ClassNotFoundや、そんなメソッドないとか、そのメソッドはPublicじゃないとか訳分かんなくなるやつ。

そんな時はエラーになっているClassがクラスパスのどこにあるか探して、複数ある場合はどっちを使うべきかを設定してやればいいし、無ければクラスパスに追加してやればOK。

Classがどのjarに含まれているか調べないといけないけど、Googleで調べても有名で皆がはまったことのあるやつしか出てこない。ですので、作りました。5年くらい前に。最近もこれに助けられた。

WebLogic 12c セットアップ手順メモ

準備

yum install ld-linux.so.2

プロダクトのインストール(コンソールモード)

http://docs.oracle.com/cd/E28613_01/doc.1211/b65933/console.htm

 chmod +x wls1211_linux32.bin 
 wls1211_linux32.bin -mode=console

ドメインの作成(コンソールモード)

http://docs.oracle.com/cd/E28613_01/web.1211/b65940/console_mode.htm

これをやってないとドメインの作成が終わらなかった。失敗したらdomains以下のファイルを削除して、再作成でOK。

export CONFIG_JVM_ARGS=-Djava.security.egd=file:/dev/./urandom

コンソールモードで起動

config.sh -mode=console

ドメイン作成後の準備

/Oracle/Middleware/wlserver_12.1/common/bin/config.sh

boot.propertiesの作成

これを作成しないと、起動時にユーザーとパスワードを聞かれる

{WLS}/user_projects/domains/mydomain/servers/myserver/security/boot.properties

いつも間違ってdomainの直ぐ下のsecurityフォルダにboot.propertiesファイルを置いて、起動しねぇ!となる。

12.1.1は必須のパッチがありそう。 http://www.davidghedini.com/pg/entry/oracle_web_logic "Before investing any time in this, despite a fresh download you will need,.... a patch: (p13606167_12110_Generic.zip). "

あと、JDKのバージョンが6系だと設定の保存で失敗することがあった。7系にあげることで解消。

iTextについてちょっと調べて見た

Javaのサーバーサイドで簡単な帳票を作成したいのだけれど、専用の製品を導入する程でもない。 ということで、手軽にPDFを作成できるライブラリを調査しました。

ネット上に情報が多そうなのはiText(http://itextpdf.com/)でした。

ライセンスについてのQiitaの記事が分かりやすかったです。 http://qiita.com/takudo/items/e2b37b659c9143db730c

CSSで改行の指定(page-break)もあるようなので、更にライトにやるなら、こっちかなぁ。 http://www.htmq.com/style/page-break-before.shtml

SQL DeveloperからSQL Serverにつなぐ

SQL DeveloperはOracleが出しているDatabaseを操作するためのGUIのクライアントツールです。Oracle SQL Developerから入手できます。

接続先のデータベースがOracle DBの場合はそのまま使えるけど、それ以外で最初は新規の接続を選択しても、Oracleというタブしかないので準備が必要です。 MicrosoftSQL Serverに接続する手順を書きます。

ドライバーの設定

Microsoftのドライバを使うのでは無くて、オープンソースjTDSを使うみたいです。

動作確認はjtds-1.3.1-dist.zipを使っています。

Zipを解凍した後、SQL DeveloperのPreferenceからjtds-1.3.1.jarのパスを設定します。

f:id:begirama:20140405074850p:plain

接続設定

ドライバを入れる前までは無かったSQL Serverタブが表示されます。

f:id:begirama:20140405072632p:plain

上手く接続できれば、GUIでがんがん操作できるので便利です。

f:id:begirama:20140405074445p:plain

MySQL

MySQLの場合も同様です。MySQLJDBCトライバーをSQL Developerから参照することで、MySQLのタブが表示されます。

MySQLのドライバーはこーゆーやつ。 mysql-connector-java-5.1.6.jar

参照資料

http://www.oracle.com/technetwork/jp/developer-tools/sql-developer/thirdparty-095608.html その他のデータベースに接続するために必要なドライバに付いても書かれています。

WebLogic Server 12c上でHibernateを使う

WebLogicHibernateを使った時にはまったことをメモしておきます。

利用している環境はWebLogic Server 12c。

発生したエラーはClassNotFound。 org.hibernate.QueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken [from 自分で作ったクラス]

解決方法はデプロイしようとしているのがwarファイルだったので、weblogic.xmlを開いてWEB-INF/lib以下を優先するように設定。

1.WEB-INF/lib以下全部を優先する場合

<weblogic-web-app>
(略)
  <container-descriptor>
    <prefer-web-inf-classes>true</prefer-web-inf-classes>
  </container-descriptor>
(略)
</weblogic-web-app>

2.特定のjarのみWEB-INF/lib以下を優先する場合 今回使っているのはantlr-2.7.6.jarでした。

<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app>
(略)
    <container-descriptor>
        <prefer-web-inf-classes>false</prefer-web-inf-classes>
        <prefer-application-packages>
            <package-name>antlr.*</package-name>
        </prefer-application-packages>
    </container-descriptor>
(略)
</weblogic-web-app>

なるべくJava EEの標準ライブラリでやった方がこの手の問題は絶対楽だな。

参考サイト

https://blogs.oracle.com/WebLogicServer/entry/resolving_conflicts_with_classloaders http://stackoverflow.com/questions/2702266/classnotfoundexception-hqltoken-when-running-in-weblogic http://docs.oracle.com/cd/E24329_01/web.1211/e24368/classloading.htm#i1098467 Log4jantlrWebLogicのマニュアルのサンプルに載るくらい皆はまってるってことだな。