Nginx incluye un módulo FastCGI que tiene directivas para el almacenamiento en memoria caché del contenido dinámico que se sirve desde el backend de PHP. Al configurar esto, se elimina la necesidad de soluciones adicionales de caché de páginas, como los proxies inversos (barnish) o los complementos específicos de la aplicación. El contenido también se puede excluir del almacenamiento en caché según el método de solicitud, la URL, las cookies o cualquier otra variable del servidor.
Habilitar el almacenamiento en caché de FastCGI
Este artículo asume que ya has instalado y configurado Nginx con PHP en tu servidor linux. Edita el archivo de configuración del Virtual Host para el que se debe habilitar el almacenamiento en caché.
nano /etc/nginx/sites-enabled/vhost
Agregua las siguientes líneas a la parte superior del archivo fuera de la directiva del server {}:
fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=MYAPP:100m inactive=60m; fastcgi_cache_key "$scheme$request_method$host$request_uri";
La directiva “fastcgi cache path” especifica la ubicación de la memoria caché (/etc/nginx/cache), su tamaño (100 m), el nombre de la zona de memoria (MYAPP), los niveles del subdirectorio y el temporizador inactivo.
La ubicación puede estar en cualquier lugar del disco duro; sin embargo, el tamaño debe ser menor que la suma de memoria RAM + Swap o de lo contrario recibirá un error que dice “No se puede asignar memoria”. Veremos la opción “niveles” en la sección de purga: si no se accede a un caché durante un tiempo determinado especificado por la opción “inactive” (60 minutos), entonces Nginx lo elimina.
La directiva “fastcgi cache key” especifica cómo se codificarán los nombres de los archivos de caché. Nginx cifra un archivo al que se accede con MD5 según esta directiva.
A continuación, mueva la directiva de ubicación que pasa las solicitudes de PHP a php5-fpm. Dentro de “location ~ .php $ {}” agregua las siguientes líneas.
fastcgi_cache MYAPP; fastcgi_cache_valid 200 60m;
La directiva “fastcgi cache” hace referencia al nombre de la zona de memoria que especificamos en la directiva “fastcgi cache_path” y almacena la caché en esta área.
De forma predeterminada, Nginx almacena los objetos en caché durante un tiempo especificado por cualquiera de estos encabezados: X-Accel-Expires/Expires/Cache-Control.
La directiva “fastcgi cache valid” se utiliza para especificar la duración de caché predeterminada si faltan estos encabezados. En la declaración que ingresamos arriba, solo las respuestas con un código de estado de 200 se almacenan en caché. Otros códigos de respuesta también pueden ser especificados.
Prueba de configuración
service nginx configtest
Reinicia Nginx si todo está bien
service nginx reload
El archivo vhost completo se verá así:
fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=MYAPP:100m inactive=60m; fastcgi_cache_key "$scheme$request_method$host$request_uri"; server { listen 80; root /usr/share/nginx/html; index index.php index.html index.htm; server_name example.com; location / { try_files $uri $uri/ /index.html; } location ~ \.php$ { try_files $uri =404; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_cache MYAPP; fastcgi_cache_valid 200 60m; } }
A continuación, haremos una prueba para ver si funciona el almacenamiento en caché.
Prueba de caché de FastCGI en tu VPS
Cree un archivo PHP que genere una marca de tiempo UNIX.
/usr/share/nginx/html/time.php
Insertar
<?php echo time(); ?>
Solicite este archivo varias veces usando curl o su navegador web.
root@droplet:~# curl http://localhost/time.php;echo 1382986152 root@droplet:~# curl http://localhost/time.php;echo 1382986152 root@droplet:~# curl http://localhost/time.php;echo 1382986152
Si el almacenamiento en caché funciona correctamente, debería ver la misma marca de tiempo en todas las solicitudes, ya que la respuesta se almacena en caché.
Haga una lista recursiva de la ubicación del caché para encontrar el caché de esta solicitud.
root@droplet:~# ls -lR /etc/nginx/cache/ /etc/nginx/cache/: total 0 drwx------ 3 www-data www-data 60 Oct 28 18:53 e /etc/nginx/cache/e: total 0 drwx------ 2 www-data www-data 60 Oct 28 18:53 18 /etc/nginx/cache/e/18: total 4 -rw------- 1 www-data www-data 117 Oct 28 18:53 b777c8adab3ec92cd43756226caf618e
La convención de nomenclatura se explicará en la sección de purga.
También podemos hacer que Nginx agregue un encabezado “X-Cache” a la respuesta, indicando si se perdió la memoria caché o se presionó.
Agregue lo siguiente sobre la directiva del servidor {} :
add_header X-Cache $upstream_cache_status;
Vuelva a cargar el servicio Nginx y realice una solicitud detallada con curl para ver el nuevo encabezado.
root@droplet:~# curl -v http://localhost/time.php * About to connect() to localhost port 80 (#0) * Trying 127.0.0.1... * connected * Connected to localhost (127.0.0.1) port 80 (#0) > GET /time.php HTTP/1.1 > User-Agent: curl/7.26.0 > Host: localhost > Accept: */* > * HTTP 1.1 or later with persistent connection, pipelining supported < HTTP/1.1 200 OK < Server: nginx < Date: Tue, 29 Oct 2013 11:24:04 GMT < Content-Type: text/html < Transfer-Encoding: chunked < Connection: keep-alive < X-Cache: HIT < * Connection #0 to host localhost left intact 1383045828* Closing connection #0
Establecer excepciones de caché
Algunos contenidos dinámicos, como las páginas de autenticación requeridas, no deben almacenarse en caché. Dicho contenido puede excluirse de la memoria caché en función de variables del servidor como “solicitud uri”, ” método de solicitud ” y “http_cookie”.
Aquí hay una configuración de muestra que debe usarse en el contexto del servidor {} .
#Cache everything by default set $no_cache 0; #Don't cache POST requests if ($request_method = POST) { set $no_cache 1; } #Don't cache if the URL contains a query string if ($query_string != "") { set $no_cache 1; } #Don't cache the following URLs if ($request_uri ~* "/(administrator/|login.php)") { set $no_cache 1; } #Don't cache if there is a cookie called PHPSESSID if ($http_cookie = "PHPSESSID") { set $no_cache 1; }
Para aplicar la variable “$no_cache” a las directivas apropiadas, coloque las siguientes líneas dentro de la ubicación ~ .php $ {}
fastcgi_cache_bypass $no_cache; fastcgi_no_cache $no_cache;
La directiva “fasctcgi cache bypass” ignora la memoria caché existente para las solicitudes relacionadas con las condiciones establecidas por nosotros anteriormente. La directiva “fastcgi no cache” no almacena en caché la solicitud si se cumplen las condiciones especificadas.
Purgando la caché
La convención de nomenclatura de la memoria caché se basa en las variables que establecemos para la directiva “fastcgi cache key”.
fastcgi_cache_key "$scheme$request_method$host$request_uri";
De acuerdo con estas variables, cuando solicitamos ” http: //localhost/time.php “, los siguientes valores serían los siguientes:
fastcgi_cache_key "httpGETlocalhost/time.php";
Pasar esta cadena a través del hash MD5 generaría la siguiente cadena:
b777c8adab3ec92cd43756226caf618e
Esto formará el nombre de archivo de la caché en cuanto a los subdirectorios que ingresamos “levels = 1: 2”. Por lo tanto, el primer nivel del directorio se nombrará con 1 carácter del último de esta cadena MD5 que es e; el segundo nivel tendrá los últimos 2 caracteres después del primer nivel, es decir, 18 . Por lo tanto, toda la estructura de directorios de este caché es la siguiente:
/etc/nginx/cache/e/18/b777c8adab3ec92cd43756226caf618e
En base a este formato de nombres de caché, puede desarrollar un script de depuración en su idioma favorito. Para este tutorial, proporcionaré un script PHP simple que purga el caché de una URL POST ed.
/usr/share/nginx/html/purge.php
Insertar
<?php $cache_path = '/etc/nginx/cache/'; $url = parse_url($_POST['url']); if(!$url) { echo 'Invalid URL entered'; die(); } $scheme = $url['scheme']; $host = $url['host']; $requesturi = $url['path']; $hash = md5($scheme.'GET'.$host.$requesturi); var_dump(unlink($cache_path . substr($hash, -1) . '/' . substr($hash,-3,2) . '/' . $hash)); ?>
Envíe una solicitud POST a este archivo con la URL para purgar.
curl -d 'url=http://www.example.com/time.php' http://localhost/purge.php
El script dará como resultado verdadero o falso en función de si el caché fue purgado o no. Asegúrese de excluir esta secuencia de comandos de la memoria caché y también restringir el acceso.