AWS で ELB 配下に EC2 Webサーバ(apache)をぶら下げている構成で、apache の access_log に応答コード「408」が定期的(約50秒)に記録される状態でした。
調査結果から分かった原因と対策内容をメモしておきます。
1.原因
応答コード「408」は、HTTPリクエストのタイムアウト(リクエストの待ち時間に反応しなかった)際の応答コードです。
以下、access_log の408記録の例です。1行だけですが。
(ELB) - - [27/Oct/2014:01:16:11 +0900] "-" 408 - "-" "-"
調べてみると、以下の事が分かりました。
- ELBが EC2 Webサーバに対して、しばらくコネクションを開いており、コネクションの再利用を行っている(ELBがEC2へのTCPコネクションを管理している)。このコネクションはデフォルトでIdle Timeout が60秒に設定されている。
- EC2 のapache にて、デフォルトでロードされている「mod_reqtimeout」モジュールにて、RequestReadTimeout ディレクティブのデフォルト値「header=20-40」が効いており、EC2 のapache がELBからの該当TCPコネクションを切断している。
- その為、ELBからの接続が残ってしまい、ELBからEC2への接続時に408(タイムアウト)となってしまう。
2.対策
対策としては、以下の2点が有効だと考えられます。
- mod_reqtimeout のRequestReadTimeout で、header値を60秒よりも長くする。(ELBのIdle Timeout値 60秒よりも長くする)
- ELBのIdle Timeout値を デフォルト値である 60秒よりも短くする。(RequestReadTimeoutの header=20-40 よりも短くする)
mod_reqtimeout は、DDos対策として有効な設定っぽいので、ELBの Idle Timeout値を60秒から30秒に設定変更する方の対策を実施する事にしました。
ELBの Idle Timeout の設定変更後は、応答コード「408」のログは記録されなくなりました。