読者です 読者をやめる 読者になる 読者になる

uokadaの見逃し三振は嫌いです

ここで述べられていることは私の個人的な意見に基づくものであり、私が所属する組織には一切の関係はありません。

nginxをリバースプロキシで使うならKeepAliveするべき

タイトルは釣りでnginxにかぎらずリバースプロキシ使うならって話。

高負荷サイトのフロントにnginxをリバースプロキシとしてたてて後ろのサーバーへリクエストをなげていたら数百rpsでいろいろなエラーがnginxのログに落ちてきた。 その時にとった対策を少しまとめてみる。

まず、nginxのエラーログに下のようなエラーの対処法。

nginx: [emerg] bind() to 127.0.0.1:8080 failed (99: Cannot assign requested address)
$ netstat -an |grep TIME_WAIT |wc

このときのwcの結果は2万数千あり、詳細を調べていくとその中の大部分が後ろのサーバーからnginxにリクエストを返すために利用したポートがほとんどであった。

これを解消するための対策として一番手っ取り早いのがカーネルのチューニングである。

$ sysctl net.ipv4.ip_local_port_range
net.ipv4.ip_local_port_range 32768 61000

$ sudo sysctl -w net.ipv4.ip_local_port_range="10240 61000"

$ sysctl net.ipv4.ip_local_port_range
net.ipv4.ip_local_port_range 10240 61000

上限は変更しないで下限だけ変更して利用できるエフェメラルポートを増やすようにした。

これでもダメな場合に nginxと後ろのアプリケーションサーバーの間をKeepAliveして接続数を抑える。 これが本当に効果的でアプリケーションサーバーからnginxへのレスポンスを返すコネクションがKeepAliveの本数だけに減るのでトータルのエフェメラルポートが万単位から100前後にまで劇的に減らせた。

さらに、コネクションが減ったことでメモリ使用量も20%前後改善したのでメモリが足りないサーバーでもこの設定は効果的だと思った。

Too many open filesが出た時

accept() failed (24: Too many open files) while accepting new connection on 127.0.0.1:80

さらに高負荷になったときにnginxのログにToo many 〜のエラーが落ちるようになった。

% cat /proc/12345/limits |grep "Max open files"
Max open files            4096                 4096                 files     

# ulimitを使ってopen出来るファイル数の上限を増やす
% sudo sh -c "ulimit -n 32768"

# nginx を再起動

% cat /proc/12345/limits |grep "Max open files"
Max open files           32768               32768               files     

nginx で Too many open files エラーに対処する - Shin x blog

apacheでも同じようなことが起きると思うのでよくやる設定だとおもう。 サーバーが再起動するとこの設定が無効になるので再起動した際はちゃんと設定が有効か確認しましょう。

2014-05-14 追記

worker_rlimit_nofile で増やすほうがスマートってことを教えてもらったのでこれを設定するようにした。 設定する値は worker_connections の3〜4倍くらいが良いらしいが自分はとりあえず2倍に設定をした。 nginx で Too many open files エラーに対処する - Shin x blog

参考

ローカルポートを食いつぶしていた話 - ダウンロードたけし(寅年)の日記

エフェメラルポート - Wikipedia