Cuando un cron mata un servidor

November 18, 2015

Desarrolladores  Off topic  PHP 


Había una vez, un ingeniero en sistemas que estaba teniendo un problema con su proveedor de servicio de internet, y quiso generar pruebas de esto porque no aceptaban sus reclamos.

El título de la entrada y ese primer párrafo son el TL;DR de esta historia, que contiene varios ingredientes que se unen, para terminar con la caída de un servidor de hosting gratuito - Por esto, chicos, un hosting gratuito no es siempre una buena opción.

Trasfondo

En una época de mi vida, antes de decidirme a hacer esta start-up, y antes de trabajar en empresas de desarrollo de software, era un desarrollador freelance a tiempo completo. Esto implicaba que debía poseer una conexión a Internet lo suficientemente estable y rápida para poder estar conectado a los servidores que mantenía y en los que terminaban alojados los sitios y sistemas que desarrollaba.

Poseer una conexión de 3mb era todo un lujo, lo normal era 1mb en la ciudad, y la diferencia de precio era sustancial.

En San Luis capital, ubicado al centro de Argentina, donde muchos se jactaban de tener un servicio de internet gratuito, la velocidad de conexión promedio no superaba los 512kbps y el acceso a la misma no era tan buena como se vendía, llegando a tener 100 clientes conectados por antena.

Esto no era un servicio deseable para un desarrollador freelance, que necesitaba una conexión estable para poder estar conectado con sus clientes, servidores y fuentes de información, por lo que todo ese grupo, o personas que podían permitírselo y consideraban aceptable el precio a pagar, contrataban un servicio pago.

Si bien existían varios proveedores privados (En realidad, eran 3), sólo había 2 que ofrecían un servicio decente a un precio no exorbitante, yo opté por el mejor de esos: 3mb a un precio de $400 al mes, teniendo en cuenta que en esa época, el sueldo promedio estaba en los $4000, era algo que no todos veían como aceptable para un consumo familiar.

El problema

Como mencioné antes, la conexión no era precisamente barata, y como la propaganda, que también resultaba ser su lema, era "Disponibilidad los 365 días del año", era de esperar que cuando su servicio fallara por más de 2 horas seguidas, el primero en llamar fuese yo.

En este caso particular, el servicio había estado funcionando de forma intermitente durante 2 días y ya estaba afectando mi trabajo, lo interesante fue que al llamar y consultar, tuvieron el descaro de decirme "Nosotros vemos el servicio funcionando de forma normal, si no tenés pruebas, no hay mucho que podamos hacer".

Siendo más que un simple usuario, opté por lo más lógico, crear evidencias de la falla del sistema. Afortunadamente, entre las características del servicio que había contratado, estaba el beneficio de tener una IP pública, y esto fue lo que terminé aprovechando al máximo. Necesitaba controlar de alguna forma los lapsos en los que el servicio estuviese caído, por lo que conseguí un hosting gratuito que me ofrecía la posibilidad de agregar un cron que cada cierto tiempo hiciera un llamado cURL a un simple script alojado en mi PC.

Creando y ejecuando el script

El script encargado de controlar el estado de mi conexión intentaba recuperar ese archivo local y en caso de fallar insertaba un registro en una base de datos, esto debía hacerse cada 1 minuto para tener un control exacto de los momentos en los que fallase porque las interrupciones a veces eran de 1 hora, a veces de 30 minutos, y a veces de 1 minuto.

Luego hice otro archivo en ese mismo servidor que se encargaba de recuperar esos datos y mostrar los períodos de tiempo en los que el servicio estaba cortado y que fuese accesible desde cualquier lugar, esta era mi prueba.

La validación de un campo no sólo debe hacerse desde el lado del cliente sino también desde el servidor, el cliente puede hacer cualquier modificación si tiene un mínimo de idea.

Al probar ese script a mano funcionaba todo perfecto, el problema apareció cuando intenté crear el cron de 1 minuto para que lo ejecutase. Al ser una cuenta gratuita, sólo podía crear un cron que iba a funcionar cada 1 hora, esto no era aceptable para mi caso y tiraba por el piso la idea del control cada minuto.

Plan A (bis): Inspeccionar el código fuente de la página y encontrar una forma de modificar el cron para que se ejecute cada 1 minuto.

Una de las cosas más interesantes de este servicio de hosting, era que en su momento utilizaba un panel de control propio en vez de utilizar uno que hubiese sido creado específicamente para eso (Como cPanel) y tenía ciertos detalles que podían ser explotados, como terminé haciendo.

Grande fue mi sorpresa al ver que las opciones que tenía disponible para seleccionar el tiempo del cron contenían de forma literal la cadena a utilizar, probé reemplazando ese valor por * * * * * et voilà, el cron ya estaba funcionando cada 1 minuto.

Esto funcionó perfectamente durante un día, luego me llegó un mail avisándome que se había suspendido el cron por violar los términos de mi cuenta, pero fueron lo suficientemente amables como para no cancelarla.

Plan B: Utilizar un cron cada 1 hora que controle e inicie un script que no va a finalizar su ejecución y controla cada 30 segundos el estado de mi conexión.

Cuando alguien dice que el ingenio humano no tiene límites, está totalmente en lo cierto. Mi nuevo script no sólo iba a ejecutarse de forma indeterminada, sino que además tenía un cron que lo volvía a iniciar si no estaba en funcionamiento.

El código era básicamente así:

$beingExecuted = false;

...
// Control de estado de ejecución del script
...

if (!$beingExecuted) {  
    do {
        if(!hostIsActive()) {
            addNonActiveEntry();
        }

        sleep(30);
    } while (true);
}

El funcionamiento nuevamente era impecable y podía ver cómo el proceso estaba controlando el estado de mi conexión. Lo entretenido vino después, porque si bien mi script funcionaba, tenía un único detalle menor: En ningún momento notificaba que el script se había iniciado y estaba en ejecución, por lo que el próximo cron que controlara su estado no iba a encontrarlo, y en consecuencia iba a crear un nuevo proceso PHP.

Esto estuvo funcionando así durante 1 semana, y todavía no entiendo por qué no lo detectaron antes si el cron lo encontraron y sacaron en 1 día.

El resultado

Con 3 días de reportes, la prueba contra el mal funcionamiento del servicio era innegable. Conseguí que dos técnicos que sólo sabían hacer ping a su servidor central para controlar el funcionamiento vinieran a casa y terminaran rehaciendo la conexión y cambiando el módem, la ejecución del ping tuve que hacerla yo mismo porque no habían visto un entorno Linux antes.

Obviamente, cuando estuvo todo funcionando, me olvidé que el script seguía en ejecución generando mi preciado reporte.

Luego de ese episodio volví a mi vida normal, olvidándome que el script seguía cumpliendo su deber, controlando si mi conexión funcionaba como correspondía. Al séptimo día vi cómo mi casilla de email de servicios que utilizo una única vez había estado inundándose con correos diciendo que:

  • Estaba consumiendo más recursos de los disponibles.
  • Estaba consumiendo el tiempo de procesamiento de otros usuarios.
  • Mi utilización de la base de datos había superado un 30%.
  • El procesador de los servidores estaba siendo utilizado demasiado por mis procesos.
  • Debía suspender los procesos de forma inmediata o mi cuenta iba a ser suspendida.
  • Era la última advertencia y que iba a necesitar pagar para poder recuperar la cuenta.
  • La cuenta había sido suspendida.
  • Los procesos seguían ejecutándose.
  • El servidor se había bloqueado debido a la cantidad de procesos.
  • Los procesos habían sido terminados.
  • La cuenta había sido bloqueada.

Todo en ese orden de severidad. Obviamente envié un mail pidiendo disculpas por haber causado tanto daño, pero no obtuve respuesta por parte de ellos.

Moraleja

Los servicios de hosting gratuito son aceptables para proyectos personales pero no para una página que espera poseer un tráfico considerable (Más de 10 personas por hora) porque los recursos son compartidos y no son tan altos como puede ser un hosting pago.

Cuando se cree un script que debe ser iniciado o controlado por un cron, antes de subirlo a producción, hay que controlarlo en el entorno local.

Por último, si tenés un proyecto personal, ya sea un sitio, una aplicación web, o tal vez una aplicación móvil, no dudes en ponerte en contacto con nosotros a contacto@cign.io, y te armamos un presupuesto acorde a tus necesidades sin cargo.

¡Hasta la próxima!