2010-11-12 22 views
8

Supongamos que está escribiendo un daemon que sirve una cola de trabajos. Varios otros programas escriben trabajos para el daemon en la cola. El daemon sondea la cola cada pocos segundos para trabajos pendientes. Supongamos que la cola se implementa como una tabla en una base de datos MySQL y que el demonio es un bucle simple:Cómo diseñar un daemon con una conexión de base de datos MySQL

  1. obtener todos los puestos de trabajo debido de la cola
  2. hacer los trabajos
  3. sueño durante N segundos
  4. Goto 1

el demonio debe sobrevivir servicio interrumpido desde el servidor de base de datos MySQL y la interrupción de las conexiones de base de datos.

¿Diseñarías el daemon para conectarte al servidor de bases de datos una vez por ciclo? es decir, ¿conectar antes de 1. y desconectar entre 2 y 3?

¿O tendrías daemon para mantener una conexión abierta? En ese caso, también necesita a) detectar cuando el servidor o la conexión no funcionan, b) desconectarse y reconectarse, yc) hacerlo sin acumular conexiones de DB, descripciones de conexiones falsas u otros recursos muertos.

Si tiene una preferencia, ¿por qué?

Pros y contras?

¿Factores que entran en el diseño?

¿Algún otro enfoque?

La respuesta aquí: mysql connection from daemon written in php no dice por qué es mejor mantener la conexión abierta. Leí en otro lado que la sobrecarga por conexión en MySQL es muy ligera. Por lo tanto, no es obvio por qué consumir permanentemente una conexión de servidor es mejor que conectar/desconectar cada pocos segundos.

En mi caso, el daemon está escrito en PHP.

+0

¿Qué es lo que estás tratando de hacer? Dependiendo del caso, parece que un archivo FIFO o un socket podría ser mejor para desencadenar el daemon ... (Y lo que haría sería volver a crear la conexión cada intervalo de sondeo, pero de nuevo no estaría sondeo cada pocos segundos) ... – ircmaxell

+0

@ircmaxell: una FIFO no es conveniente en mi caso porque los procesos que colocan trabajos en la cola necesitan poder leerlos y porque el estado de la cola de trabajos necesita sobrevivir al reinicio del servidor. La replicación de MySQL de la cola también es útil. –

+0

No quise pasar todos los datos a través de un FIFO. Solo para activar el daemon para leer desde la cola basada en mysql. Entonces, básicamente, 'INSERT INTO queue VALUES (job) ', luego' file_put_contents (' fifo.file ',' 1 '); '. El daemon dormiría tratando de abrir el fifo. Entonces, si se termina de procesar todo, básicamente se bloqueará en 'fopen ('fifo.file', 'r');'. La próxima vez que un proceso se agrega a la cola, simplemente notifica al daemon, que inmediatamente comienza a procesar el trabajo. Pero mientras duerme, no consume ningún recurso, ya que es una llamada al sistema que bloquea (incluso durante horas). – ircmaxell

Respuesta

7

En realidad estoy trabajando en something muy cerca de lo que describiste, pero en mi caso el daemon no sondea para el caso de que los obtenga asincrónicamente a través de XMPP (pero eso es más que el punto).

Cortar el intermediario

Creo que en lugar de almacenar los eventos en la base de datos y encuestas de ellos w/MySQL que probablemente podría utilizar Gearman para enviarlos desde el cliente de forma asíncrona (example).

recolección de elementos

PHP no es realmente diseñado para funcionar como un demonio, y no fue hasta PHP 5.3 cuando se hizo circular reference garbage collection que se convirtió en una opción viable. Es muy importante que utilice PHP 5.3 si desea alguna posibilidad de funcionamiento a largo plazo sin pérdidas de memoria.

Otra cosa a tener en cuenta acerca de GC es que la memoria es sólo libre si no está ya referenciado (en cualquier lugar). Entonces, si asigna una variable al alcance global, estará allí hasta que salga el daemon. Es importante que cualquier código que cree o use no genere variables en lugares (es decir, registro estático, sin eliminar datos antiguos, etc.).

Stat caché

Otra cosa es que es importante ejecutar clearstatcache de vez en cuando. Debido a que su proceso de PHP no se reinicia, es importante hacer esta llamada manualmente para evitar la obtención de datos de estadísticas antiguas (que pueden afectarle o no). De acuerdo con el documentation estas funciones están en caché.

funciones afectadas incluyen stat(), lstat(), file_exists(), is_writable(), is_readable(), is_executable(), is_file(), is_dir(), is_link(), filectime(), fileatime(), filemtime(), fileinode(), filegroup(), fileowner(), filesize(), filetype() y fileperms().

gestión de recursos

Si vas a estar usando algo como MySQL durante la vida de su proceso, sugeriría hacer una conexión en el arranque y mantenerla viva. Aunque podría usar más ram en el lado de MySQL, reducirá la latencia y la sobrecarga de la CPU al no tener que conectarse cada 1 segundo.

Sin solicitud de URL

Esto puede parecer obvio, pero con PHP CLI no hay ninguna solicitud de URL información. Algunas bibliotecas no se escriben con esto en mente, y esto puede causar algunos problemas.

LooPHP

voy a estallar un enchufe descarado en aquí para un marco que escribí para ayudar en la gestión de los demonios de PHP. LooPHP es un marco bucle de ejecución que le permite programar eventos a suceder o crear escuchas para las fuentes abstractas (zócalo, corriente, etc.). En mi caso, tengo el demonio haciendo más de 1 cosa, por lo que es muy útil contar con sistema de seguimiento de todos los contadores de tiempo para mí, así que puedo sondear con eficacia stream_select para la conexión XMPP.

+0

Ese es un comentario muy útil, Kendall. ¡Gracias! Estoy bastante seguro de que no tengo referencias circulares pero me estoy ejecutando en 5.3.3, así que está bien. No usa 'stat', pero ese es un buen punto general. No es una pena compartir LooPHP solo porque lo escribiste. Es más de lo que necesito ahora, pero tengo otro proyecto en el horizonte que podría resultarle muy útil. –

+0

@fsb ¿Cómo está poniendo trabajos en la cola? Vale la pena mirar a Gearman (mi primer punto). Resume una gran cantidad de procesamiento de cola para usted. –

+0

Como dije en el OP, la cola es una tabla MySQL. Entonces, los trabajos se ponen con INSERT. –

0

Creo que lo mejor que puede hacer es medir el tiempo que lleva conectarse/desconectarse de la base de datos. Luego trate de encontrar algún tipo de probabilidad de que el servidor de la base de datos deje de estar disponible. Determine el costo de una conexión de servidor permanente. Y finalmente, trate de determinar el costo (en horas, molestia, o lo que sea) de agregar código que trate con problemas de conectividad a la base de datos. Si puede determinar con éxito esos números y compararlos, tiene una respuesta. Me resulta difícil (y supongo que a nadie) proponer buenas estimaciones para esos valores, pero la conclusión probablemente sea que es una elección entre el rendimiento y la viabilidad (en términos de menor costo).

+0

Un estudio cuantitativo concluyente de los costos de recursos del servidor en relación con las dificultades de diseño del daemon me va a costar más que las tarifas de alojamiento del servidor ;-) –

+0

@fsb, jaja, estoy seguro de que tiene razón. ¿Y aún confía en que no se está micro optimizando o preocupándose por un problema que no tiene? –

1

Si desea realizar un demonio fiable, tendrá que ponerse de bases de datos errores/desconecta y vuelve a conectar en cualquiera de los casos (de desconectar o estar conectado). Como debe hacer esto de todos modos, también puede volver a utilizar una conexión.

En otras palabras, el hecho de que tenga una conexión recién abierta no significa que la consulta no fallará y la conexión deberá reabrirse e intentarse nuevamente.

Por lo tanto, creo que la manera más limpia sería preservar la conexión. Pero solo a duras penas.

+0

Hola Sean. En mi caso, está bien que el daemon use el mismo bucle para el sondeo como para reconectarlo. Entonces, si la conexión recién abierta no funciona, o algo relacionado con DB falla en los pasos 1 (vea OP), el deamon simplemente salta al paso 3. Entonces se obvia una rama de código de reconexión en db-dailure explícita. –

Cuestiones relacionadas