Trabajos en background con script/runner

Boris, la araña, lleva ya una semana rastreando la web en busca de páginas, saltando de unas a otras a través de los hiperenlaces que encuentra… A estas alturas está cerca de las 30.000 URLs almacenadas, de las que unas 6.000 han sido exploradas en busca de meta keywords, lo que ha resultado en unas 21.400 palabras clave diferentes por el momento.

Para hacer este trabajo en background contínuo desde el servidor empleé una solución cutre-y-rápida consistente en un controlador/vista que al ser visitado, buscaba la siguiente página en cola y la exploraba. Para simular una visita a esa vista cada minuto, usaba wget desde cron, como expliqué en los comentarios de este post.

Esta técnica funciona, pero tiene sus pegas. Lo primero, no es muy elegante el usar una vista si no necesitas ver nada. Por otro lado, las llamadas a las vistas pasan a través del servidor web, así que estaba haciendo trabajar a Apache sin ser necesario. Sobre todo, lo malo es que como la operación de actualización tomaba mucho tiempo, en visitar la URL externa y procesarla, al final se podía traducir en que la parte pública de la web no estaba disponible porque tenía a todos mis apaches encargados en labores de background.

Ahora estoy probando la técnica de script/runner. Es muy sencillo, básicamente te permite ejecutar un método de un modelo, de la siguiente manera:

./script/runner -e production “Model.do_something”

El parámetro -e es para indicarle el environment, el de producción en este caso. Y entre comillas, lo que quieras ejecutar. Ahora esto lo puedes meter como trabajo cron y a correr. Por el momento va funcionando bien y se nota un aumento en la capacidad de respuesta de la web, ya que todos los apaches/fastcgi están disponibles para atender la parte pública, mientras script/runner hace su trabajo en la trastienda.

Por otro lado, he añadido un Timeout en las operaciones de red para que si una actualización dura más de 55 segundos, se aborte antes de la siguiente llamada de cron para no ir acumulando tareas y consumir recursos.

Sigo pensando en probar el plugin daemon_generator porque creo que dará mejor rendimiento que script/runner. El principal inconveniente de script/runner es que arranca toda la lógica de la aplicación Rails en cada llamada, lo cual es muy ineficiente, mientras que con daemon_generator se arranca al comienzo del demonio y éste se dedica a despertarse cada cierto tiempo para hacer sus tareas y se vuelve a dormir, pero cada vez que despierta ya tiene la lógica cargada. A ver si lo miro bien porque por lo que probé, daba problemas con mi versión de Rails.

3 comments ↓

#1 Edu on 06.01.07 at 2:09 am

Gracias Jaime por la referencia a daemon_generator. Le estoy echando un vistazo y tiene muy buena pinta, sobre todo por lo fácil que es gestionar el arranque y parada de procesos y la integración con Capistrano.

Otro que tiene muy buena pinta es el scheduler de OpenWFEru (http://openwferu.rubyforge.org/scheduler.html) que a mi me viene de perlas porque tienes mucho más control de los tiempos de ejecución de las tareas, no sólo con sleep.

La combinación de ambos puede ser explosiva :-)

Saludos!

#2 Emili Parreño on 06.05.07 at 9:08 am

Creo que con un demonio la cosa irá bastate mejor. Otra opción seria hacer una función recurrente, lo has pensado?

#3 Jaime Iniesta on 06.05.07 at 12:00 pm

Con script/runner va muy bien, aunque un demoño irá mejor sin duda…

Una función recurrente, que se llame a sí misma, o simplemente un bucle infinito? Lo malo es que si se aborta la ejecución, habría que volver a llamarla… con cron o algo… ¿no?

Leave a Comment