このブログと併設している「ぼくんちの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で既に危ない状態になってる。
- さくらのスタンダードで運営していた時、CPU使用率50%以上、ロードアベレージ1.5を超えると503エラーが発生する事を体感的に掴んでいた。
- この時点での失敗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 のパケット上限を増やす」を行う事。
サーバー内部のパケットも破棄される状態だったらしい。
- httpdを再起動すると、以下のメッセージが記録されていた。
5.ひとまず上記の対策で1晩放置して様子見。
- ひとまず上記の対策で1晩放置して様子見。
翌日、ほとんど効果がなかったので次の対策に乗り出す。
- さくらの管理画面からコンソール接続し「3.sshでログインできない」で書いた「ログイン時のエラーメッセージ」を読めた事でようやく根本的な解決策に辿り着く事が出来た。
6. さくらの管理画面からコンソール接続
- ログイン時のエラーメッセージ
ip_conntrack: table full, dropping packet.
printk: 1243 messages suppressed.
- iptables のパケット情報が一杯になり、これ以上コネクションが張れない状態だった。
- 次項「7. iptables のパケット上限を増やす」で対処できた。
- ここでの失敗
7. iptables のパケット上限を増やす
- 大幅に改善した
- cat /proc/sys/net/ipv4/ip_conntrack_max
ip_conntrackの最大値を調べる
- cat /proc/sys/net/ipv4/netfilter/ip_conntrack_count
ip_conntrackの現在値を調べる - 現在値 = 最大値の場合、パケットがドロップしまくっている状態。
サーバー再起動してからip_conntrack_maxを増やす。 - net.ipv4.ip_conntrack_max = 45000
(元の数値は最大値・現在値ともに32760だった) - このままでは iptables 再起動で元の値に戻るので注意。
- 参考にしたURL
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に設定
- チューニング前
- その他メモ
- リンク先では「StartServers」の値も揃えた方が良いように書かれていたが、なんとなく少なめに設定してみた。
- メモリ1GBの 場合、MaxClients 100 あたりが丁度よくなるのはだいたいドコでも同じなのかな?
同時接続数(MaxClients)をいくつに設定すべきか?
apacheの同時接続数(MaxClients)を検証する » taka's趣味の部屋
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」は、光回線ユーザーもいる反面 まだアナログモデムなど低速回線からのアクセスも多く、ガラケーからのアクセスもあった時代の設定だった。
- 余談メモ
- Nginx の keep-alive の設定と検証 - How old are you?
Nginx導入する時はこのページを参考にkeepalive の設定を行う。
- Nginx の keep-alive の設定と検証 - How old are you?
11.TCPセッションの数を増やす
- 上記「10.」までの対策で、高負荷時のレスポンスはかなり改善された。しかし、まだ5万PV/hourを超えるとサーバー表示はおかしくなる。
- messagesでエラーログを読んでみる
possible SYN flooding on port 80. Sending cookies.
- KeepAliveをOFFにしたらこのメッセージが出るようになった。
- SYNパケットが溢れたか、もしくはDos攻撃を受けたと判定を受けているらしい。
- SYNパケット・・・・TCPで接続を確立する時にクライアントからサーバーに送られるパケット
SYN flood - Wikipedia
- デフォルトの値は結構小さいらしい。→確認してみる
sysctl net.core.somaxconn
結果 → net.core.somaxconn = 128
足りていない。 - 以下のように設定変更した
- 画像サーバー、HTMLサーバーの設定
sysctl -w net.core.somaxconn=1024 - アクセス解析サーバーの設定
sysctl -w net.core.somaxconn=384 - Dos攻撃判定そのものを無効化する場合
sysctl -w net.ipv4.tcp_syncookies=0
- これは今回は試していない。
- 詳しい: listen backlog 【3.6】 - Linuxカーネルメモ
「net.ipv4.tcp_syncookies=0」は不要か?
そしてもう少しチューニングが必要な感じ。 - 大量アクセスの波は去った。実機での検証は出来なかった。次回に持ち越し。
- これは今回は試していない。
- 画像サーバー、HTMLサーバーの設定
- 参考にしたURL
- 小岩以上アキバ未満~記憶のディザスター~: CentOS6などでdmesgにpossible SYN flooding on port(SYN flooding警告)が出た場合の対策方法を考えてみるテスト
- Linuxサーバで負荷試験するにあたって - Qiita
- DSAS開発者の部屋:高負荷サイトのボトルネックを見つけるには
- 再起動時も有効にする方法
/etc/sysctl.conf に「net.core.somaxconn = 1024」を追記
memcached が変なんです。顛末記 | 丸ノ内テックブログ
12. 今後の予測をしてみる
- ここまでのチューニングを施し、次に大量アクセスが来た場合、以下のエラーが発生すると予測する。
- エラーログ「Too many open files」が記録される
- open files の値を確認
1024 - 制限値を上げるため /etc/security/limits.conf ファイルを編集
soft nofile 3072
hard nofile 3072 - 再起動しても値が反映されない場合がある
- 参考
Linux サーバでの「Too many open files」対策について - akishin999の日記
13. サーバー増強を視野に入れる
- ここまで書いたすべての対策を行うと、http Clientに割り当てできるメモリが僅かになり、起動できるClientの数が足りなくなる。結局アクセスを捌き切れなくなる。
- 2~4GBのメモリが使えるサービスを使う。
- これ以上 多くのメモリを積んでも、100Mbps 共有回線の20~40%を常時占有する状態になってしまう。
- メモリ増やすより台数増やす。
- 100Mbps 共有回線で常時 30Mbps を占有するのはさすがに申し訳ない
- 回線品質の高い サービスを利用する or クラウドを利用する。
- 見積もってみたら月額5万コースだ...orz
- やっぱり さくらのVPSの下位グレードを3~4台借りて負荷分散した方が安いなコレ。
- いちおうクラウドも勉強してみる
- 一度組めばスケールするの簡単そうだけど、最初に構成組むのが異様に難しいなコレ(^_^;
14. まとめ
- 画像専用サーバーでもKeepAliveはOFFにする
- httpd Clientの数は必要最小限に減らす。
httpdが使うメモリの量もギリギリまで減らす。 - メモリに余裕が出来た分を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 が応答しなくなったため、解析ツールにアクセスが飛ばなかった。)
- Mogura PlusXをインストールしたサーバー。
- 見立てが少し甘かった。
- 過去、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 対策モジュール。
- 当初から画像サーバーにのみ導入中。
たまに役に立つので、今回の負荷対策でも停止させずにそのまま様子見。