ローカルのRedisに大量データを入れていたところ、以下のエラーが発生しました。
Could not connect to Redis at 127.0.0.1:6379: Cannot assign requested address
Socketの状態を見てみたら以下の通り。28232 TIME-WAIT
が問題でした。
$ ss -tan | awk ‘{print $1}’ | sort | uniq -c 1 ESTAB 9 LISTEN 1 State 28232 TIME-WAIT
Linuxはデフォルトでephemeralポートのレンジとして以下が割当たっています。だいたい28000くらいなので、ここに引っかかっています。
$ sysctl -a | grep ip_local_port_range net.ipv4.ip_local_port_range = 32768 60999
対策①
ephemeralポートのレンジを増やす
例えば以下のように設定するとephemeralポートとして割り当て可能なポートが増えます。
$ sysctl -a | grep ip_local_port_range net.ipv4.ip_local_port_range = 32768 60999
対策②
または、net.ipv4.tcp_tw_reuse
を有効化します。これにより既にTIME-WAITになっている同一のIP・同一のPortのクライアントからのSYNが来た場合にTIME-WAITのソケットを再利用します。
同一クライアントから多くの接続を張る場合には効果大きいと思います。逆に大量のクライアントから接続を張る場合(今回のケースでは少ないかもしれませんが・・)net.ipv4.tcp_tw_reuse
はあまり効果無いことになります。
$ sysctl -a | grep net.ipv4.tcp_tw_reuse net.ipv4.tcp_tw_reuse = 1
設定するとある程度までは TIME-WAIT
の数増えますが、そこで止まるようになるはずです。
$ ss -tan | awk ‘{print $1}’ | sort | uniq -c 6 ESTAB 9 LISTEN 1 State 14114 TIME-WAIT
ここまで書いてみて気付いたのですが、他に書いてられる方いらっしゃいましたね。
kakakikikekeのブログ: Could not connect to Redis at 127.0.0.1:6379: Cannot assign requested address