続・間違いだらけの負荷対策
事の始まり
3月に入ってから「斉藤さん」のWebサーバーのピークタイムでのアクセス数が秒間180アクセスを境に動かなくなり、しまいには一部アクセスが固まって動かなくなるという現象が発生した。
Apacheのエラーログを見ると、データベースサーバーに接続できていない旨が出ていたため、その辺を念頭に置いていろいろと探ってみたのだが・・・。
ソケット数の限界?
「netstat -ant」と打つと、その時点でのTCPコネクションの一覧が出る。
ピーク時にWebサーバー側は30000前後、DBサーバー側は8000前後。
HandlerSocketのポート(標準では9998と9999)に絞ってみてみると、Webサーバー側は8000前後なのに対し、DBサーバー側は500前後。
明らかにWebサーバーのコネクション数がおかしい。
MySQLのコネクション数は問題なさそうなので、HandlerSocketのソケットが開けなくてパケットがドロップしてる?と想像して、/etc/sysctl.confにいろいろ設定を書いてみるが駄目。
iptables?
そういえばカーネル周りの設定をしておきながらカーネル周りのログを見ていなかった、と思い/var/log/messageを見てみると以下のようなログが出ていた。
Mar 8 02:57:26 api kernel: ip_conntrack: table full, dropping packet. Mar 8 02:57:38 api kernel: printk: 346 messages suppressed.
これを元にググってみると、どうやらiptablesに関係するエラーらしいということが分かった。
ちなみに、ニフティクラウドのサーバーは建てた時点で外部ネットワークに晒されるようになっているため、iptablesによるポートフィルタリングがデフォルトで設定された状態*1である。
この、iptablesはパケットを解析する際に/proc/net/ip_conntrackというファイルにその情報を記録するのだが、テーブルの上限数が設定されており、それを超えてしまうとパケットを落としてしまうらしい。
現在のiptablesのテーブルの項目数(?)とその限界は以下のように確認できる。
# 最大 $ cat /proc/sys/net/ipv4/ip_conntrack_max 65536 # 使ってる項目数 $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_count 63642
うおおおおテラギリギリスwwwwwwww
というわけで、そいつを上げればいいんだなと思い、両方のサーバーの/etc/sysctl.confに
net.ipv4.ip_conntrack_max = 131072
を設定してApacheBenchを動かしてみると、今まで途中で止まっていたベンチがスムーズに動くようになった。
まとめ
参考にしたサイト
中〜大規模サーバーを運用するときの勘所 – iptablesとip_conntrack – cyano
http://www.sssg.org/blogs/naoya/archives/1454
もしかして・・・
(アクセス裁けなかったの)Nginxのせいじゃない・・・!?