俺の報告

RoomClipを運営するエンジニアの日報(多分)です。

日報 #11 - apacheの「例のやつ」

うちにはインコがいるのですが、

俺の布団に入るとひっくり返って暴れます。臭いんだろうね。

 

さて今日の報告。

 

1. ELBレイテンシーに異常値発生

2. もろもろ

 

今日はELBレイテンシーが突発的に上昇するという事件に遭遇しました。

ロードバランサーからインスタンスまでの通信時間は命なので、僕はこれを最も重要な指標として捉えております。

 

さて、この数値の上昇には幾つか原因が考えられるわけですが、

とにかく最初に確認しなければならないのはELBのヘルスチェックに対してサーバがちゃんと応答したのかどうか?ということ。

要はELBにおいて「in serviceだけどめっさ遅くなった」のかそれとも「見えなくなってout of serviceになった」のかどっちだということ。あとは4xx or 5xxの数。

前者であれば極論そんなに問題はなさそうだが、後者であれば一大事です。

 

どちらにせよ、対応方法は色々です。

誰でも今すぐできるのは、ログのチェックです。

apacheの生ログをとりあえず眺める、というのはどういうアプリをいれていてもとても勉強になりますね。(もちろん、他に色々やりかたありますが。。。)

awkとかsedとかを使って出来るだけ早く何が起きたっぽいのかを確認します。

よくあるのは「行儀の悪いロボットのアクセス」。

エラーがおきたっぽい行数で、なんかこんな感じ

cat access.log | sed -n '1000, 5000n' | grep hoge.com -c

みたいな感じで集中的なアクセスがあったのかを確認しやす。

過負荷がかかるとmod-evasiveみたいなんが発動するが、それはさておき、とにかく確認。

過去僕がマークしたサイトは3つほどあります。

 

続いて、http://www.hping.org/visitors/doc.htmlみたいなのでaccess.logを解析。

何が起きたのかを俯瞰します。

この時までに大体原因っぽいのは掴めていたいですが、まぁそんなことないですね。

 

これで分からなければ徹底調査になります。

DB周り、CPU周り、syslogなどとにかく調査対象となります。

 

まぁこれは色々やり方があると思いますが、

重要なのは対応策です。

今回は(そんなに大事でもなかったので)少しApacheのコンフィグをいじってみることにしました。

Apacheのコンフィグは色々ありますが、ここではforkの時に特に注意する「いつものやつ」について再考してみます。

 

僕の思考順序はこんな感じ。

「1ページ平均何リクエスト?」→chromeのデバッガとかで見てみるのが手軽で楽。Nとします。

「リクエスト/秒はどの程度?」→時刻によってことなりますが、

一番ナマナマしいやり方として、僕はよくnetstatを監視します。

こんな感じで。

watch -d -n 1 "sudo netstat -plan|grep :80| grep ESTABLISHED | awk {'print $5'}|cut -d: -f 1|sort|uniq -c|sort -nk 1"

秒間ごとに眺めます。本当は一日のログをとるけど。これをRとします。

 

このNとRで大体のkeepaliveの値を決めます。

各レスポンスタイムも適当に。

 

そして、問題は、、、

startclient

minspare

maxspare

maxclient

MaxRequestsPerChild 

ですね。

 

端的に僕の考え方としては2つあります。

「CPUもメモリもいつだって限界まで使うべし」

「必要な時に必要な分だけ使うべし」

まぁどっちでもいんだけど。。。

まずhttp://d.hatena.ne.jp/R-H/20110317これを参考にしてメモリから算出されるmaxClientをボンヤリと定めます。

子プロセスのメモリはcowのためか親プロセスとシェアしているので、そこまで注意するのが必要。

 

ほいで、 

maxclientが定まったら、startclientもminspareもmaxspareもぜーんぶその値にしちゃうってのも1つの考え方。

このやり方だと、apacheを起動する、というプロセスを踏まなくていいので、急激アクセスに強い。

でも例えばEC2を色々な用途で使ってたりすることって、ほら、あるじゃなーい?

(あっちゃ駄目だけど)

まぁデプロイツールとかテストとか巡回させたり、EC2をいつもメモリパンパンにさせとくのは微妙。

だからまぁ大体は後者の「必要な時に必要な分だけ使うべし」的な考え方を採用します。

 

maxclientはそのままでいいんだけど、

startclientとminspare、maxspareは?

startclientは「いつも大体こんなもん」という値にします。(え

すごい簡単にいえば、平常時でps -ef | grep apache -cみたいなことして出てくる数値くらい。

(もうちょっとまじめにやるけど)

僕は大体maxspareについては

maxclient-(startclient+minspare)

こういう式にしてます。

凄い単純にmaxclient数プロセスが立ち上がる=緊急事態なので、

もしmaxclient数で捌き切った後、即効で待機プロセスをキルするなんてとてももったいない+危険だと考えます。

なので、アクティブプロセス稼働しているのがstartclient+minspare個になったとき、

ようやく「緊急事態は終了した」と判断して、待機プロセスをキルすればよいと。

だから上記の式にしています。

 

あってっかどうか、意見が欲しいので、何か少しでも気になった方いらっしゃったら、

ぶっこみください・・・