Blog Archives

Carga rápida y masiva de Memcache para Nginx

Hace años escribí sobre como uso Nginx como proxy de Apache en algunas instalaciones. En esa arquitectura contemplo Memcache. La configuración es muy sencilla, basta agregar a la sección location que queramos cachear lo siguiente:

set $memcached_key $uri;
memcached_pass 127.0.0.1:11211;
error_page 404 @fallback;

Y agregar el location @fallback correspondiente:

location @fallback {
proxy_pass http://localhost:8000;
}

El único problema, como algunas personas que han usado Nginx con Memcache, es que alguien tiene que llenar Memcache con objetos para que Nginx pueda leerlos.

Usualmente, los desarrolladores de la aplicación usarán las librerías del lenguaje de programación para acceder a Memcache y cargar allí algunos objetos. Esto funciona, y es como la mayoría de la gente implementa este escenario. Sin embargo, si uno quiere cargar varios archivos de forma rápida a Memcache, no hay muchas herramientas sencillas y fácilmente disponibles.

Por ejemplo, hace dos meses en la wiki de Nginx alguien publicó un método para precargar memcache con Python. Es un enfoque interesante, pero complicado de mantener y decididamente experimental.

Sin embargo, memcache ya incluye un cliente llamado memccp que permite cargar archivos en Memcache. El problema es que este cliente no permite definir la llave con la que el objeto se almacena en Memcache. Esa llave es $uri, por ejemplo algo como /wp-content/plugins/akismet/akismet.gif.

Cuando Nginx encuentra un cliente que hace GET a este archivo, lo sirve desde Memcache, lo que en este escenario nos ahorra abrir una conexión TCP a localhost, que Apache atienda y responda una petición, y potencialmente I/O de disco.

Este parche a libmemcached permite que se defina una clave con –key, lo que facilita precargar archivos como imágenes o CSS en Memcache. Su uso es sencillo y se puede invocar desde un shell script (probado en dash)

#!/bin/sh
BASE=”/var/www/mysite”
for file in `\
find $BASE -type f \
-name ‘*.jpg’ -or \
-name ‘*.gif’ -or \
-name ‘*.png’ \
| sed “s#$BASE##”`
do
echo “Adding $file to memcached…”
sudo memccp –key=$file –servers=localhost $BASE$file
done

Entre otros escenarios que puedes activar en este caso, está el poder almacenar archivos para distintos hosts virtuales. En este caso sugiero que configures $memcached_key para usar $http_host y $uri, y añadas una variable de prefijo a tu script. También puedes correr otro memcache, si en realidad lo necesitas. memccp tiene otros problemas, por ejemplo no maneja la codificación de caracteres muy bien. Pero para archivos binarios, usualmente estáticos, ahorra bastante trabajo.

El repositorio en GitHub es un paquete fuente de Debian. Si tienes las dependencias (sudo apt-get build-dep libmemcached-tools) puedes construir el paquete (dpkg-buildpackage -b) e instalar libmemcached-tools que contiene memccp.

Este escenario es uno de los que describo en mi próximo libro rápido sobre Debian para aplicaciones Web, que está actualmente en fase de edición.

Haciendo que nginx y Apache coexistan

nginx es un producto que me ha apasionado desde hace varios años. Su enfoque orientado a eventos lo hace inherentemente distinto a otros servidores Web, y en particular Apache y Cherokee que eran los dos que tenían mi atención allá en el 2006, cuando usaba Gentoo y pasaba la noche compilando cosas.

El rendimiento de nginx es increíble, y su funcionalidad como proxy reverso HTTP es incuestionable. Lo que la gente normalmente dice es que nginx tiene muy buen performance, pero pocas funcionalidades, especialmente cuando se compara con Apache, que tiene módulos para casi cualquier cosa.

A pesar de que mi primer proyecto grande con nginx fue justamente un caso de funcionalidades (hacer un proxy IMAP) estoy consciente de esa limitante, por lo que siempre he pensado que Apache es un buen servidor Web de backend, y nginx funciona muy bien en el frontend, como proxy reverso y caché. De hecho eso se aplica para otros servidores Web, incluso no solamente de código abierto sino propietarios como IIS o WAS.

Desde hace ya varios años utilizo una arquitectura sencilla pero con muchos beneficios, donde nginx se para delante de mis servidores Apache (que sirven aplicaciones con maravillosos módulos) y hace caché con el popular motor memcached.

Básicamente, en la instancia server de nginx correspondiente, y en el location que queramos servir, colocamos algo como:

location / {                set  $memcached_key  $uri;                memcached_pass 127.0.0.1:10101;                proxy_pass http://127.0.0.1:8080/;                ...        }

Lo que hacemos es pasar a un server memcached corriendo en 10101, y utilizar un proxy reverso en 8080, que en este caso sería nuestro Apache. La URI que el cliente desea es lo que se busca en memcache como una clave, y para eso sirve la primera línea. El resto de la configuración involucra instalar y correr memcached (en Debian y derivados, aptitude install memcached) e instalar, configurar y correr Apache en el puerto que definamos; y opcionalmente protegerlo con Netfilter (iptables).

Hay dos caveats de esta solución. El primero es que si delegamos los registros en Apache, solo veremos conexiones locales. Para eso hay soluciones, como pasar algunos headers con el host apropiado y usar un módulo de Apache (RPAF) en el backend. El segundo caveat es que no queremos que todas las aplicaciones pasen por el memcached, para ello podemos abrir el puerto del Apache, o bien definir otro server en nginx y solo usar proxy_pass.

En mi escenario, memcached ocupa alrededor de 2 MB. de memoria RAM cuando no hay carga y puede crecer hasta 64 MB. cuando hay carga (es el default) lo cual es razonable en un VPS.

¿Hay algo mejor que nginx? Sí. nginx y tu servidor Web preferido.

Puntero Nulo – Episodio 5

Escúchalo:: PunteroNulo-Episodio5

La semana pasada me dijeron que el podcast era demasiado técnico. Gracias, aunque siempre intento digerir las noticias de tecnología algunos días después de que estén de moda (para no caer en la agenda) y de una forma que sea comprensible para la mayoría de la audiencia técnica.

Como siempre, sus comentarios y sugerencias son siempre bienvenidos en el correo j en bureado.com y en Twitter, @bureado.

De facto, el podcast ha estado saliendo quincenal así que mejor no engañaos. A continuación las fuentes de este episodio:

Apache/Mongrel como proxy para Puppet

Puppet es un gestor de configuraciones compuesto por un lenguaje declarativo para expresar configuraciones de sistema, un distribuidor de esa configuración y una librería para implementarla en distintos sistemas operativos. Ya había hablado sobre Puppet hace tiempo, en particular por tratarse del sistema de gestión de configuraciones propuesto para su uso en la DSLv2 de EDELCA.Asuma el lector como premisa que WEBrick no sirve (¡hola Aníbal Rojas!) y por lo tanto debe usar un proxy enfrente de puppetmasterd para poder hacer algo serio con Puppet.Puede usar varios servidores Web decentes, pero básicamente hay tres formas documentadas y probadas de hacerlo con éxito: Apache, pound y nginx.Apache y nginx son muy buenas elecciones. Si ya tiene algo operando en Apache, necesita algo específico de un módulo de Apache y no sufre de esa enfermedad que le obliga a querer poner un servidor Web distinto a Apache just for the sake of it, use Apache; el mantenedor de nginx en Debian sufre de severos problemas mentales.El problema es que, al menos en las versiones de Puppet disponibles en Lenny en su estado actual, Apache patea al puppetd de la máquina del puppetmasterd si el CRL está vacío y activa esta función, como está documentado en el reporte 1525.Como bonus, posteé ahí un snippet de configuración de Apache que funciona muy bien en un caso de referencia donde implementé Puppet con Apache como proxy, además de describir el problema de la CRL y como se soluciona comentando una línea.

Follow

Get every new post delivered to your Inbox.

Join 1,800 other followers