Que es Varnish
Funcionalidades
- Equilibrio de Carga
- Reescritura de URL
- Comprobación de Backends
- Manejo elegante de backend muertos
- Soporte parcial para ESI(Edge Side Includes)
Arquitectura
- Caché monolítica mapeada a memoria virtual
- Archivos configuración compilados en C
- Trata todo el ciclo de vida de una petición
- Cambios de configuración en caliente
- Logs escritos en memoria compartida
Herramientas
Compilación de Varnish 4.1 en CentOs7
Para poder compilar sin problemas debemos tener instalados los siguientes paquetes:
Vamos al directorio de repositorios y creamos el nuestro para Varnish
/etc/yum.repos.d/
Creamos el archivo varnishcache_varnish41.repo con el siguiente contenido:
[varnishcache_varnish41]
name=varnishcache_varnish41
baseurl=https://packagecloud.io/varnishcache/varnish41/el/6/$basearch
repo_gpgcheck=1
gpgcheck=0
enabled=1
gpgkey=https://packagecloud.io/varnishcache/varnish41/gpgkey
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300
[varnishcache_varnish41-source]
name=varnishcache_varnish41-source
baseurl=https://packagecloud.io/varnishcache/varnish41/el/6/SRPMS
repo_gpgcheck=1
gpgcheck=0
enabled=1
gpgkey=https://packagecloud.io/varnishcache/varnish41/gpgkey
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300
Procedemos a la instalación:
sudo yum -q makecache -y –disablerepo=’*’ –enablerepo=’varnishcache_varnish41′
Configuración Varnish
Parámetros de Arranque
Funciones Varnish – Rutinas
Cuando una petición HTTP llega a Varnish, éste la procesa llamando a las diferentes rutinas en un orden concreto, y se ejecuta el código que hay dentro de dichas subrutinas. Ese código puede ser el código por defecto de Varnish o bien código personalizado por nosotros.
De estas rutinas las que más vamos a usar son: vcl_recv() y vcl_fetch(), aunque vamos a ver todas las opciones disponibles:*
- vcl_recv() >Cuando se recibe una petición HTTP Varnish lanza esta subrutina. Nos permite decidir si la aceptamos o no, cómo hacerlo y que backend usar.
- vcl_fecth() >Se ejecuta después de haber obtenido del backend HTTP los datos solicitados, después de haberse acepta la petición de vcl_recv().
En todas las funciones podemos realizar diferentes acciones, para ello tenemos la función return() con las diferentes acciones dentro de ella:
- pass ->Si para la petición en curso devolvemos pass, la peticiÃşn se envia al servidor Backend sin buscarse en la caché y la respuesta del backend http se devuelve al usuario sin cachearse.
- pipe ->Esta acciÃşn çortocircuita. el cliente HTTP y el Backend HTTP de forma que Varnish se limita a transferir datos de uno a otro. Es similar a pass (no se cachea) y ademÃąs Varnish no se dedica a inspeccionar el trÃąfico HTTP ni rellenar los objetos req/beresp/obj por lo que a veces se utiliza para evitar que objetos muy grandes (vÃŋdeos, etc) sean «procesados»por varnish.
- lookup ->Fuerza a Varnish a que devuelva el objeto desde la caché incluso si la petición en sí mísma está solicitando contenido no cacheado.
- deliver ->Le indica a Varnish que queremos devolver el objeto cacheado si es posible.
- hit_for_pass ->Similar a pass (pero accesible desde vcl_fetch) salvo porque crea un objeto de tipo hitforpass y lo que se hace en este caso es cachear la decisión de no cachear.
- restart ->Una forma de volver a ejecutar la lógica desde el principio.
- vcl_hash() >Permite alterar el hash que se utiliza para gestionar el objeto en la cachÃľ. Normalmente es la URL pero podemos alterar dicho hash a nuestra voluntad. Un ejemplo sería cachear la página del perfil (/profile/) de cada usuario, aÃśadiendo concatenando la cookie de usuario a la URL, lo que generaría un objeto distinto en cada para cada usuario.
- vcl_pipe() >Modo Pipe
- vcl_pass() >Podemos forzar a que se reinicie la transacción, lo cual incrementa un contador interno de restart»que podemos detectar en otras funciones.
- vcl_hit() >Llamada cuando lookup en la caché encuentra un objeto válido.
- vcl_miss() >Es llamada cuando lookup no encuentra un objeto válido.
- vcl_error() >LLamada cuando se encuentra un error por cualquier motivo.
- vcl_deliver() >Es llamada antes de que un objeto cacheado sea entregado al cliente HTTP.
Configuración Caché
Tenemos el fichero /etc/varnish/default.vlc
Varnish y WordPress
vcl 4.0;
import std;
# Default backend definition. Set this to point to your content server.
backend default {
.host = «127.0.0.1»;
.port = «8080»;
}
#Backend net-lz.com
backend netlz {
.host = «127.0.0.1»;
.port = «8080»;
}
#Backend gamesranking.info
backend gamesranking {
.host = «127.0.0.1»;
.port = «8080»;
}
#Backend trailersdecine.com
backend trailersdecine {
.host = «127.0.0.1»;
.port = «8080»;
}
sub vcl_recv {
#Control para ver que backend utilizar
if (req.http.host == «www.net-lz.com» || req.http.host == «net-lz.com»){
} elseif (req.http.host == «www.gamesranking.net» || req.http.host == «gamesranking.net»){
} elseif (req.http.host == «www.trailersdecine.com» || req.http.host == «trailersdecine.com»){
}else {
}
#Si la petición es para 443 nos aseguramos que lo marqué en las cabeceras HTML
}
#Tipos de codificaciones aceptadas
if (req.http.Accept-Encoding) {
# remove req.http.Accept-Encoding;
set req.http.Accept-Encoding = «gzip»;
} elsif (req.http.Accept-Encoding ~ "deflate") {
set req.http.Accept-Encoding = «deflate»;
#remove req.http.Accept-Encoding;
}
}
#Consultas archivos multimedia
if (req.url ~ «wp-content/themes/» && req.url ~ «\.(gif|jpg|jpeg|swf|css|js|flv|mp3|mp4|pdf|ico|png)(\?.*|)$») {
unset req.http.cookie;
set req.url = regsub(req.url, "\?.*$", "");
}
#Consultas a otro tipos de archivos
if (req.url ~ «\?(utm_(campaign|medium|source|term)|adParams|client|cx|eid|fbid|feed|ref(id|src)?|v(er|iew))=») {
set req.url = regsub(req.url, "\?.*$", "");
}
# no cacheamos las cookies de administrador
# soluciona la redirección que se generaba al querer entrar como administrador
if (req.http.cookie) {
if (req.http.cookie ~ «(wordpress_|wp-settings-)») {
return(pass);
} else {
unset req.http.cookie;
}
}
#Desactivamos la cache para esta url
if (!(req.url ~ «wp-(login|admin)»)) {
unset req.http.cookie;
}
#No cacheamos cookies específicas de wordpress
set req.http.cookie = regsuball(req.http.cookie, «wp-settings-\d+=[^;]+(; )?», «»);
set req.http.cookie = regsuball(req.http.cookie, «wp-settings-time-\d+=[^;]+(; )?», «»);
set req.http.cookie = regsuball(req.http.cookie, «wordpress_test_cookie=[^;]+(; )?», «»);
#No cacheamos cookies en general
if (req.http.cookie == «») {
unset req.http.cookie;
}
#Pasamos sin cacheo las url con wp-admin y wp-login
if (req.url ~ «wp-admin|wp-login») {
return (pass);
}
}
#fin vcl_recv
sub vcl_backend_response {
set beresp.ttl = 10s;
set beresp.grace = 1h;
}
#Marcamos que debemos guardar cómo estadísticas
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = «HIT»;
} else {
set resp.http.X-Cache = «MISS»;
}
return (deliver);
}
Podríamos añadir una configuración para permitir la opción purge desde diferentes sitios, este no se ha hecho debido a que tenemos instalado un plugin en la red multisite de worpdress que nos ofrece esta funcionalidad y la configuración Varnish ha sido diseñada con esta objetivo. Ver: https://varnish-cache.org/trac/wiki/VCLExamples
Configuración Varnish especiales
REMOTE ADDRESS PHP
Para que PHP pueda capturar las Ip de los usuarios que se conectan debemos añadir algunos cambios al archivo default.vcl de varnish.
Añadimos la siguiente configuración dentro del la subrutina vcl_recv:
#Control Varnish para que PHP puede devolver las IP de los usuarios que se conectan
if (req.restarts == 0) {
if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For =
req.http.X-Forwarded-For + «, » + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
Ahora nos faltará 2 procesos, añadir unas líneas al Vhost de correspondiente y crear un fichero php que se encargará de asegurarnos que cojamos la ip buena.
Vhost de ejemplo:
<VirtualHost *:8080>
DocumentRoot «/web/wordpress/static/trailersdecine»
ServerName trailersdecine.com
ServerAlias www.trailersdecine.com
<Directory /web/wordpress/static/trailersdecine>
#Linea para Varnish
php_value auto_prepend_file «/www/conf/sites/varnish_client_ip.php»
AllowOverride All
Order deny,allow
Allow from all
</Directory>
CustomLog logs/common.trailersdecine combined
ErrorLog logs/error.trailersdecine
#Linea y log para varnish
LogFormat «%{X-Forwarded-For}i %l %u %t \»%r\» %>s %b \»%{Referer}i\» \»%{User-Agent}i\»» varnish
# Other directives here
</VirtualHost>
Como podéis observar dentro de Directory podemos ver como se hace una llamada al archivo varnish_client_ip.php, vamos a crearlo con el siguiente cotenido:
<?phpif( isset( $_SERVER[ ‘HTTP_X_FORWARDED_FOR’ ] ) ) {
$_SERVER[ 'REMOTE_ADDR' ] = $_SERVER[ 'HTTP_X_FORWARDED_FOR' ];
}
?>
Con tal de no parar el servicio vamos a recargar ambos
service varnish reload
/www/bin/apachectl stop
/www/bin/apachectl start
Ya tenemos nuestro servicio ce cacheo listo
MOD HEADERS
Con tal de controlar las cabeceras que viene de http y https y permitir el trasposo de archivos multimedia entre estos dos protocolos debemos añadir configuración tanto a Varnish como en Apache.
Varnish mod_headers.
Configuración Apache para Varnish
Como Varnish está a la escucha en el puerto 80, debemos indicarle a Apache que escuche en otro puerto, en este caso el 8080.
#Puertos de escucha
Listen *:8080
Listen *:443
#Módulos necesarios
LoadModule proxy_modulemodules/mod_proxy.so
LoadModule proxy_balancer_modulemodules/mod_proxy_balancer.so
LoadModule proxy_http_modulemodules/mod_proxy_http.so
LoadModulos mod_ssl
#NameVirtualHost
Este paso no es estrictamente necesario
NameVirtualHost *:8080NameVirtualHost 217.13.124.73:443
Virtualhost para sitios sin SSL
<VirtualHost *:8080> DocumentRoot «/web/wordpress/static/trailersdecine» ServerName trailersdecine.com ServerAlias www.trailersdecine.com <Directory /web/wordpress/static/trailersdecine> AllowOverride All Order deny,allow Allow from all </Directory> CustomLog logs/common.trailersdecine combined ErrorLog logs/error.trailersdecine # Other directives here</VirtualHost>
Es una configuración típica excepto con los puertos de escucha y con el puerto de escucha a la hora de configurar el Vhost: 8080.
Varnish y HTTPS
Varnish no soporta HTTPS, no podemos configurar Varnish para que escuche el puerto 443 simplemente.
Para solucionar este problema debemos configurar el virtualhost de la siguiente manera:
Enlaces de referencia