Apacheのmod_statusの各状態はどういう意味か?
Apacheのmod_statusを使えば各プロセスの状態を知ることができます。CloudForecastやCacti等でそれを元に視覚化している人も多いと思います。
mod_statusで確認できる状態には以下の11種類があるのですが、
状態名 | 値 | mod_stautsでの記号 | 説明 |
---|---|---|---|
SERVER_DEAD | 0 | . | Open slot with no current process |
SERVER_STARTING | 1 | S | Server Starting up |
SERVER_READY | 2 | _ | Waiting for connection (or accept() lock) |
SERVER_BUSY_READ | 3 | R | Reading a client request |
SERVER_BUSY_WRITE | 4 | W | Processing a client request |
SERVER_BUSY_KEEPALIVE | 5 | K | Waiting for more requests via keepalive |
SERVER_BUSY_LOG | 6 | L | Logging the request |
SERVER_BUSY_DNS | 7 | D | Looking up a hostname |
SERVER_CLOSING | 8 | C | Closing the connection |
SERVER_GRACEFUL | 9 | G | server is gracefully finishing request |
SERVER_IDLE_KILL | 10 | I | Server is cleaning up idle children |
年に3回ぐらい「これって具体的にどういう状態なんですか?」と聞かれてテケトーに答えてたので、httpdが一生のうちどういう状態を変遷するのかと、いくつかの状態についてはソースも読みながら確認してみたのでそのメモです。
httpdの一生
Apache 2.2.27で、prefork MPMでのhttpdの一生はこんな感じでした。
- 起動
- DEAD -> READY
- READY -> READY
- リクエスト/レスポンス処理 (非 keepalive)
- READY -> BUSY_READ
- BUSY_READ -> BUSY_READ
- BUSY_READ -> BUSY_WRITE
- BUSY_WRITE -> BUSY_LOG
- BUSY_LOG -> CLOSING
- CLOSING -> READY
- リクエスト/レスポンス処理 (keepalive)
- READY -> BUSY_READ
- BUSY_READ -> BUSY_READ
- BUSY_READ -> BUSY_WRITE
- BUSY_WRITE -> BUSY_LOG
- BUSY_LOG -> BUSY_KEEPALIVE
- BUSY_KEEPALIVE -> CLOSING
- CLOSING -> READY
まずはDEADから始まり、もろもろ初期化を済ませると READY に遷移し、続いて生きてる限り回るループの中で(再度)READY に遷移し accept(2) してリクエストを待ちます。
リクエストが着弾してaccept(2)が抜けると、ap_read_requestによりHTTPリクエストを処理します。このap_read_requestの前にBUSY_READに遷移し、ap_read_requestが終わるとBUSY_WRITEに遷移します。
ここで留意すべきは、HTTPリクエスト処理を終えた時点でBUSY_WRITEに遷移するという点です。
低速な回線のクライアントへのレスポンスの送信の場合にBUSY_WRITE状態で滞留するのはもちろんですが、reverse proxy先のバックエンドサーバーの処理が遅い場合もBUSY_WRITEで滞留します。
つまりBUSY_WRITEだけでは回線起因でレスポンス送信に時間がかかっているのか、バックエンドの処理が詰まっているのか判別できません。
バックエンドの処理が詰まっているかどうかは、その処理時間をバックエンドサーバーのログやレスポンスヘッダに入れる(で、フロントのApacheのアクセスログで記録してクライアントへのレスポンスからは当該ヘッダを消す)ようにしておけばよいと思います。
さて、無事にレスポンスを返し終えると、BUSY_LOGに遷移しap_run_log_transactionでログの記憶を行います。ちなみに、異常系で終了する場合も同じくBUSY_LOGに遷移してログを書き出します。
あとはCLOSING→READYと遷移し最初に戻ります。HTTP keepaliveが有効の場合は、BUSY_KEEPALIVE→CLOSING→READYという遷移になります。
ちなみにですが、少なくとも今回確認した Apache 2.2.27, prefork MPM, Linuxでは、
- BUSY_DNS
- IDLE_KILL
は使われていないようでした。