TCPとNginxの設定不足によるトラブル
初の技術的な投稿では、自分が100~200人ぐらいを対象にシステムを提供した際に起きた問題について触れたいと思います。
C言語の演習環境を提供するという目的で、100人ぐらいの同時アクセスがあるという想定のもと、仮想マシン1台に構築しました。 Nginxによるリバースプロキシを前面に置いて、認証結果によってユーザ毎別々のDockerコンテナに振り分ける構成です。
以前40人程度を対象に、DockerではなくVirtualBoxによる仮想マシンを使用し、同じシステムを問題なく提供できていたので特に考えず構築し、デプロイしました。 結果、繋がらないの怨嗟の声がそこら中から上がる展開に。
ロードアベレージの極端な上昇が見られなかったので「あの部屋のネットワークが細いのが原因ではないか」と高を括っていたのですが、ネットワークが整備された部屋でも同じ現象が見られたため、ドキドキしながら原因を探しました。 結果、TIME_WAITになっている大量のポートを発見。
先ずはTIME_WAITが原因だと考え、Linuxパラメータの変更による解決を試みました。
# /etc/sysctl.conf
fs.file-max = 5242880
net.ipv4.ip_local_port_range = 18000 65535
net.core.netdev_max_backlog = 10240
net.core.somaxconn = 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_fin_timeout = 20
net.ipv4.tcp_max_syn_backlog = 10240
net.ipv4.tcp_rfc1337=1
設定後seleniumを使用して150人同時アクセス再現を試みた結果、まだ繋がらないホストがあったためnginxの設定変更を行いました。
# nginx.conf # 差分箇所のみ記述 worker_rlimit_nofile 150000; events { multi_accept on; worker_connections 65535; } http { tcp_nopush on; sendfile on; server_tokens off; reset_timeout_connection on; }
ここまでやった結果、seleniumでのアクセス再現も問題なく成功し、実稼働でも繋がらないという声は(ほとんど)なくなりました。 設定内容の解説については後日記事にできたら、と思います。
参考 Nginxのパフォーマンスを極限にするための考察 – Qiita http://qiita.com/iwai/items/1e29adbdd269380167d2