This article was published over 2 years ago. Some information may be outdated.
Some Linux servers limit incoming network connections to a low number -- sometimes as few as 128. If your server has the hardware to handle thousands of concurrent connections but somaxconn is set too low, the kernel will reject connections before your application ever sees them.
Linux controls this limit through the somaxconn kernel parameter. The default value varies by distribution; on Ubuntu, it defaults to 4096.
Check your current value:
sysctl net.core.somaxconn
Benchmarking with a low limit
Install Apache Benchmark on your machine before proceeding.
Set somaxconn to 100 to demonstrate the problem:
echo 100 > /proc/sys/net/core/somaxconn
# remember to reload nginx
sudo service nginx reload
Send 500 requests with 150 concurrent connections:
ab -n 500 -l -c 150 -k -H "Accept-Encoding: gzip, deflate" http://example.com/
-cconcurrency: Number of multiple requests to perform at a time.
Result:
Concurrency Level: 120
Time taken for tests: 5.215 seconds
Complete requests: 500
Failed requests: 0
Non-2xx responses: 373
Keep-Alive requests: 373
Total transferred: 1280928 bytes
HTML transferred: 1039564 bytes
Requests per second: 95.88 [#/sec] (mean)
Time per request: 1251.513 [ms] (mean)
Time per request: 10.429 [ms] (mean, across all concurrent requests)
Transfer rate: 239.88 [Kbytes/sec] received
Out of 500 requests, only 127 succeeded. The remaining 373 returned non-2xx responses.
Non-2xx responsesshows the total number of requests that returned a non-success status code.
At this point, accessing the site in a browser would likely show a 502 Bad Gateway because Nginx cannot accept more connections than the kernel allows.
Increase the incoming connections
Set somaxconn to 1000:
echo 1000 > /proc/sys/net/core/somaxconn
Run the benchmark again, this time with 1000 requests and 200 concurrent connections:
ab -n 1000 -l -c 200 -k -H "Accept-Encoding: gzip, deflate" http://157.90.226.65/usr
Result:
Concurrency Level: 200
Time taken for tests: 39.830 seconds
Complete requests: 1000
Failed requests: 0
Keep-Alive requests: 0
Total transferred: 9066911 bytes
HTML transferred: 7698000 bytes
Requests per second: 25.11 [#/sec] (mean)
Time per request: 7966.077 [ms] (mean)
Time per request: 39.830 [ms] (mean, across all concurrent requests)
Transfer rate: 222.30 [Kbytes/sec] received
All 1000 requests succeeded.
Persisting the change
Writing to /proc/sys/net/core/somaxconn is temporary -- the value resets on reboot. To make it permanent, create a sysctl configuration file:
echo "net.core.somaxconn=10000" > /etc/sysctl.d/network-tunning.conf
A value of 10,000 is a reasonable starting point for most production servers.
Summary
somaxconncontrols the maximum number of queued incoming connections at the kernel level -- a low value silently drops connections regardless of your server's capacity.- The default value varies by distribution, so always check your current setting before assuming it is adequate.
- A too-low
somaxconncauses502 Bad Gatewayerrors because Nginx (or any other reverse proxy) cannot accept connections the kernel has already rejected. - Write the value to
/etc/sysctl.d/to persist it across reboots.