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.