2010-04-21 3 views
10

J'essaie de trouver le moyen le plus efficace d'exécuter une tâche PHP assez lourde des milliers de fois par jour. Il doit établir une connexion IMAP à Gmail, faire une boucle sur les e-mails, enregistrer ces informations dans la base de données et enregistrer les images localement. Exécuter cette tâche de temps en temps à l'aide d'un cron n'est pas un gros problème, mais je dois l'exécuter toutes les minutes et je sais que les crons finiront par courir les uns sur les autres et causer des problèmes de mémoire.Que dois-je utiliser lorsqu'un travail cron ne suffit pas? (php)

Quelle est la prochaine étape lorsque vous devez exécuter efficacement une tâche plusieurs fois par minute? Pheanstalk et je ne suis pas entièrement sûr si cela fera ce dont j'ai besoin. Pensées???

+0

Ceci n'est pas directement lié à votre question, mais utilisez CURL pour récupérer les images. Il met en cache la requête DNS, alors que file_get_contents() et d'autres fonctions de fichiers natifs ne le font pas. Une fois, j'ai eu besoin de faire un script pour récupérer des images, et à peu près tout le temps d'exécution était la latence du réseau. Cela peut donc aider un peu à le réduire. – Savageman

Répondre

7

Créez un mécanisme de verrouillage afin que les scripts ne se chevauchent pas. Ceci est tout à fait simple que les scripts ne fonctionnent que chaque minute, un simple fichier .lock suffirait:

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

    do_stuff_here(); 

    unlink("foo.lock"); 
?> 

Cela fera en sorte scripts ne fonctionnent pas en parallèle, il vous suffit de vous assurer que le fichier est supprimé .lock quand le programme se termine, vous devriez avoir un seul point de sortie (sauf pour la sortie au début). Une bonne alternative - comme l'a suggéré Brian Roach - est un processus de serveur dédié qui s'exécute tout le temps et maintient la connexion au serveur IMAP. Cela réduit les frais généraux beaucoup et ne sont pas beaucoup plus difficile que d'écrire un script php normal:

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

Je pense que le démon sera mon meilleur pari et que l'IMAP ouvert devrait rendre les choses beaucoup plus rapides. Merci pour le conseil! – mike

10

Je ne suis pas un mec PHP mais ... qu'est-ce qui vous empêche d'exécuter votre script en tant que démon? J'ai écrit beaucoup de scripts Perl.

+0

Je n'ai jamais écrit de démon auparavant, mais je vais commencer à faire plus de recherches maintenant. Merci pour la suggestion. – mike

+0

Fondamentalement ... vous enveloppez tout dans un 'while (1)' et exécutez le script en arrière-plan. S'il est important que vous finissiez par faire quelque chose plutôt que d'être simplement tué, regardez dans la gestion des signaux afin de pouvoir nettoyer avant de quitter. Points bonus pour forking plutôt que d'exiger qu'il soit exécuté à partir du shell dans le backgorund :) –

+0

Je suggérerais 2 fichiers: le premier crée un autre processus qui exécute le daemon. Le premier attendra quelques secondes et vérifiera si le démon est toujours en cours d'exécution. Sinon, il peut le relancer. Je n'ai pas vraiment confiance en PHP pour avoir été aussi longtemps, donc je pense qu'il vaut mieux prendre des précautions. – Savageman

3

J'ai un certain nombre de scripts comme ceux-ci, où je ne veux pas les exécuter à partir Cron au cas où ils empilent -up

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

La partie exec $0 commence le script en cours d'exécution à nouveau, en se substituant en mémoire, il fonctionnera toujours sans problèmes. Toute mémoire utilisée par le script PHP est nettoyée à chaque fermeture, ce qui n'est pas un problème non plus.

Une simple ligne va commencer, et le mettre dans l'arrière-plan:

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

ou il peut être démarré de la même lorsque la machine commence par divers moyens (par exemple de Cron « de @reboot .... »

0

fcron http://fcron.free.fr/ ne démarrera pas de nouvel emploi si l'ancien est toujours en cours d'exécution, vous pouvez utiliser @ 1 command et ne pas s'inquiéter des conditions de course.

Questions connexes