11 de Mayo, 2012

»MDN hack day · Ah, qué lío... no tengo tiempo para nada. Mañana estaremos en el MDN hack day en Londres (Mozilla tiene unas oficinas o algo así). El programa pinta muy bien, lo que no sé es al final qué haremos con lo de hack ;).

Hay 0 comentarios, anotación clasificada en: mozilla, software libre.

7 de Mayo, 2012

»OpenID y Google Accounts · Al final resulta que fui demasiado optimista cuando publiqué la web de los crucigramas, y me ha llevado algo de tiempo implementar las cuentas de usuario. Por una parte python-openid es feo y tiene algunos fallos algo imprevisibles (por ejemplo, esta mañana me ha saltado un KeyError indocumentado... si eso no es diseñar mal un módulo, no sé qué es :D), y por otra parte había que escribir bastante JavaScript (que me gusta tanto). Al final llegamos justos para el crucigrama número 100 (yupi!), y con 18166 usuarios semanales según un crucigrama al día en Chrome Web Store.

Hay 0 comentarios, anotación clasificada en: python, django.

2 de Mayo, 2012

»Oh, ironía · Por muy contentos que estemos por dejar de depender de Flash para ciertas cosas gracias a HTML5, los fabricantes de navegadores tienen que ponerse de acuerdo en qué formatos van a ser capaces de reproducir. Si me preguntas, yo creo que H.264 no puede ser el estándar para el vídeo en la web, porque es una tecnología patentada (los problemas que vamos a tener, si es que alguna vez llega a ser legal reproducirlo en Linux). Y eso que hay gente que afirma que no pasa nada, que hay buen rollo: Motorola puede bloquear la distribución de Xbox y Window 7 en Alemania porque Microsoft incumple patentes necesarias para reproducir vídeo con H.264. ¿Y la ironía? Bueno, Microsoft ha utilizado sus propias patentes para obligar a diferentes fabricantes de móviles a pagar por cada móvil que venden con Android. Alucinante.

Hay 0 comentarios

29 de Abril, 2012

»Nautilus Flickr Uploader 0.13 · Ayer publiqué una nueva entrega de Nautilus Flickr Uploader, y es una versión de mantenimiento. He revisado los cambios para soportar OAuth y he limpiado un poco el código, principalmente eliminando dos dependencias algo raras que ya no son necesarias. Lo importante es que estés usando al menos la versión 0.11, porque las anteriores dejarán de funcionar a finales de Julio.

Hay 0 comentarios, anotación clasificada en: nautilus-flickr-uploader, perl, software libre.

25 de Abril, 2012

wsgi2cgi

Una de las pegas de nginx es que no tiene soporte para CGI (clásico), y me parece bien por la problemática que tiene en cuanto a seguridad a cambio de escaso beneficio. Además los arreglos que hay no tienen mucho de simple :).

A veces tienes que ejecutar algún CGI de forma puntual (algo así como el inetd de las aplicaciones web :P), e imagino que el camino fácil es convertir la aplicación a usar FastCGI con algún wrapper.

En realidad da un poco igual cómo, porque el proceso se tiene que ejecutar para cada petición (siendo poco eficiente), pero me he puesto y he hecho un adaptador para poder ejecutar CGIs vía cualquier servidor que entienda WSGI (como Gunicorn). El proyecto está en GitHub: wsgi2cgi.

Es bastante sencillo y tampoco le falta mucho para estar acabado, solo algunos tests que validen formalmente mis pruebas ;).

Hay 0 comentarios, anotación clasificada en: python, software libre.

22 de Abril, 2012

»Dragons of Winter Night · He terminado el segundo tomo de las Crónicas de la Dragonlance, tras leer Dragons of Autumn Twilight. En mi opinión mejor escrito, y diría que no tiene ningún momento chirriante (o al menos no tan evidente como el primer libro). Menos escaramuzas y más épica, desarrollando los personajes de Sturm y Laurana, y ya está claro que los escritores tiene preparado un futuro interesante para Raistlin. Además aparece Kitiara por primera vez, y las lanzas que dan nombre a la trilogía. Aunque es cierto que recordaba más el primer libro, este segundo tomo tiene otro ritmo, con más tensión e historia una vez que el escenario está bien definido, anticipándonos a lo que será el desenlace.

Hay 0 comentarios, anotación clasificada en: lecturas.

19 de Abril, 2012

Aplicaciones Django con nginx

Cuando trabajaba con Cherokee (que ya no, pero eso es otra historia), ponía en producción mis experimentos usando FastCGI con Django. No está mal, es una solución rápida (solo hay que instalar flup), fácil de configurar para que funcione, y a otra cosa.

Se puede ejecutar en una linea, además con un usuario sin privilegios, usando algo como:

su -c "python $PROJ_DIR/manage.py \
    runfcgi method=prefork maxchildren=10 minspare=2 maxspare=6 host=127.0.0.1 \
    port=8001 pidfile=$PROJ_DIR/run/django_fcgi.pid \
    outlog=$PROJ_DIR/log/out.log errlog=$PROJ_DIR/log/err.log daemonize=yes" $USERNAME

Así he tenido funcionando todas mis aplicaciones hechas con Django, aunque tiene algunas pegas.

Arrancar el servicio

Con Cherokee casi está resuelto: lo hace por nosotros (más o menos podemos usar la linea anterior como orden para ejecutar, sin las variables), aunque nos es óptimo porque no podemos implementar adecuadamente separación de privilegios (ejecutar el servidor web como root es malo, pero correr servidor y aplicaciones bajo el mismo usuario tampoco me convence).

Con nginx no es posible ni siquiera eso, y no hay cosa más ingrata que escribir nuestro propio script para init.d ;).

Al final he llegado incluso a usar con prisas un @reboot en el crontab del usuario ejecutando la aplicación.

Monitorización

En el caso de Cherokee está razonablemente cubierto, porque si el proceso no está disponible, lo reiniciará; pero la separación de privilegios me parece importante y ya he comentado que no es posible. Tuve mis experimentos con suidexec, pero no es la situación ideal.

Algún watchdog he hecho con BASH, en plan comprobar si el proceso sigue ahí; pero es una solución un poco en la linea del hack del crontab.

Rendimiento

Lo peor configurar FastCGI es que recuerda mucho a Apache: ¿qué valores empleamos para maxchildren, mispare y maxspare? Si no tienes mucho tráfico dará un poco igual, pero esos ajustes sumados a la carga que añade el protocolo usado por FastCGI (que a fin de cuentas lleva dando vueltas desde 1996), empieza a ser un engorro cuando corres varias aplicaciones en el mismo servidor. Al final no es una mala opción si tenemos recursos abundantes (no es el caso) o no podemos usar algo mejor.

Experimento: nginx + gunicorn + supervisor

Tenía claro que la solución no iba a venir necesariamente de un solo proyecto, así que aprovechando que estoy migrando de OVH a Memset (esto también es historia para otro día), he buscado hacer las cosas algo más ordenadas que hasta ahora.

Me he decidido por lo siguiente:

  • nginx: bueno, esto lo tenía claro. Me permite hacer todo lo que necesito, y es excelente como proxy HTTP (soportando sockets UNIX, genial para montajes locales) y sirviendo contenido estático.
  • Gunicorn: es un servidor ligero en recursos y bastante rápido, con soporte WSGI y específico para algunos frameworks (como Django). Es fácil de configurar y, aunque tiene la pega de que hay que indicar el número de workers, aporta mucho más rendimiento que FastCGI (con 2 workers es suficiente para aplicaciones con cierto tráfico).
  • Supervisor: permite lanzar las aplicaciones, con separación de privilegios y monitorización. Hay otros proyectos que pueden ofrecernos lo mismo. Este está desarollado en Python y parece potente (me he quedado en la superficie), aunque resulta muy sencillo de configurar y utilizar.

La configuración depende un poco de cómo quieras desplegar las aplicaciones, por ejemplo: usando un subdominio.

Empezamos con nginx. Trabajando con Debian, ponemos la configuaración en /etc/nginx/sites-available/app.usebox.net para luego hacer un enlace simbólico a /etc/nginx/sites-enabled/:

upstream app {
        server unix:/tmp/django-app.sock fail_timeout=0;
}

server {
	listen   80;

	server_name  app.usebox.net;
	access_log  /var/log/nginx/app.usebox.net.access.log;

	location /static {
		alias   /home/app/project/static;
	}

	location / {
	        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_redirect off;

                proxy_pass http://app;
	}
}

Para configurar gunicorn solo hay que crear un fichero Python, por ejemplo en la raíz de nuestro proyecto como gunicorn.py:

bind = "unix:/tmp/django-app.sock"  # el socket que hemos indicado en nginx
workers = 2  # se recomienda empezar con cores+1, y luego ir ajustando
django_settings = 'project.settings'  # el projecto Django se llama project
pythonpath = '/home/app/'  # directorio superior a donde instalamos la app

Finalmente escribimos la configuración del proceso en supervisor, que en Debian va en /etc/supervisor/conf.d/, por ejemplo app.conf:

[program:app]
command=/usr/bin/gunicorn_django -c /home/app/project/gunicorn.py
directory=/home/app/project/
user=app
autostart=true
autorestart=true
redirect_stderr=true

En Debian el supervisor se ejecuta como root al arranque del sistema, con lo que puede ejecutar los procesos con el usuario que indiquemos (app en este ejemplo).

Solo hay que recargar la configuración de nginx y ejecutar algo como un supervisorctl reload.

Con supervisorctl podemos ejecutar operaciones sobre la aplicación, como por ejemplo:

# supervisorctl status app
app                     RUNNING    pid 11682, uptime 1:42:01

Están disponibles las típicas órdenes para gestionar los procesos (stop, start, restart, etc), y en /var/log/supervisor/ tenemos logs que pueden ser bastante interesantes (sobretodo si tenemos algún problema configurando el invento, porque captura la salida de gunicorn).

He llamado la propuesta experimento porque estoy en pruebas, aunque si no hay problemas, parece una solución definitiva y mucho más mantenible y ordenada que lo que venía haciendo hasta ahora ;).

Hay 4 comentarios, anotación clasificada en: python, django.

15 de Abril, 2012

»Puntos y comas · Aprende a usarlos adecuadamente. No puedo estar más de acuerdo con este comentario épico de Douglas Crockford. Igual se puede considerar una funcionalidad del lenguaje, siempre puedes decirle a alguien que está equivocado. Por si acaso, me guardo esta imagen para uso futuro (imagen original CC: by-nc-sa, Douglas Crockford by Eric Miraglia).

Hay 0 comentarios, anotación clasificada en: javascript.

13 de Abril, 2012

»Pyscho Killer · Iba a convocar una nueva edición de adivina la canción, pero como últimamente no tienen nada de éxito, hemos publicado directamente nuestra versión de Psycho Killer de Talking Heads. Además ahí, en el pueblo fantasma la red social de Google. De todas formas, por los viejos tiempos, aquí la tienes en formato ogg.

Hay 0 comentarios

10 de Abril, 2012

¿Qué español hablas?

Mi web para hacer crucigramas está funcionando mejor de lo que imaginaba, sobretodo gracias a su entrada en la Chrome Web Store (se llama Un Crucigrama al Día, original... ¿no?).

También funciona en Firefox, y no veo porqué no debería hacerlo en otros navegadores modernos que respeten los estándares ;) (sospecho que hasta en IE9 podría funcionar), pero me parece que su único punto de entrada es el web store de Google, que dice que hay 14806 usuarios semanales en este momento.

Esa cifra ya no está subiendo como hace unas semanas, ni el número de visitas diario ha variado demasiado en todo el periodo.

Mirando las estadísticas de acceso, la mayor parte del tráfico se reparte entre España, México y Argentina; lo que me lleva al principal problema que creo que tiene este tipo de aplicaciones.

Hay una cita muy conocida de Winston Churchill refiriéndose a los americanos y los brítánicos, que dice que eran dos naciones divididas por un idioma común. En el caso del Español (castellano), ¡son muchas más naciones!

He mejorado significativamente el algoritmo que genera los crucigramas (los de las últimas dos semanas utilizan la versión mejorada, y se nota la diferencia), y le he dedicado mucho tiempo a intentar limitar la aparición de localismos o palabras de ámbito específico, pero es realmente difícil y no creo que consiga llegar a un nivel de refinamiento suficientemente alto.

En primer lugar no todas las entradas del Wikcionario referidas a dichos localismos están clasificadas adecuadamente, y en segundo lugar... ¿a qué ámbitos son a los que queremos dar prioridad?

Mi primera idea fue dar prioridad a los ámbitos relativos a España, pero enseguida me di cuenta que estaba completamente equivocado: el tráfico que viene del continente americano triplica el que viene de la península. Imagino que preguntar a un Colombiano por el gentilicio de los que viven en Jaén no es nada fácil :P.

Al final he intentado llegar a un compromiso en el que es posible que hayan 2 o 3 definiciones que van a chirriar independientemente dónde te encuentres (una expresión española por una palabra de uso común en Chile, por un término despectivo usado en Argentina, por ...). De esta forma quizás los crucigramas sean interesantes para cualquiera, independientemente de qué español sea el que hable.

Hay 1 comentario

Entradas antiguas