Web サーバーで通信断が発生しました。
「/var/log/httpd/error_log」を確認したところ、以下のメッセージが出力されていました。
[error] (70007)The timeout specified has expired: ajp_ilink_receive() can’t receive header |
原因と対策を調査します。
調査個所&方法
ログを調査します。
調査するログ
- /var/log/httpd/access_log
- /var/log/httpd/error_log
- catalina.out
調査するポート
ApacheとTomcatの連携なので「8009番ポート」を確認します。
[root@cent07 ~]# netstat -t | egrep “^tcp.*:8009” |
Tomcat は「8009番ポート」で AJP の通信を受け付けています。
AJP とは「Apache JServ Protocol」の略です。
ab(ApacheBench)コマンドを実行してみる
httpd をインストールすると ab コマンドもインストールされます。
[root@cent07 ~]# ab |
tcpdump でパケットキャプチャする
パケットの中身を見ることが出来ればほとんど原因を特定することができます。
tcpdumpのインストールと使い方 パケット解析をする
FWでコネクションを切断していないか確認する
FWでコネクションを切断していても Tomcat 側では「ESTABLISHED」だと勘違いするらしいです。(切断されたことが通知されないらしいです)
http://d.hatena.ne.jp/mercystage/20090105/1314536504
timeout が発生した原因
timeoutが発生した原因については以下の可能性があります。
リクエストを処理するのに時間が掛かりすぎている
リクエストがノード側で処理されるのに時間がかかっている可能性があります。
アプリケーションの処理を確認し、タイムアウト時間を延ばす場合は、ノードのタイムアウト値を追加します。
タイムアウト値は各ノードごとに設定することができます。
また、ノード上のバランサーの設定が適切でない可能性があります。元々どの値で、どのように設定を変更したのかを調べます。
Tomcatの「server.xml」の値を調べてみます。
<Connector executor=”tomcatThreadPool” |
【Apache】httpd.conf の変更
コンフィグファイルのここを修正 or 設定すれば確実に復旧できるというものはありません。
そのためいくつかの値を総合的に調整していきます。
Apacheの httpd.conf の
- TimeOut
- KeepAlive
- ProxyTimeout ← プロキシリクエストのタイムアウトを指定します。
の値を調べてみます。
TimeOut
クライアントとの間でデータのパケットをやりとりするときに待機する最長の時間を設定します。
Apache は、指定されている時間に達してもパケットを受け取れないと接続を切断します。
時間は秒単位でデフォルトは300秒です。
接続しているネットワークが遅く、頻繁に接続が中断するようなことがない限り、この設定を変える必要はありません。
接続が頻繁に中断するようなら、値を増やして、切断の回数を減らすようにします。
TimeOut 600 ← 単位は「秒」。600は10分(600秒)になります。 |
KeepAlive
Webブラウザとの間で持統的な接続を維持するかどうかを指定できます。
持続的な接続では、1つの要求が完了するたびに接続を閉じて次の要求に対して新しく接続を開く代わりに、複数の要求で同じ接統を繰り返し使うことができます。
持統的接続を使うと、サーパーのオーバーヘッドが減り、パフオーマンスが向上するので、この設定は「on」のままにしておきます。
KeepAliveを「ON」にすると復旧することもあります。
MaxKeepAliveRequests
一回の接続で処理できるリクエストの数を指定します。
もしタイムアウトやエラーが発生する場合は、なるべく大きい値に設定します。
値が大きければ大きいほど、1回の接続で処理できるリクエストの数も多くなります。
※ただし、同時に KeepAlive の値を「on」に設定しておく必要があります。
KeepAliveTimeout
1つのリクエストが完了してから、接続を中断せずに次の新しいリクエストを待つ時間(秒)です。
ProxyPass
ProxyPass を利用しプロキシサーパーを設定して、リモートサイトのコンテンツがあたかもローカルにあるように見せることができます。
この ProxyPass でリモートにある Web サーバーのドキュメントツリーを、あたかもプロキシサーパーのドキュメントツリーの下にあるように見せかけることができます。
この値に紐付いている「keepalive」の値を「on」に設定します。←「keepalive=on」
コンフィグを設定変更したらサービスの再起動を忘れずに
httpd.conf の値を変更したらサービスの再起動を実施します。
# systemctl restart httpd.service |
【Tomcat】server.xmlの変更
Tomcatの「server.xml」の値を調べてみます。
connectionTimeoutの値を調べて調節します。
<Connector executor=”tomcatThreadPool” |
「Tomcat」connectionTimeout について
http://a4dosanddos.hatenablog.com/entry/2013/07/18/233208
http://tomcat.apache.org/tomcat-7.0-doc/config/http.html
connectiontimeoutについて
The number of milliseconds this Connector will wait, after accepting a connection, for the request URI line to be presented. Use a value of -1 to indicate no (i.e. infinite) timeout. The default value is 60000 (i.e. 60 seconds) but note that the standard server.xml that ships with Tomcat sets this to 20000 (i.e. 20 seconds). Unless disableUploadTimeout is set to false
, this timeout will also be used when reading the request body (if any).
リクエストURI行が表示されるために、このコネクタが接続を受け入れた後に待機する時間をミリ秒数で設定します。 無限(つまり無限)のタイムアウトを示すには、-1の値を使用します。 デフォルト値は60000(60秒)ですが、Tomcatに同梱されている標準のserver.xmlは20000(つまり20秒)に設定されています。 disableUploadTimeoutがfalseに設定されていない限り、このタイムアウトは要求本体(存在する場合)を読み取るときにも使用されます。
まだ試していませんが、このコネクションタイムアウトの時間が経過すると FIN パケットを送信されるようです。
tcpdumpのインストールと使い方 パケット解析をする
その他対応方法
その他の対応方法です。
OSを再起動する
一度 OS を再起動してみます。
AJPを利用せずにhttpを使う
AJP のバグを疑い、AJP を利用するのではなく、tomcat の http server と連携します。
mod_proxyのバグ
https://bz.apache.org/bugzilla/show_bug.cgi?id=38227
参考サイト
http://blog.hiroaki.home.group.jp/2009/05/ajpreadheader-ajpilinkreceive-failed.html
コメント