2010-09-02 1 views
8

Im работает над простым приложением чата, возможно от 10 до 20 пользователей в комнате.Простой PHP длинный скрипт чата для голосования, слишком простой?

Сценарий, запрашивающий базу данных для новых сообщений, выглядит слишком простым для всего запроса, который он получит.

Ниже приведен блок кода, который петли для новых сообщений, остальная часть скрипта просто получает переменные, построение запроса и объект ответа 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; 
    } 
} 

Блок выше будет запрашивать базу данных для новых сообщений каждую секунду в течение 10 секунд, если после 10 секунд новых сообщений не будет отправлено уведомление обозревателю. Браузер ждет 5 секунд, а затем отправляет другой запрос , чтобы получить новые сообщения.

Однако, если скрипт находит новые сообщения, браузер запрашивает новые сообщения мгновенно, как только он получит ответ с новыми сообщениями с сервера.

Этот процесс продолжается и на ...

Так как я могу оптимизировать этот процесс дальше? Насколько это хорошо? Работает нормально на моем локальном сервере, но я боюсь, что только несколько пользователей могут перегрузить живой сервер (общий хост) со всеми запросами и циклами.

Вот живой DEMO вы можете проверить с поджигатель http://pixbush.com/chat/chat.php

+3

Простота - это то, что мы как программисты ** стремимся к **. –

+4

Ссылка больше не работает. – kachar

ответ

2

Это орет для AJAX.

Смотрите мое сообщение сегодня на how to send JavaScript responses to PHP. Нет причин, по которым ваш скрипт должен вообще зацикливаться.


EDIT: Мой плохой об AJAX. Когда я написал IRC chatbot PHP-Egg, я столкнулся с этой проблемой * 100. То, как я ее решил (еще в PHP 4 дня, заметьте), был pcntl_fork() PHP и просто он возвращался каждый раз, когда появлялось сообщение. Преимуществом является то, что он не блокирует CPU на 100%, в отличие от sleep(), и МНОГО быстрее, чем 10 секунд, или любой произвольный лимит, который вы на него наложили.


Я снова пересматривают свой ответ (извините!):

Использование своего рода асинхронного процесса, который выводит текст в файл.

Тогда что вы могли бы сделать это

если (filemtime ('chat.log')> Время() - 5) { эхо json_encode (file_get_contents ('chat.log')); }

Привилегии: Ограниченное использование SQL; нет необходимости в цикле.

+3

Я уверен, что OP * * использует AJAX вместе с ** длительным опросом **, как говорится в этом вопросе. http://en.wikipedia.org/wiki/Comet_(programming)#Ajax_with_long_polling – deceze

+0

@Pablo: Несколько руководств, которые могут вам помочь: 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 чат-/. AJAX - это, безусловно, путь. –

+1

im Использование AJAX, Plus im Looping на сервере для минимизации запросов AJAX. – Pablo

0

Вы можете попробовать использовать файлы, помеченные в соответствии с talkId вместо DB, и просто проверить, был ли файл «тронут». Кроме того, используйте usleep и set_time_limit (для сервера Windows), чтобы установить интервал в milisecs и увеличить время ожидания. На самом деле Usleep задерживает использование ЦП, но все еще срабатывает мгновенно, если файл был изменен.

Вот раздел моего скрипта чата. =)

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

То же, что и мой ответ, поэтому я согласен. –

+0

и как именно вы убедитесь, что файл не поврежден, так как доступ одновременно и, возможно, был написан в одно и то же время? – Pablo

+0

Для одновременного доступа FS блокирует файлы, которые не повреждают его. Если это произойдет, изменений не будет. Возможно, 1 из 50 шансов, что это произойдет. Шанс слишком низкий, чтобы сделать его шоу-пробкой. Плюс, эта же проблема также возникает, если вы используете БД. Файлы лучше, теоретически, потому что он «освобождает» блокировку и реагирует быстрее, чем DB. – sheeks06

3

Из вашего описания, это звучит, как у вас есть 5-секундный разрыв молчания, которая побеждает в пользу длительного опроса. Попросите браузер немедленно запустить другой запрос, когда вызов возвращается (длинный или короткий) с сервера. В качестве резервного копирования, с каждым вызовом сервера, браузер запускает тайм-аут, немного превышающий тайм-аут на стороне сервера, но отменяя его при возврате запроса. Если запрос сервера завершается с ошибкой и завершается тайм-аут браузера, запустите новый запрос.

1

Я делаю веб-чат и сталкивался с тем же решением для хранения обновлений в реальном времени. Итак, я задаюсь вопросом, поняли ли вы это: хороший ли способ сохранить циклическую работу на стороне сервера с помощью функции sleep(), или, может быть, лучше использовать больше запросов ajax. И функция sleep() действительно хорошая идея, и она не остановит сервер, если несколько пользователей заняты опросом?

Я вижу meebo, используя длинный опрос (время между запросами также зависит от фокуса окна, я думаю), в то время как SO chat app. похоже, просто использует только ajax-запросы. Поэтому меня удивляет.

+1

Длительный опрос с использованием функции sleep() звучит хорошо на бумаге и даже лучше работает на локальной тестовой машине. Но на реальном сервере (общий хостинг) не так много, это накладывает слишком много внимания на сервер. В конечном итоге я решил сохранить только запросы ajax, не долгие опросы. Я также создал некоторую логику для увеличения и уменьшения скорости запросов ajax в зависимости от уровня активности и ситуации. – Pablo

+0

спасибо за ответ, я посмотрю, как проходит мой длинный опрос, а затем решите оставить или отказаться от него – dr3w