併設の「ぼくんちのTV別館 (さくらのVPS3台体制)」が1日80万PVに達し、サーバーのパフォーマンスが著しく悪くなり、ほぼフリーズしたような状態になった後に行ったチューニング。
- 最低限の情報のみを掲載した簡易版です。
- 当時のメモを詳細に読みたい場合→ 時系列版を用意しています。
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.アクセスが増えすぎた後、どうなったか
- 画像サーバーが応答しなくなった。
- 画像サーバーにsshログインできなくなった
2.sshログインできなくなった場合
- さくらの管理画面のコンソールを使ってログインを試みる
- ログインできない場合でも、エラーメッセージが表示される。
- メッセージを元に対策が取れる。
- 今回の場合、iptablesのコネクションが一杯になっていた。
- どうにもならない時は強制リブートをかける。
- 詰まっているパケットが破棄されてログイン可能になる。
3.sshログイン後
- TOPコマンドで得られる情報だけで判断しない。
- iptablesやTCP接続が一杯になり、通信が破棄されているケースは TOPコマンドでは判断できない
4.iptables
- パケットが一杯になった時のエラー1
ip_conntrack: table full, dropping packet.
printk: 1243 messages suppressed. - パケットが一杯になった時のエラー2
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
apacheのエラーとして記録される。
「apachectl configtest」や「httpd 再起動」した時に上記エラーが出る。
名前解決がうまくいっていないように見えるが、パケットが一杯になっているだけ。 - 解決方法
- 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
- cat /proc/sys/net/ipv4/ip_conntrack_max
5. iptables 未検証項目
- iptables ディレクティブは上から順に処理される。
ディレクティブの記述順を変更するとどうなるだろう? - 例えば 80番ポートより先に22番ポートの処理を記述すれば、sshのアクセス処理は優先されるんじゃないだろうか?
- まだ試していない。優先順位低め。気が向いたときに試す。
たぶん上手くいく。
6. httpd Client
- どうやらクライアント数が多すぎたらしい。メモリ不足に陥っていた。
- 「MaxClients = MinSpareServers = MaxSpareServers = N」
という感じで最大値と最小値を同じ数値に固定すと fork が発生しないらしい。 → Apacheのチューニングメモ - Qiita - forkはサーバにとって重い部類の処理、負荷の高いときにforkを大量に行うのは良くないらしい。 → プロのサーバ管理者がApacheのStartServers, (Min|Max)SpareServers, MaxClientsを同じにする理由 - blog.nomadscafe.jp
- 「MaxClients = MinSpareServers = MaxSpareServers = N」
- 画像サーバー側のチューニング
- チューニング後
StartServers 80
MinSpareServers 100
MaxSpareServers 100
MaxClients 100
MaxRequestsPerChild 8000
MaxMemFree 768
なんとか動くようになった。MaxMemFree を2048→768 に減らしたのが効果が大きかった。
- ただし、この時点では3万PV/hour (推定40万リクエスト/hour)位までアクセスは落ちていた。
- スタティクファイルのみを配信するサーバーなので、[MaxMemFree] はかなり小さい値でも問題なさそう。
- 今度 [MaxMemFree 512]まで下げてみよう。
- チューニング後
- HTMLサーバー側のチューニング
- チューニング後
StartServers 35
MinSpareServers 35
MaxSpareServers 35
MaxClients 35
MaxRequestsPerChild 4000
MaxMemFree 2048
- これで良い感じになった。
- cgi やphp化したhtmlを走らせているので、1つの子プロセスが結構メモリを食っていた。35個でもギリギリswapが発生するかしないか・・・・という感じ? 少し様子見
- /etc/php.ini
memory_limit = 16M に設定
無駄にメモリを食わせない。
- チューニング後
- その他メモ
- リンク先では「StartServers」の値も揃えた方が良いように書かれていたが、なんとなく少なめに設定してみた。
- メモリ1GBの 場合、MaxClients 100 あたりが丁度よくなるのはだいたいドコでも同じなのかな?
同時接続数(MaxClients)をいくつに設定すべきか?
apacheの同時接続数(MaxClients)を検証する » taka's趣味の部屋
7. KeepAlive
- 個人的に一番ショックを受けた項目。
画像サーバーもKeepAlive OFFの方が高速だった! - KeepAliveTimeout 1 でもアクセス多いとセッション足りなくなる。
- 余談メモ
- Nginx の keep-alive の設定と検証 - How old are you?
Nginx導入する時はこのページを参考にkeepalive の設定を行う。
- Nginx の keep-alive の設定と検証 - How old are you?
8. TCPセッションの数を増やす
- 上記「7.」までの対策で、高負荷時のレスポンスはかなり改善された。しかし、まだ5万PV/hourを超えるとサーバー表示はおかしくなる。
- messagesにエラーログ
possible SYN flooding on port 80. Sending cookies.
- KeepAliveをOFFにしたらこのメッセージが出るようになった。
- SYNパケットが溢れたか、もしくはDos攻撃を受けたと判定を受けている・・・・らしい。
- SYNパケット・・・・TCPで接続を確立する時にクライアントからサーバーに送られるパケット
SYN flood - Wikipedia
- SYNパケット・・・・TCPで接続を確立する時にクライアントからサーバーに送られるパケット
- デフォルトの値は結構小さいらしい。→確認してみる
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 が変なんです。顛末記 | 丸ノ内テックブログ
9. 今後の予測をしてみる
- 次に大量アクセスが来た場合、以下のエラーが発生すると予測する。
- エラーログ「Too many open files」が記録される
- open files の値を確認
1024 - 制限値を上げるため /etc/security/limits.conf ファイルを編集
soft nofile 3072
hard nofile 3072 - 再起動しても値が反映されない場合がある
- 参考
Linux サーバでの「Too many open files」対策について - akishin999の日記
10. サーバー増強を視野に入れる
- ここまで書いたすべての対策を行うと、http Clientに割り当てできるメモリが僅かになる。起動できるClientの数が足りなくなる。結局アクセスを捌き切れなくなる。
- 2~4GBのメモリが使えるサービスを使う。
- これ以上 多くのメモリを積んでも、100Mbps 共有回線の20~40%を常時占有する状態になってしまう。
- メモリ増やすより台数増やす。
- (今のページ構成の場合) 10万PV/hourのアクセスが発生すると、30Mbpsの転送量が発生する。
- 100Mbps 共有回線で常時 30Mbps を占有するのはさすがに申し訳ない
- 回線品質の高い サービスを利用する or クラウドを利用する。
- 見積もってみたら月額5万コースだ...orz
- やっぱり さくらのVPSの下位グレードを3~4台借りて負荷分散した方が安いなコレ。
- あと、画像を減らそう。
- いちおうクラウドも勉強してみる
- 一度組めばスケールするの簡単そうだけど、最初に構成組むのが異様に難しいなコレ(^_^;
11. まとめ - 今回 効果があった対策
- 画像専用サーバーでもKeepAliveはOFFにする
- httpd Clientの数は必要最小限に減らす。forkしないようにする。
httpdが使うメモリの量もギリギリまで減らす。 - メモリに余裕が出来た分をiptablesのパケット処理やTCPセッション数の増加に回す。
- サーバー素人の浅はかな考えだけど、
メモリ使用量は
httpd Client : iptabls+TCP : MySQL = 4:4:2
くらいにしとけば良いんじゃないだろうか?
- サーバー素人の浅はかな考えだけど、
今回の場合、この3つが正解だった。
VPSを初めて触った2011年当時、あれこれをチューニングを施したつもりになっていたが、まだまだだった。
12. その他に行った事
- 画像サーバー側が限界に近かったので、
・ブログのヘッダ画像 2個
・javascript ファイル 1個
・css ファイル 2個
上記5点を HTMLサーバー側に移動した。
13. チューニング後のパフォーマンス
エラーが出なくなった、パフォーマンスが落ちなくなった、というだけで、処理能力は上がらなかったようだ。次に大量アクセスを貰うまで、正確な結果は分からない。
- 画像サーバー側
- 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 のアクセスを解析。もう少しイケる。
(12万PVが発生した際、画像サーバーに置いた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 対策モジュール。
- 当初から画像サーバーにのみ導入中。
たまに役に立つので、今回の負荷対策でも停止させずにそのまま様子見。