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