2010-09-02 4 views
8

Im travaillant sur une application de chat simple, probablement 10 à 20 utilisateurs par pièce.Simple script de conversation PHP longue interrogation, trop simple?

Le script qui interroge la base de données pour les nouveaux messages semble trop simple pour toutes les requêtes qu'il va recevoir.

est en dessous du bloc de code qui boucle pour les nouveaux messages, le reste du script ne fait que commencer les variables, la construction de la requête et l'objet de réponse JSON:

$sleepTime = 1; //Seconds 
$data = ""; 
$timeout = 0; 

//Query database for data 
while(!$data and $timeout < 10){ 
    $data = getQuery($sql); 
    if(!$data){ 
     //No new messages on the chat 
     flush(); 
     //Wait for new Messages 
     sleep($sleepTime);   
     $timeout += 1; 
    }else{ 
     break; 
    } 
} 

Le bloc ci-dessus interroger la base de données pour les nouveaux messages chaque seconde pendant 10 secondes, si après les 10 secondes, il n'y a pas de nouveaux messages, il en informera le navigateur. Le navigateur attend 5 secondes, puis envoie une autre requête pour obtenir de nouveaux messages.

Cependant, si le script trouve de nouveaux messages, le navigateur demandera plus de nouveaux messages instantanément dès qu'il reçoit la réponse avec les nouveaux messages du serveur.

Ce processus se poursuit et ...

Alors, comment puis-je optimiser ce processus plus loin? Est-ce que c'est aussi bon que ça? Fonctionne très bien sur mon serveur local, mais j'ai peur que seulement quelques utilisateurs puissent surcharger un serveur en direct (hôte partagé) avec toutes les demandes et les bouclages.

est ici en direct DEMO vous pouvez vérifier avec Firebug http://pixbush.com/chat/chat.php

+3

La simplicité est ce que nous, en tant que programmeurs **, recherchons **. –

+4

Le lien ne fonctionne plus. – kachar

Répondre

2

Ce cris pour AJAX.

Voir mon post aujourd'hui sur how to send JavaScript responses to PHP. Il n'y a aucune raison que votre script doive faire une boucle.


EDIT: Mon mauvais à propos de l'AJAX. Quand j'ai écrit le chatbot IRC PHP-Egg, j'ai rencontré ce problème * 100. La façon dont je l'ai résolu (de retour dans les 4 jours de PHP, attention) était de pcntl_fork() PHP et de l'avoir simplement retourné chaque fois qu'il y avait un message. Les avantages sont que cela ne bloque pas le CPU à 100%, contrairement à sleep() et est BEAUCOUP plus rapide que 10 secondes ou toute limite arbitraire que vous avez mis dessus.


Je révision ma réponse encore une fois (désolé!):

utiliser une sorte de processus asynchrone qui déverse le texte dans un fichier.

Alors ce que vous feriez est

si (filemtime ('chat.log')> time() - 5) { écho json_encode (file_get_contents ('chat.log')); }

Avantages: utilisation SQL limitée; pas besoin de boucle.

+3

Je suis à peu près sûr que l'OP * utilise * AJAX avec ** l'interrogation longue **, comme l'indique la question. http://en.wikipedia.org/wiki/Comet_(programming)#Ajax_with_long_polling – deceze

+0

@Pablo: Quelques tutoriels qui peuvent vous aider ici: http://css-tricks.com/chat2/, http: // net. tutsplus.com/tutorials/javascript-ajax/how-to-create-a-simple-web-based-chat-application/, http://anantgarg.com/2009/05/13/gmail-facebook-style-jquery -bavarder/. AJAX est certainement le chemin à parcourir. –

+1

im en utilisant AJAX, Plus im Looping dans le serveur pour minimiser les requêtes AJAX. – Pablo

0

Vous pouvez essayer d'utiliser des fichiers étiquetés d'après conversationId au lieu d'une base de données et de vérifier si le fichier a été «touché». En outre, utilisez usleep et set_time_limit (pour le serveur Windows) pour définir votre intervalle en milisecs et augmenter le temps de sommeil. Usleep effectivement, retarde l'utilisation du CPU mais est toujours allumé instantanément, le fichier a été changé.

Voici une section de mon script de discussion. =)

define('SUCCESS', '__SUCCESS__'); 
define('FAILED', '__FAILED__'); 

$tmpLib = $TMPFOLDER; 
$msgPath = $MSGFILE; 

$timeout = $POLLSPEEDSEC; 

$acct = new Account($tmpLib, $_GET['key']); 

if (false === $acct) { 
    return false; 
} 

$msg = new Message($msgPath, $acct); 

$lastMod = !empty($_GET['ts']) ? $_GET['ts']: 0; 
$lastMod = substr($lastMod, 0, 10); 
$lastMod = (int)$lastMod; 

$result = array(); 

$start = gettimeofday(); 
$prevMsg = $acct->getTemp('cache'); 

do{ 
    usleep(10000); 

    if ($acct->getFileTime() >= $lastMod) { 
     $result['account'] = $acct->getAllOnline(); 
    } 

    if($msg->getFileTime() >= $lastMod) { 
     $result['message'] = $msg->fetch(); 
    } 

    if (!empty($result)) { 
     $theMsg = json_encode($result); 
     if ($theMsg != $prevMsg) { 
      $acct->setTemp('cache', $theMsg); 
      echo $theMsg; 
      flush(); 
      exit; 
     } 
     $result = array(); 
     $lastMod = time(); 
    } 

    $end = gettimeofday(); 
} while($timeout > ($end['sec'] - $start['sec'])); 

echo FAILED; 
+0

Même que ma réponse, donc je suis d'accord. –

+0

et comment exactement vous assurez-vous que le fichier ne soit pas corrompu par l'accès simultané et peut-être écrit en même temps? – Pablo

+0

Pour un accès simultané, FS ​​verrouille les fichiers sans les corrompre. Si cela se produit, aucun changement ne sera effectué. Il y a peut-être 1 chance sur 50 que cela se produise. La chance est trop faible pour en faire un spectacle-bouchon. De plus, le même problème se produit également si vous utilisez une base de données. Les fichiers sont meilleurs, en théorie, parce qu'ils "libèrent" le verrou et répondent plus vite que les DB. – sheeks06

3

D'après votre description, il semble que vous avez 5 secondes espace de silence qui contrecarre le bénéfice de long sondage. Avoir le navigateur démarrer une autre demande immédiatement lorsqu'un appel revient (long ou court) du serveur. En tant que sauvegarde, à chaque appel de serveur, le navigateur doit démarrer un délai d'expiration légèrement plus long que le délai d'expiration côté serveur, mais l'annuler lorsqu'une demande est renvoyée. Si la demande du serveur échoue et que le délai d'expiration du navigateur est terminé, lancez une nouvelle demande.

1

J'ai commencé à discuter sur le Web et je suis tombé sur la même solution pour garder les mises à jour en temps réel. Donc, je me demande si vous l'avez compris: est-ce un bon moyen de garder la boucle côté serveur en utilisant la fonction sleep(), ou peut-être qu'il vaut mieux utiliser plus de requêtes ajax à la place. Et la fonction sleep() est-elle vraiment une bonne idée et n'arrêtera pas le serveur quand plusieurs utilisateurs sont interrogés?

Je vois meebo en utilisant l'interrogation longue (le temps entre les requêtes dépend aussi de l'accent de la fenêtre, je suppose) tout en SO chat app. semble juste utiliser seulement des requêtes ajax. Alors ça me fait réfléchir.

+1

longue interrogation en utilisant la fonction sleep() sonne bien sur le papier et encore mieux en cours d'exécution sur la machine de test locale. Mais sur le serveur live (hébergement mutualisé) pas tellement, cela met trop de stress sur le serveur. J'ai finalement décidé de ne garder que les requêtes ajax, pas de longues interrogations. J'ai également créé une logique pour augmenter et diminuer le taux de demandes ajax en fonction du niveau d'activité et de la situation. – Pablo

+0

merci pour la réponse, je vais voir comment ma longue interrogation va et puis décider si le laisser ou refuser – dr3w