Webサーバに過度のアクセスが。どうしよう?の件
ってな時の話は誰しも困るもの。
俺は今困ってないけど、そうなっちゃった時の対策を検討してます。はい。
負荷の原因が特定少数による場合なら検出してはじけばよろしい↓。
http://d.hatena.ne.jp/stanaka/20070204
来た負荷の種類に関係なく、負荷をヨソに逃がしてよけるなら↓。
- Milano::Monolog - mod_rewriteでサーバーの負荷が高いときだけリダイレクトする
http://rebecca.ac/milano/mt/archives/001540.html
(↑RewriteMapで毎度perl叩くのもそれなりに負荷?)
- Clouder::Blogger - mod_loadaverage_actionリリース
http://clouder.jp/yoshiki/mt/archives/000722.html
ロードアベレージ、かぁ。と思う俺。単一コンテンツ、多段でない構成ならアリなのかな?
このあたりの考察はJcode.pmよりはテレビでお馴染みの弾さんの考察が詳しい。
http://blog.livedoor.jp/dankogai/archives/50670205.html
さてさて、ケチばっかりつけてる俺は何を考えているかというと、ウチの事情ばっかりを考えているわけだけど、まずはウチの事情から。
- どんなコンテンツがいつどんな形で置かれるかわからない、というレベルで自由度が高い(要するにコンテンツ書く人は何でもアリ)
- 箱モノのロードバランサは振分先が応答しない時に別な振分先に飛ばす機能を持っているが、これは使いたくない。(理由は後述)
- コンテンツを返すWebサーバの前にリバースプロキシがいる。
- 負荷を計る指標としてロードアベレージってどうなの
- リバースプロキシの裏にいるWebサーバどもが貧弱(これが根本原因じゃん…、って思うけど簡単には入れ替えられない)
- サービスできない時にダンマリじゃなくて、「御免」とクライアントに返したい
ってことで、リバースプロキシをいじることにしたよ。
リバースプロキシはApacheなんだけど、Apacheは2.0.31以降からProxyTimeoutというディレクティブを持っている。Apacheのmod_proxy_httpはProxyTimeout秒たったリクエストを、502 HTTP_BAD GATEWAY でエラーにしちゃうんだね。っていうかHTTP_BAD_GATEWAYってそういうものみたいだね。
だから、ウチの要件であるところの「御免を返す」というのは、ErrorDocument 502 /sorry.html とすれば良い。
ProxyTimeout 5 ErrorDocument 502 /sorry.html
たったのこんだけで、裏方のWebサーバが忙しい時に、ちゃんと「御免」!ということが出来るようになる。わーい。
あとはApache1.3で動いてるあいつを2.2系にでも入れ替えちゃうだけだね。workerにしちゃおっかなー。rewriteぐらいしかやらせてないからこの変更は楽だ。
以下、いいわけ?
自分で作ったほうが楽しいかもしれないけど、今後もちゃんとソースコードをメンテナンスしていくだけのリソース確保は難しいし、時間もないし、ありもので済ませる選択肢はハカーの皆様からすればヘタレかもしれないけど、現実はこんなとこですよ。
不特定多数、多量のリクエストを受けた時にボトルネックになるのはだいたいリバースプロキシじゃなくて、その裏にあるWebサーバ群なので、この方法は安い早い旨いのはず。っていうかこんな設定は普通?みんなとっくにやってる?
■後述って書いちゃった話
箱物ロードバランサが持っている「バックアップサーバ機能」みたいな奴って、振分先が全部死なないと変えてくんないんですよ。だから、瀕死でいっぺぇいっぺぇだけど、踏ん張ってる間は「つながらねー」状態が続くのです。それよりは、わりきって「御免」としたいのね。
あと、ロードアベレージを指標にしたくないのは、ロードアベレージが高い=サービス不能状態じゃないから。たとえば閾値を5にしたとして、まだ平気なのに「御免」!とか、もう無理なのに出ないとか、そういう最適値を見つけて、気にするのは嫌なんです。特にウチみたいに日々おかしなコンテンツが産まれては消えていく環境だとね。ロードアベレージよりは、Proxy先のWebサーバが応答すんのに時間かかってる、っていうほうがより負荷状況を表してると思うよ。