I've been trying to tune up our Ubuntu 14.04 LTS web server instances, hosting both web applications and reverse-proxying nginx, to handle as many req/s as possible with the given hardware. It's a c4.2xl EC2 instance with 8x vCPU.
I'm running the following two benchmark tools against it from my office machine (NOT both at the same time):
wrk -c1000 -d2m -t8 --timeout 90 --latency http://api.mysite.com/2/ping
# or
ab -k -n 100000 -c 1000 http://api.mysite.com/2/ping
What I'm seeing is that by running ss -tan | wc -l
I always max out at about 65.5k connections in TIME-WAIT
My OS setup is:
net.ipv4.ip_local_port_range value="15000 65000"
/etc/security/limits.conf
has `www-data hard nofile 100000' in it/etc/pam.d/common-session*
are updated to read the above
And the nginx setup is:
worker_processes auto; # will result in 8 on this machine
events {
worker_connections 8192;
multi_accept on;
use epoll;
}
Upstream to the api being proxied to nginx is below, used to get a very high maximum of different TCP quadruplets, meaning I pretty much never run out of ephemeral ports in nginx -> app:
upstream my_api {
server 127.0.0.1:3004;
server 127.0.0.2:3004;
server 127.0.0.3:3004;
[...]
}
I experience a similar issue with my m3.large instance where instead of 65k I max out at 32k. The difference between the two instances is that the former has 2vCPU, the latter has 8, and the former has 7.5GB memory and the latter has 15GB.
A similar problem has been described in this post (Scaling beyond 65k open files (TCP connections)) but it doesn't seem to apply in my case, as on my smaller instance the vm.max_map_count
is 65530, but it never goes past 32k connections in TIME-WAIT
.
I thought that at first the limit was just # processes * # workers, but on the smaller instance I'm still capped at 32k even if I raise the # of workers per process to 25k each, so that's not it.
I'm not sure what knob to tweak at this point, not clear to me where these hard constraints could be coming from. Could use some help here.
Interestingly enough, I don't see connections being ultimately refused from either of these machines as TIME-WAIT reaches this "limit". It's possible the socket queues are filling up behind the scenes and the client just re-attempts to establish a connection later again, which is why I'm not seeing any permanent failures.
Update:
On a c4.8xlarge instance I can get up to 262k connections in TIME-WAIT with the same exact deployment configurations. Even limiting # of nginx workers to just 1 doesn't change it. Still not sure what the difference would be here.
Update 2:
I strongly suspect this has to do with the different instances all having different net.ipv4.tcp_max_tw_buckets
values which from what I can tell match exactly the pattern I'm seeing.