2010-04-21 21 views
10

que estoy tratando de averiguar la forma más eficiente de ejecutar una tarea bastante fuertes miles de PHP veces al día. Necesita hacer una conexión IMAP con Gmail, recorrer los correos electrónicos, guardar esta información en la base de datos y guardar las imágenes localmente.¿Qué uso cuando un trabajo cron no es suficiente? (Php)

Ejecutar esta tarea de vez en cuando con un cron no es gran cosa, pero tengo que ejecutarlo cada minuto y sé que finalmente los crons comenzarán a correr uno encima del otro y causarán problemas de memoria.

¿Cuál es el siguiente paso cuando se necesita para ejecutar una tarea de manera eficiente múltiples veces por minuto? He estado leyendo sobre beanstalk & pheanstalk y no estoy del todo seguro de si eso hará lo que necesito. Pensamientos ???

+0

Esto no está directamente relacionada con su pregunta, pero el uso de CURL para recuperar las imágenes. Cache la solicitud de DNS, mientras que file_get_contents() y otra función de archivo nativo no lo hace. Una vez tuve que hacer un script para recuperar imágenes, y prácticamente todo el tiempo de ejecución fue latencia de red. Entonces eso puede ayudar un poco a reducirlo. – Savageman

Respuesta

7

bien crear un mecanismo de bloqueo por lo que los scripts no se solaparán. Esto es bastante simple como secuencias de comandos sólo se ejecutan cada minuto, un archivo .lock sencilla sería suficiente:

<?php 
    if (file_exists("foo.lock")) exit(0); 
    file_put_contents("foo.lock", getmypid()); 

    do_stuff_here(); 

    unlink("foo.lock"); 
?> 

Esto se asegurará de que las secuencias de comandos no se ejecutan en paralelo, sólo hay que asegurarse de que el archivo se elimina .lock cuando el programa sale, debe tener un único punto de salida (excepto la salida al principio).

Una buena alternativa - como se sugiere Brian Roach - es un proceso de servidor dedicado que funciona todo el tiempo y mantiene la conexión con el servidor IMAP arriba. Esto reduce la sobrecarga mucho y no es mucho más difícil que escribir un guión normal de PHP:

<?php 
    connect(); 
    while (is_world_not_invaded_by_aliens()) 
    { 
    get_mails(); 
    get_images(); 
    sleep(time_to_next_check()); 
    } 
    disconnect(); 
?> 
+2

Creo que el daemon va a ser mi mejor opción y mantener el IMAP abierto debería hacer las cosas mucho más rápidas. ¡Gracias por el consejo! – mike

10

Yo no soy un tipo PHP, pero ... ¿Qué le impide ejecutar el script como un demonio? He escrito muchos guiones de perl que hacen precisamente eso.

+0

Nunca antes he escrito un daemon, pero comenzaré a investigar un poco más ahora. Gracias por la sugerencia. – mike

+0

Básicamente ... simplemente envuelve todo en 'while (1)' y ejecuta el script en segundo plano. Si es importante que termine de hacer algo en lugar de simplemente morir, investigue el manejo de la señal para que pueda limpiar antes de salir. Puntos de bonificación por bifurcación en lugar de requerir que se ejecute desde el shell en el fondo :) –

+0

Sugiero 2 archivos: el primero crea otro proceso que ejecuta el daemon. El primero solo esperará un par de segundos y verificará si el daemon aún se está ejecutando. Si no, puede relanzarlo. Realmente no confío en PHP por correr tanto tiempo, así que creo que es mejor tomar precauciones. – Savageman

3

Tengo una serie de guiones como estos, en los que no quiero para ejecutarlos desde cron en caso de que se apilan -arriba.

#!/bin/sh 
php -f fetchFromImap.php 
sleep 60 
exec $0 

La parte exec $0 comienza a correr de nuevo la secuencia de comandos, sustituyéndose en la memoria, para que se ejecute siempre sin problemas. Cualquier memoria que utiliza el script PHP se limpia cada vez que sale, por lo que tampoco es un problema.

Una simple línea comenzará él, y lo puso en el fondo:

cd /x/y/z ; nohup ./loopToFetchMail.sh & 

o puede ser iniciado de manera similar cuando la máquina empieza con diversos medios (por ejemplo, de Cron '@reboot ....')

0

fcron http://fcron.free.fr/ no se iniciará un nuevo trabajo si el anterior todavía se está ejecutando, podría utilizar @ 1 command y no preocuparse por las condiciones de carrera.

Cuestiones relacionadas