このブログと併設している「ぼくんちのTV別館」は、さくらのVPS3台体制で運営しています。
2016年5月に アクセス数が1日80万PVに達し、サーバーのパフォーマンスが著しく悪くなり、ほぼフリーズしたような状態になってしまいました。

まえおき

  • 本当は 早急に VPSを5~6台体制にするか、専用サーバもしくはクラウドの利用を開始すべき。
  • でも、限界ギリギリのサーバーをチューニングできる機会は滅多にないので、サーバー増設前にできる所までチューニングしてみます。
  • 久々のサーバー設定。大変だけど楽しいヾ(*´Д`*)ノ
    (でも本当は今こんなコトしてる場合じゃない orz )

VPS 3台の内訳

VPS A ・・・・・ 本体。MTOS5 + PHP化した静的HTML
VPS B ・・・・・ 画像サーバー (javascriptやcssも含む)
VPS C ・・・・・ アクセス解析 + 逆アクセス解析ツール + 1MB超えたファイルなど

サーバーの仕様は3台とも同じ。
 ・メモリ1GB HDD20GB の初期980円(後から増強)コース
 ・OS: Cent OS 5.11 (64bit)
 ・httpサーバー: Apache2系
※画像サーバだけでも Nginx にしよう・・・・と思いつつも全く手が付いていない状態。

 

以下、行った対処とチューニング。
※メモの序盤は時系列の記録です。
※後半で今回行った各種チューニングの内容をメモしています。

1.はじまり

  • 2016/5/20 午前8時半頃から問題発生。
  • 午前10時半頃、サーバーが激重になっているのに気が付く。
    アクセス数が尋常じゃない事もすぐに気が付いた。
    • 9時台に 12万PV/hourを記録していたらしい。
  • 後から分かったこと
    • 5月20日、実際には8時半ころからエラーが出ていた。
    • 5月23日もエラーが出た。
    • 両方の共通点:
      HTMLサーバーに 5万PV/hour
      画像サーバーに 45万アクセス/hour
      どうやらこの辺が限界らしい。
    • まず画像サーバー側で障害が出る。

2.まずブラウザからサイト表示して確認

  • かなりレスポンスが悪いものの、HTMLサーバーとアクセス解析サーバーは ギリギリ作動しているように見える。この2つにエラーログは発生していない。
  • 画像サーバーは良くても応答に5~30秒かかる。悪いと全く応答しなくなる。

画像サーバーの状態の把握からはじめる事にした。

3.sshでログインできない

  • Tera Term や WinSCP でSSHログインができない。
    • 画像サーバー、HTMLサーバー、この二つがログインできない状態。
  • ここでの対処方法1
    さくらの管理画面のコンソールからログインを試みれば良かった。
    • コンソールからログインを試みた場合、(たとえログイン出来なくても) ログインできない理由が表示される。
    • 表示されたメッセージ
      ip_conntrack: table full, dropping packet.
      printk: 1243 messages suppressed.
    • 原因は iptables のパケット情報が一杯になり溢れているからだった。
  • ここでの対処方法2
    さくらの管理画面で強制リブートすれば良かった。
    • リブートすれば、詰まったパケットが全部破棄されとりあえずsshログイン出来るようになった筈。
    • サーバーが半分フリーズしたような状態で強制リブートするのが怖かった。
    • ただしリブート後にログイン出来ても、その後の対処方法が分からなければ、15~30分ほどで再びサーバーはフリーズしたと思う。
      原因が分からないままコレを繰り返すと余計に慌てていたと思うので、結果的にはこの時点で再起動しなくてよかったと思う。

4.sshログイン後

  • 実は再起動する前、10~15回くらいのチャレンジでsshログインできた。
  • TOPコマンドしてみる
    • CPU使用率は10%を切っている。ロードアベレージは 0.6くらい。メモリはほぼ使い切っている。SWAP は多少利用しているが、リアルタイムで増減はしていない。
    • メモリ使用量を減らせば何とかなるんじゃないか?と勘違いしてしまった。
  • ここで実際に行った対処
    ※あまり効果はなかった
    • MaxClients を減らす、KeepAliveの時間を短くする、等の対処を行う。効果は無かった。
    • アクセス過多時にメモリを大量に食う逆アクセス解析ツールを止めた。
    • アクセス頻度の高いファイル (*.css、*.js、ヘッダー画像) をHTMLサーバー側に移した。
      • とりあえずレイアウトの乱れは収まった。
      • 画像サーバー側のレスポンスは少ししか回復しなかった。
      • 再びアクセスが増加し、5万PV/hourを超えたあたりで今度は画像サーバー、HTMLサーバーの両方がレスポンスが悪くなってしまった。
      • HTMLサーバーは css、js、html などテキストベースのファイルはphpとして作動させるようにしている。
      • 5万PV/hour ≒ 20万PV/hour 相当の処理をさせてしまっていた、という感じか。(css 2個、js 1個、html 1個)
  • この時点での失敗1
    • この時点では httpd の再起動しかしなかった。サーバー自体を再起動すべきだった。
    • css、js、ヘッダ画像をHTMLサーバーに移したのは、この時点では正解だったが、長い目で見ると悪手だった。
  • この時点での失敗2
    TOPコマンドの結果に注目しすぎていた。
    • さくらのスタンダードで運営していた時、CPU使用率50%以上、ロードアベレージ1.5を超えると503エラーが発生する事を体感的に掴んでいた。
      上記は2010年頃の話。さくらのスタンダードはサーバーがかなりパワーアップしているので、上記は当てはまらなくなっているかも。
    • iptablesのパケット処理やTCP接続の数が足りない場合、CPU使用率10%以下、ロードアベレージ 0.6程度でもサーバーがフリーズする。
    • 現在の私のサーバーの場合、ロードアベレージ 0.3~0.4で既に危ない状態になってる。
  • この時点での失敗3
    • httpdを再起動すると、以下のメッセージが記録されていた。
      httpd: apr_sockaddr_info_get() failed for hogehoge.com
      httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
    • /etc/hosts の記述に問題は無い、というかこの5年設定は変えず、一度もエラーが出たことが無い部分だ。
    • このエラーログを読み、DNSサーバーが限界になった、もしくはhttpdの名前解決に問題が発生していると思ってしまった。
    • VPSのTOPコマンドでは余裕があったことから、余計にそう思ってしまった。
    • 正解は「7. iptables のパケット上限を増やす」を行う事。
      サーバー内部のパケットも破棄される状態だったらしい。

 

5.ひとまず上記の対策で1晩放置して様子見。

  • ひとまず上記の対策で1晩放置して様子見。
    翌日、ほとんど効果がなかったので次の対策に乗り出す。
  • さくらの管理画面からコンソール接続し「3.sshでログインできない」で書いた「ログイン時のエラーメッセージ」を読めた事でようやく根本的な解決策に辿り着く事が出来た。

6. さくらの管理画面からコンソール接続

  • ログイン時のエラーメッセージ
    ip_conntrack: table full, dropping packet.
    printk: 1243 messages suppressed.
  • iptables のパケット情報が一杯になり、これ以上コネクションが張れない状態だった。
  • 次項「7. iptables のパケット上限を増やす」で対処できた。
  • ここでの失敗

7. iptables のパケット上限を増やす

8. iptables 未検証項目

  • iptables ディレクティブは上から順に処理される。
    ディレクティブの記述順を変更するとどうなるだろう?
  • 例えば 80番ポートより先に22番ポートの処理を記述すれば、sshのアクセス処理は優先されるんじゃないだろうか?
  • まだ試していない。優先順位低め。気が向いたときに試す。
    たぶん上手くいく。

9. httpd Client

  • どうやら数が多すぎたらしい。メモリ不足に陥っていた。
  • MaxClients = MinSpareServers = MaxSpareServers = N」
    という感じで最大値と最小値を同じ数値に固定すと fork が発生しないらしい。 → Apacheのチューニングメモ - Qiita
  • forkはサーバにとって重い部類の処理、負荷の高いときにforkを大量に行うのは良くないらしい。 → プロのサーバ管理者がApacheのStartServers, (Min|Max)SpareServers, MaxClientsを同じにする理由 - blog.nomadscafe.jp
  • 画像サーバー側のチューニング
    • チューニング前
      StartServers       8
      MinSpareServers    5
      MaxSpareServers   20
      ServerLimit      256
      MaxClients       256
      MaxRequestsPerChild  10000
      MaxMemFree 2048
      メモリ不足が発生した。
    • 1回目のチューニング
      StartServers 80
      MinSpareServers 120
      MaxSpareServers 120
      MaxClients 120
      MaxRequestsPerChild 8000
      MaxMemFree 2048
      まだメモリ不足が発生した。
    • 2度目のチューニング
      StartServers 80
      MinSpareServers 100
      MaxSpareServers 100
      MaxClients 100
      MaxRequestsPerChild 8000
      MaxMemFree 768
      なんとか動くようになった。
      • ただし、この時点では3万PV/hour (45万リクエスト/hour)位までアクセスは落ちていた。
      • スタティクファイルのみを配信するサーバーの場合、[MaxMemFree] はかなり小さい値でも問題なさそう。
      • 今度 [MaxMemFree 512]まで下げてみよう。
  • HTMLサーバー側のチューニング
    • チューニング前
      StartServers       8
      MinSpareServers    5
      MaxSpareServers   20
      ServerLimit      256
      MaxClients       256
      MaxRequestsPerChild  10000
      MaxMemFree 2048
      メモリ不足が発生した。
    • チューニング
      StartServers 35
      MinSpareServers 35
      MaxSpareServers 35
      MaxClients 35
      MaxRequestsPerChild 4000
      MaxMemFree 2048
      • これで良い感じになった。
      • cgi やphp化したhtmlを走らせているので、1つの子プロセスが結構メモリを食っていた。30個でもギリギリswapが発生するかしないか・・・・という感じ? 少し様子見
      • /etc/php.ini 
        memory_limit = 128M (初期値?)のままだった。
        16Mにした記憶があるんだけどなあ....もう一回16Mに設定
  • その他メモ

10. KeepAlive

  • 個人的に一番ショックを受けた項目。
    画像サーバーもKeepAliveはOFFの方が高速だった!
    • チューニング前
       MaxKeepAliveRequests 100
       KeepAliveTimeout 4 
    • 1回目のチューニング
       MaxKeepAliveRequests 70
       KeepAliveTimeout 3
    • 2回目のチューニング
       MaxKeepAliveRequests 30
       KeepAliveTimeout 1
      ここまで全て、9時~12時もしくは16時、21時頃 (このサイトのピークタイム) にTCP接続が一杯になり、そこから後はサーバーレスポンスが非常に悪い状態が続くようになってしまった。
    • 3回目のチューニング
       KeepAlive off
      サーバーレスポンスが全然落ちない。画像20~30個あるWebページにアクセスが集中しても大丈夫。
      KeepAlive とは何だったのか・・・・orz
  • ちなみに、チューニング前の「KeepAliveTimeout 4」は、光回線ユーザーもいる反面 まだアナログモデムなど低速回線からのアクセスも多く、ガラケーからのアクセスもあった時代の設定だった。
  • 余談メモ

11.TCPセッションの数を増やす


12. 今後の予測をしてみる

  • ここまでのチューニングを施し、次に大量アクセスが来た場合、以下のエラーが発生すると予測する。

13. サーバー増強を視野に入れる

  • ここまで書いたすべての対策を行うと、http Clientに割り当てできるメモリが僅かになり、起動できるClientの数が足りなくなる。結局アクセスを捌き切れなくなる。
    • 2~4GBのメモリが使えるサービスを使う。
    • これ以上 多くのメモリを積んでも、100Mbps 共有回線の20~40%を常時占有する状態になってしまう。
    • メモリ増やすより台数増やす。
  • 100Mbps 共有回線で常時 30Mbps を占有するのはさすがに申し訳ない
    • 回線品質の高い サービスを利用する or クラウドを利用する。
    • 見積もってみたら月額5万コースだ...orz
    • やっぱり さくらのVPSの下位グレードを3~4台借りて負荷分散した方が安いなコレ。
  • いちおうクラウドも勉強してみる
    • 一度組めばスケールするの簡単そうだけど、最初に構成組むのが異様に難しいなコレ(^_^;

14. まとめ

  1. 画像専用サーバーでもKeepAliveはOFFにする
  2. httpd Clientの数は必要最小限に減らす。
    httpdが使うメモリの量もギリギリまで減らす。
  3. メモリに余裕が出来た分をiptablesのパケット処理やTCPセッションの数の増加に回す。
    • サーバー素人の浅はかな考えだけど、
      メモリ使用量は
      httpd Client : iptabls+TCP : MySQL = 4:4:2
      くらいにしとけば良いんじゃないだろうか?

今回の場合、この3つが正解だった。
VPSを初めて触った2011年当時、あれこれをチューニングを施したつもりになっていたが、まだまだだった。

15. その他に行った事

  • 画像サーバー側が限界に近かったので、
     ・ブログのヘッダ画像 2個
     ・javascript ファイル 1個
     ・css ファイル 2個
    上記5点を HTMLサーバー側に移動した。

16. チューニング後の結果

  • 画像サーバー側
    •  5万PV/hour (70~90万リクエスト/hour ?)でもパフォーマンス低下はしなくなった。
    • しかし、対策前の障害発生中でも、最大 75万リクエスト/hour くらい処理してた。
    • あれ?変わらない...?でもまあ、 チューニング後はパフォーマンスは落ちなくなったので良しとしよう。
    • ※チューニング後、まだ5万PV/hour以上のアクセスは来ていない。
  • HTMLサーバー側
    • 12万PV/hour でも何とか応答していたものが、5万PV/hourがほぼ限界になってしまった。(13~15万リクエスト/hour → 30~40万リクエスト/hour に増大したため)
    • 最終的なチューニングが終わった後は 5万PV/hourクラス のアクセスは発生していない。もう少し余力はあるかも?
  • 余談: アクセス解析サーバ
    • Mogura PlusXをインストールしたサーバー。
      CPU負荷は一番高いが、今の所チューニングなしでも元気に動いている。
    • ピーク時・・・・7万件/hour のアクセスを解析。
      (画像サーバーに置いたjavascript が応答しなくなったため、解析ツールにアクセスが飛ばなかった。)
  • 見立てが少し甘かった。
    • 過去、2015年2月に 4.3万PV/hour のアクセスが発生した際、3つのサーバー全てでロードアベレージ0.3前後だった。
    • ロードアベレージだけを見て「この位のアクセスならVPS1個で処理できるかも」とメモをしていたが、大間違いだった。安定稼働できるギリギリのアクセスだったかもしれない。
    • しかし・・・・
      • 当時・・・・
        画像1個のページに9万PV/day
        画像9個のページに4万PV/day
      • 今回・・・・
        画像9~11個のページに9万PV/day X2ページ
        画像9~16個のページに5万PV/day X3ページ
        画像5~15個のページに3万PV/day X5ページ
      • といった感じで、画像サーバーへの負荷は当時の4~5倍は発生していた。前回と今回を比較してはいけないな、とも思った。

次にやること

abテストする。
過去abテストした時は、リアルで大量にアクセスを捌いた経験が無かったので、ベンチマークの数値にイマイチ実感がなかった。今回の経験を踏まえ、もう一回abテストしてみる。

その他: mod_evasive20.c

  • DDos 対策モジュール。
  • 当初から画像サーバーにのみ導入中。
    たまに役に立つので、今回の負荷対策でも停止させずにそのまま様子見。