Of course we cannot always share details about our work with customers, but nevertheless it is nice to show our technical achievements and share some of our implemented solutions.
A Nginx reverse proxy suddenly started to return error 500 on all kinds of sites. The response varied between a real http error (500) and a non-working http communication.
$ curl https://app.example.com -v
* Rebuilt URL to: https://app.example.com/
* Trying xxx.xxx.xxx.xxx...
* Connected to app.example.com (xxx.xxx.xxx.xxx) port 443 (#0)
* found 127 certificates in /etc/ssl/certs/ca-certificates.crt
* found 520 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_256_GCM_SHA384
* server certificate verification OK
* server certificate status verification SKIPPED
* common name: *.example.com (matched)
* server certificate expiration date OK
* server certificate activation date OK
* certificate public key: RSA
* certificate version: #3
* subject: OU=Domain Control Validated,OU=Gandi Standard Wildcard SSL,CN=*.example.com
* start date: Thu, 24 Oct 2019 00:00:00 GMT
* expire date: Thu, 09 Dec 2021 23:59:59 GMT
* issuer: C=FR,ST=Paris,L=Paris,O=Gandi,CN=Gandi Standard SSL CA 2
* compression: NULL
* ALPN, server accepted to use http/1.1
> GET / HTTP/1.1
> Host: app.example.com
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 500 Internal Server Error
< Server: nginx
< Date: Fri, 14 Aug 2020 06:16:54 GMT
< Content-Type: text/html
< Content-Length: 10
< Connection: close
< ETag: "5f362c2c-a"
<
Error 50x
* Closing connection 0
$ curl https://app.example.com -v
* Rebuilt URL to: https://app.example.com/
* Trying xxx.xxx.xxx.xxx...
* Connected to app.example.com (xxx.xxx.xxx.xxx) port 443 (#0)
* found 127 certificates in /etc/ssl/certs/ca-certificates.crt
* found 520 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* gnutls_handshake() failed: The TLS connection was non-properly terminated.
* Closing connection 0
curl: (35) gnutls_handshake() failed: The TLS connection was non-properly terminated.
Luckily there are error logs available - and the logged error is very much self-explaining:
2020/08/14 08:15:31 [alert] 22158#22158: *469070133 768 worker_connections are not enough while connecting to upstream, client: 54.93.81.216, server: app.example.com, request: "GET /v3/connect/config HTTP/1.1", upstream: "http://127.0.0.1:8105/v3/connect/config", host: "app.example.com"
worker_connections is a global config option in the events context. On most Nginx installations this can be found in /etc/nginx/nginx.conf.
events {
worker_connections 768;
# multi_accept on;
}
The default value, here on an Ubuntu 18.04 system, is set to 768 worker_connections. In this case, this reverse proxy received more connections than this and the default worker_connections limit is not high enough.
After setting worker_connections to a higher value and a Nginx restart, the errors were gone and the reverse proxy served the application again.
root@nginx:~# grep worker_connections /etc/nginx/nginx.conf
worker_connections 1024;
root@nginx:~# systemctl restart nginx
$ curl https://app.example.com -I
HTTP/1.1 200 OK
Server: nginx
Date: Fri, 14 Aug 2020 06:18:45 GMT
Content-Type: application/json
Connection: keep-alive
Vary: Accept-Encoding
Cache-Control: no-cache, no-store, must-revalidate
Expires: Wed 24 Feb 1982 18:42:00 GMT
X-Frame-Options: deny
There are two ways of monitoring the Nginx reverse proxy and therefore "kind of" monitoring its number of worker connections:
Unfortunately both ways do not show the real Nginx-internal number of concurrent worker_connections. But they can help indicate when the current limits won't be enough to handle communications.
The Nginx Status page can be actively monitored with the monitoring plugin check_nginx_status. The results can be graphed and this is a helpful indicator to see whether or not Nginx will run into problems (or to detect other problems such as DDOS attacks):
By using the lsof command (netstat would be an alternative), the number of ESTABLISHED tcp connections from and to Nginx listening on ports 80 and 443 are counted:
root@nginx:~# lsof -i :443,80 | grep ESTABLISHED -c
67