環境
- CentOS release 6.3 (Final)
- Apache/2.2.15
事象
同時1接続で20000リクエストを発行すると、Apacheの設定上は十分さばけるリクエスト数にもかかわらずTimeoutエラーとなる。
# ab -n 20000 -c 1 http://localhost/
Benchmarking localhost (be patient)
Completed 2000 requests
Completed 4000 requests
Completed 6000 requests
Completed 8000 requests
Completed 10000 requests
Completed 12000 requests
Completed 14000 requests
apr_poll: The timeout specified has expired (70007)
原因
syslogを見ると、以下の様なエラーが出ている。
iptablesのトラッキングテーブルが上限を超えて、パケットを破棄していることが原因のよう。
# cat /var/log/messages
Feb 19 15:33:07 localhost kernel: TCP: time wait bucket table overflow
Feb 19 15:33:15 localhost kernel: nf_conntrack: table full, dropping packet.
iptablesのトラッキングテーブルの上限は、カーネルパラメータの「nf_conntrack_max」で定義されている。
現在の定義値を見てみると14680となっているので、おおよそ14000リクエストでTimeoutになっている。
# sysctl -a | grep nf_conntrack_max
net.netfilter.nf_conntrack_max = 14680
net.nf_conntrack_max = 14680
対処法
/etc/sysctl.confに以下を追記して、トラッキングテーブルの上限を増やす。
# vi /etc/sysctl.conf
net.netfilter.nf_conntrack_max = 100000
net.nf_conntrack_max = 100000
設定反映
# sysctl -p
再度、負荷テストを実行すると問題なく処理できる。
# ab -n 20000 -c 1 http://localhost/
Benchmarking localhost (be patient)
Completed 2000 requests
Completed 4000 requests
Completed 6000 requests
Completed 8000 requests
Completed 10000 requests
Completed 12000 requests
Completed 14000 requests
Completed 16000 requests
Completed 18000 requests
Completed 20000 requests
Finished 20000 requests
参考サイト