NGINX: Mejorar el rendimiento con la caché

Buenas, hoy vengo a traeros un post sobre como mejorar el rendimiento de un site, solamente utilizando la caché de nginx. Esto viene perfecto para solventar problemas de cargas de backend. Es especialmente útil en aplicaciones de lenguaje interpretado como php o ruby. Y una alternativa muy interesante a herramientas como varnish.

Nginx como servidor proxy caché

Vamos a poner un ejemplo, tenemos un servicio que cada vez que se le hace una petición, tarda entre 7 y 12 segundos en responderla. Por lo que si en un momento dado, se realizan varias peticiones concurrentes, puede llegar a colapsar el servidor interrumpiendo el servicio. También contamos con la problemática que el contenido de del aplicativo cambia cada poco tiempo, por lo que no nos interesa tener una caché muy grande. Para esto, vamos a implementar el concepto de micro-caché.

Si realizamos un benchmark del site antes de implantar la caché, podemos obtener los siguientes resultados

ab -n 1000 -c 5 https://example.com/
Server Software:        nginx
 Server Hostname:        example.com
 Server Port:            443
 SSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-AES128-GCM-SHA256,2048,128
 Document Path:          /
 Document Length:        514442 bytes
 Concurrency Level:      5
 Time taken for tests:   1632.410 seconds
 Complete requests:      1000
 Failed requests:        857
   (Connect: 0, Receive: 0, Length: 857, Exceptions: 0)
 Total transferred:      515275643 bytes
 HTML transferred:       514448515 bytes
 Requests per second:    0.61 #/sec
 Time per request:       8162.048 ms
 Time per request:       1632.410 [ms] (mean, across all concurrent requests)
 Transfer rate:          308.26 [Kbytes/sec] received
 Connection Times (ms)
              min  mean[+/-sd] median   max
 Connect:      111  116  46.5    113    1158
 Processing:  4683 8037 4220.3   6394   40880
 Waiting:     4061 7530 4217.6   5883   40042
 Total:       4796 8153 4221.1   6510   409

Como se puede ver, los resultados del benchmark, dejan mucho que desear. En resolver todas las peticiones, ha tardado casi 30 minutos y ha fallado casi en el 90% de las peticiones ya sea por carga o por time-out.

Time taken for tests:   1632.410 seconds
Complete requests: 1000
Failed requests: 857

Para solucionar esto, vamos a habilitar la opción de proxy_cache de Nginx y volver a realizar un benchmark para comprobar los resultados.

Para esto, se necesita una versión de igual o superior a Nginx:1.11.10

Primero, se declara el path de la caché y se le da un nombre. En este caso se llamará cache. ¿Original no?. Y se le puede indicar el path para guardar los elementos cacheados temporales.

vim /etc/nginx/nginx.conf
proxy_cache_path     /var/www/cache levels=1:2 keys_zone=cache:8m max_size=1000m inactive=600m;
proxy_temp_path /var/www/cache/tmp;

Una vez hecho eso, hay que ir al site que queremos configurar y añadir en el location que queramos cachear lo siguiente:

location / {
proxy_buffering on;
proxy_cache cache;
proxy_cache_key "$scheme$host$proxy_host$request_uri $cookie_location";
proxy_set_header Host $host;
add_header X-Proxy-NGINX-Cache $upstream_cache_status;
proxy_ignore_headers "Set-Cookie";
proxy_cache_lock on;
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
proxy_cache_valid 200 301 302 15s;
proxy_pass http://unicorn_https;
}

La info de los módulos disponibles de nginx, se puede ver aquí.

Reiniciamos nginx

systemctl restart nginx

Y vamos a volver a lanzar el mismo benchmark para comprobar los resultados.

ab -n 1000 -c 5 https://example.com/

Server Software: nginx
Server Hostname: example.com
Server Port: 443
SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES128-GCM-SHA256,2048,128
Document Path: /
Document Length: 514462 bytes

Concurrency Level: 5
Time taken for tests: 94.333 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 515315001 bytes
HTML transferred: 514462000 bytes
Requests per second: 10.60 #/sec
Time per request: 471.665 ms
Time per request: 94.333 [ms] (mean, across all concurrent requests)
Transfer rate: 5334.69 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 111 113 1.4 113 139
Processing: 221 357 172.3 295 2267
Waiting: 37 49 135.4 38 2044
Total: 333 470 172.6 408 2386

Ahora se puede observar que el rendimiento ha mejorado notablemente.

Time taken for tests:   94.333 seconds
Complete requests: 1000
Failed requests: 0

Resumiendo, la caché de Nginx, es una opción de caché perfectamente válida para sacarnos de un apuro. Si bien es cierto que no es tan configurable como Varnish, puede cubrir la mayoría de necesidades.


Also published on Medium.

One comment

Leave a Reply

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *