Используете комету с PHP?

82

Я думал о реализации чата в реальном времени с использованием PHP-бэкенда, но наткнулся на этот комментарий на сайте, посвященном комете:

Насколько я понимаю, PHP - ужасный язык для Comet, потому что Comet требует, чтобы вы поддерживали постоянное соединение с каждым клиентом браузера. Использование mod_php означает постоянное привязывание дочернего Apache к каждому клиенту, который вообще не масштабируется. Люди, которых я знаю, занимающиеся Comet, в основном используют Twisted Python, который предназначен для обработки сотен или тысяч одновременных подключений.

Это правда? Или это что-то, что можно настроить вокруг?

ржаной
источник
4
вы можете запускать php как fastcgi ...
Итай Моав -Малимовка 02
4
Используйте nodeJS в качестве сервера для поддержания клиентских подключений, веб-сокеты в javascript для подключения к серверу из браузера. PHP в этом смысле может быть привилегированным клиентом, который будет подключаться к nodejs, передавать некоторые служебные данные, которые будут каким-то образом обрабатываться на стороне клиента.
Artjom Kurapov
1
@ArtjomKurapov Вы можете сделать PHP в веб - сервер , таким образом обходя метод Apache по обработке запросов - думать об этом , как реальный сервер PHP принимает запросы по уходу комета только .
Christian
@Christian, если вы имели в виду встроенный веб-сервер php начиная с версии 5.4, то он предназначен только для разработки, и использование его на производстве - плохая идея
Artjom Kurapov
2
@ArtjomKurapov Нет, я имел в виду написать настоящий PHP-сервер с использованием PHP-сокетов для прослушивания порта 80 и блокировки ввода на неопределенный срок - эффективно, как серверы работают. Это уже можно увидеть в действии в таких проектах, как phpwebsocket .
Christian

Ответы:

61

Соглашаясь / расширяя то, что уже было сказано, не думаю, что FastCGI решит проблему.

Apache

Каждый запрос в Apache будет использовать один рабочий поток до тех пор, пока запрос не будет завершен, что может занять много времени для запросов COMET.

В этой статье об Ajaxian упоминается использование COMET на Apache, и это сложно. Проблема не является специфической для PHP и применима к любому внутреннему модулю CGI, который вы, возможно, захотите использовать в Apache.

Предлагаемое решение заключалось в использовании модуля MPM «событий», который изменяет способ отправки запросов рабочим потокам.

Этот MPM пытается исправить «проблему сохранения активности» в HTTP. После того, как клиент завершит первый запрос, он может оставить соединение открытым и отправлять дальнейшие запросы, используя тот же сокет. Это может сэкономить значительные накладные расходы при создании TCP-соединений. Однако Apache традиционно держит весь дочерний процесс / поток в ожидании данных от клиента, что имеет свои недостатки. Чтобы решить эту проблему, MPM использует выделенный поток для обработки как прослушивающих сокетов, так и всех сокетов, находящихся в состоянии Keep Alive.

К сожалению, это тоже не работает, потому что он будет «откладывать» только после завершения запроса, ожидая нового запроса от клиента.

PHP

Теперь, учитывая другую сторону проблемы, даже если вы решите проблему с задержкой одного потока на запрос кометы, вам все равно понадобится один поток PHP на запрос - вот почему FastCGI не поможет.

Вам нужно что-то вроде Continuations, которое позволяет возобновлять запросы комет, когда наблюдается событие, по которому они инициированы. AFAIK, это невозможно в PHP. Я видел это только на Java - см. Сервер Apache Tomcat .

Редактировать:

Здесь есть статья об использовании балансировщика нагрузки ( HAProxy ), позволяющего запускать как сервер apache, так и сервер с поддержкой кометы (например, причал, tomcat для Java) на порту 80 одного и того же сервера.

Майк Хьюстон
источник
20
Я понимаю, что это не совсем решение: /
Майк Хьюстон,
+1, потому что Apache / PHP - не лучший вариант для масштабирования кометного решения. Варианты для пользователей PHP: 1) как вы упомянули, сумасшедшие конфигурации дополнительных серверов и прокси или 2) использование решения SaaS и выгрузка кометного материала через что-то вроде WebSync On-Demand.
jvenema 04
1
Это неверно в нескольких аспектах. Если кто-то хочет отказаться от метода с одним потоком для каждого пользователя, этого можно легко добиться, удалив Apache в качестве посредника и позволив PHP обрабатывать эти запросы. Конечно, Apache лучше обслуживает контент, поэтому я бы запустил этот PHP-сервер без apache на поддомене, который не обслуживает какой-либо контент.
Christian
@MikeHouston А как насчет того, чтобы попробовать комету с php в IIS?
ravi404
@ravz, здесь есть кое-что о IIS и комете: stackoverflow.com/questions/1898848/comet-programming-in-iis , но я подозреваю, что PHP-модуль fast-cgi имеет те же ограничения, что и apache. Здесь упоминается однопоточная среда: microsoft.com/web/platform/phponwindows.aspx - Я сам не использую серверы Windows, поэтому не уверен в модели потоковой передачи.
Майк Хьюстон,
14

Вы можете использовать Nginx и JavaScript для реализации системы чата на основе Comet, которая очень масштабируема с небольшой загрузкой памяти или ЦП.

У меня есть очень простой пример, с которого вы можете начать. Он охватывает компиляцию Nginx с модулем NHPM и включает код для простых ролей издателя / подписчика в jQuery, PHP и Bash.

http://blog.jamieisaacs.com/2010/08/27/comet-with-nginx-and-jquery/

Джейми
источник
10

PHP

Я нашел эти забавные скринкасты, объясняющие простую комету. В качестве примечания я действительно думаю, что это убьет ваш сервер при любой реальной нагрузке. Когда у вас всего пара пользователей, я бы сказал, что просто выберу это решение. Это решение действительно просто реализовать (скринкасты занимают всего 5 минут вашего времени :)). Но, как я уже говорил ранее, я не думаю, что это хорошо для большого количества одновременных пользователей (думаю, вам следует протестировать его;)), потому что:

  1. Он использует файловый ввод-вывод, который намного медленнее, чем просто получение данных из памяти. Как, например, функции filemtime(),
  2. Во-вторых, но я не думаю, что в последнюю очередь PHP не имеет достойной модели потоков. PHP в любом случае не был предназначен для этого из-за модели без совместного использования ресурсов . Как и на слайдах, говорится: «Общие данные передаются на уровень хранилища данных», как, например, MySQL.

Альтернативы

Я действительно думаю, что вам следует попробовать альтернативы, если вы хотите провести какой-либо кометный / длинный опрос. Вы можете использовать много языков, например:

  • Java / JVM: продолжения Jetty .
  • Python: слюни Дастина .
  • Эрланг: популярный язык для комет и т. Д.
  • Lua, Ruby, C, Perl и многие другие.

Простое выполнение простого поиска в Google покажет вам множество альтернатив, а также PHP (который, я думаю, при любой большой нагрузке убьет ваш сервер).

Альфред
источник
7

mod_php - не единственный способ использовать PHP. Вы можете использовать fastcgi. PHP должен быть скомпилирован с использованием --enable-fastcgi.

PHP как FastCGI: http://www.fastcgi.com/drupal/node/5?q=node/10

Vartec
источник
6

Вы также можете попробовать https://github.com/reactphp/react

React - это низкоуровневая библиотека для программирования на PHP, управляемого событиями. В его основе лежит цикл событий, поверх которого он предоставляет низкоуровневые утилиты, такие как: абстракция потоков, асинхронный DNS-преобразователь, сетевой клиент / сервер, http-клиент / сервер, взаимодействие с процессами. Сторонние библиотеки могут использовать эти компоненты для создания асинхронных сетевых клиентов / серверов и многого другого.

Цикл событий основан на шаблоне реактора (отсюда и название) и сильно вдохновлен такими библиотеками, как EventMachine (Ruby), Twisted (Python) и Node.js (V8).

Вводный пример показывает простой HTTP-сервер, прослушивающий порт 1337:

<?php

$i = 0;

$app = function ($request, $response) use (&$i) {
    $i++;

    $text = "This is request number $i.\n";
    $headers = array('Content-Type' => 'text/plain');

    $response->writeHead(200, $headers);
    $response->end($text);
};

$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$http = new React\Http\Server($socket);

$http->on('request', $app);

$socket->listen(1337);
$loop->run();
Гордон
источник
4

У меня похожая проблема. Один из вариантов, который мне интересен, - это использовать существующий сервер Comet, например cometd-java или cometd-python, в качестве основного концентратора сообщений. Тогда ваш PHP-код является просто клиентом для сервера Comet - он может публиковать или читать сообщения из каналов, как и другие клиенты.

Здесь есть интересный фрагмент кода: http://morglog.org/?p=22=1, который реализует часть этого метода (хотя есть и фрагменты кода отладки).

Эван П.
источник
3

В настоящее время я реализую масштабируемый сервер PHP Comet с использованием функций сокетов. Он называется фет ([ph] p com [et]).

Страница проекта: http://github.com/Tim-Smart/phet

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

РЕДАКТИРОВАТЬ: недавно добавленные возможности многопоточности с использованием pcntl_forkметода :)

Тим
источник
Нет доступных примеров использования этой библиотеки.
ftrotter 07
3

Вам будет сложно реализовать комету в PHP только из-за присущей ей однопоточности.

Проверьте Websync On-Demand - услуга позволяет интегрировать PHP с помощью серверного издания, разгружая тяжелые вещи параллельного соединения и позволит вам создать приложение чата в режиме реального времени в кратчайшие сроки.

Jvenema
источник
1

Вам нужно будет создать свой собственный сервер на PHP. Использование Apache / mod_php или даже fastcgi вообще не масштабируется. Несколько лет назад, но можно начать:

PHP-Comet-Server: http://sourceforge.net/projects/comet/

срусси
источник
0

Я думаю, что это скорее проблема, связанная с тем, что постоянно работает много потоков apache. Это будет существовать с любым языком, если он работает через apache так же, как PHP (обычно).

Benlumley
источник
1
Я думаю, дело в том, что вы обычно запускаете php в процессе на запрос, а не в потоке на запрос.
troelskn 02