Появилась необходимость поднять WebSocket сервер, а так как проет пишется на php, то тут особых вариантов и не было - phpdaemon. Немного погуглив нашел сравнительную статью Нагрузочное тестирование: Node.JS vs phpDaemon. Результаты порадовали и было решено попробовать это чудо (скажу только, что пока нареканий нет, la упал на порядок + разгрузили fcgi воркеров).
При установке выбрал: Сервер SSH, Стандартные системные утилиты
Новый phpdaemon (от 23 января 2013) требует php 5.4. Поставить можно так (взято с serverfault http://serverfault.com/questions/404815/how-can-i-upgrade-php-to-a-higher-version-for-debian-squeeze):
Из требований самого phpdaemon:
Стоит проверить наличие следующих модулей:
Ставим:
Копируем конфиги:
AppResolver.php служит для роутинга приложений (но! не для WebSocket. для WS ws://server/RouteForAppName).
Правим основной конфиг /etc/phpdaemon/phpd.conf:
Есть один нюанс: пул WebSocketServer должен быть в конфиге до пула HTTPServer, так как на данный момент при инициализации HTTPServer получает инстанс WebSocketServer. Если последнего нет, то он создается, но не пул а отдельный сервер. Если указано несколько воркеров, то только первый сможет сделать бинд для сокета WS.
appfilepath - параметр для поиска приложений. Наши приложения будут лежать в /var/www/apps-phpdaemon/. Параметр передается в glob() так:
Создадим папку для наших приложений:
В файле phpd в качестве интерпретатора указан /opt/bin/php, поэтому нужен запуск в виде php /opt/phpdaemon/bin/phpd.
Проверяем, что все "взлетело":
Если теперь вбить в браузере http://server-address:8080/ExampleWebSocket/ то должны увидеть следующее.
Кнопка Create WebSocket инициирует соединение, Ping - отправляет запро, Close WebSocket - закрывает соединение.
Посмотреть пакеты WS (в хроме) можно щелкнув на соответствующий запрос на установку WS соединения.
Остановить phpdaemon можно так:
init скрипт (из репо не подходит для squeeze), ротация логов и прочее - на ваше усмотрение.
Установка Debian
Установочный образ debian-6.0.6-amd64-netinst.isoПри установке выбрал: Сервер SSH, Стандартные системные утилиты
Требования phpdaemon
Ставить будем из репо, по-этому необходим git:# apt-get install git
Новый phpdaemon (от 23 января 2013) требует php 5.4. Поставить можно так (взято с serverfault http://serverfault.com/questions/404815/how-can-i-upgrade-php-to-a-higher-version-for-debian-squeeze):
# echo "deb http://ftp.ru.debian.org/debian/ wheezy main non-free contrib" >> /etc/apt/sources.list # cat >> /etc/apt/preferences <<EOF Package: * Pin: release n=squeeze Pin-Priority: 650 Package: * Pin: release n=wheezy Pin-Priority: -10 EOF
apt-get update apt-get install -t wheezy php5-cli php5-dev php-pear
Из требований самого phpdaemon:
# apt-get install -t wheezy libevent-dev # pecl install https://bitbucket.org/osmanov/pecl-event/downloads/event-1.0.0.tgz< # echo "extension=event.so" > /etc/php5/conf.d/event.ini # pecl install channel://pecl.php.net/proctitle-0.1.2 # echo "extension=proctitle.so" > /etc/php5/conf.d/proctitle.ini # cd /usr/src/ # git clone https://github.com/zenovich/runkit.git # cd runkit/ # pecl install package.xml # echo "extension=runkit.so" > /etc/php5/conf.d/runkit.ini # pecl install eio # echo "extension=eio.so" > /etc/php5/conf.d/eio.ini
Стоит проверить наличие следующих модулей:
# php -m | grep pcntl # php -m | grep shmop # php -m | grep sockets
Установка phpdaemon
Репо на github: https://github.com/kakserpom/phpdaemonСтавим:
# cd /opt/ # git clone https://github.com/kakserpom/phpdaemon.git
Настройка phpdaemon
Конфиги лежат в /opt/phpdaemon/conf/ и /opt/phpdaemon/conf/conf.d/, я предпочитаю их в /etc/phpdaemon/.Копируем конфиги:
# mkdir /etc/phpdaemon # cp /opt/phpdaemon/conf/phpd.conf.example /etc/phpdaemon/phpd.conf # cp /opt/phpdaemon/conf/AppResolver.php /etc/phpdaemon/ # cp -rp /opt/phpdaemon/conf/conf.d /etc/phpdaemon/
AppResolver.php служит для роутинга приложений (но! не для WebSocket. для WS ws://server/RouteForAppName).
Правим основной конфиг /etc/phpdaemon/phpd.conf:
user www-data; group www-data; max-workers 1; min-workers 1; start-workers 1; max-idle 0; # logging-related logevents 1; logqueue 1; logreads 1; logsignals 1; verbose 0; verbosetty 0; # apps search appfilepath '{app-*,applications,/var/www/apps-phpdaemon}/%s.php'; # apps routing path '/etc/phpdaemon/AppResolver.php'; # Pools Pool:WebSocketServer { enable 1; listen '0.0.0.0'; port 8047; } Pool:HTTPServer { enable 1; listen '0.0.0.0'; port 8080; expose 1; } # Apps # для фоллбэка на http если клиент не поддерживает websocket WebSocketOverCOMET { enable 1; } # Для теста доступности по HTTP Example { enable 1; } # Для теста WS с фолбэком на comet и longpolling ExampleWebSocket { enable 1; } # прочие конфиги/приложения #include conf.d/*.conf
Есть один нюанс: пул WebSocketServer должен быть в конфиге до пула HTTPServer, так как на данный момент при инициализации HTTPServer получает инстанс WebSocketServer. Если последнего нет, то он создается, но не пул а отдельный сервер. Если указано несколько воркеров, то только первый сможет сделать бинд для сокета WS.
appfilepath - параметр для поиска приложений. Наши приложения будут лежать в /var/www/apps-phpdaemon/. Параметр передается в glob() так:
if (class_exists('Daemon', false) && isset(Daemon::$config->appfilepath->value)) { $files = glob($g = sprintf(Daemon::$config->appfilepath->value, str_replace('_', DIRECTORY_SEPARATOR, $classname)), GLOB_BRACE); if (isset($files[0])) { require $files[0]; return; } }
Создадим папку для наших приложений:
# mkdir /var/www/apps-phpdaemon/
Поправим роутер приложений (/etc/phpdaemon/AppResolver.php), чтобы дать доступ к приложению ExampleWebSocket:
- if (preg_match('~^/(WebSocketOverCOMET|Example)/~', $req->attrs->server['DOCUMENT_URI'], $m)) { + if (preg_match('~^/(WebSocketOverCOMET|Example|ExampleWebSocket)/~', $req->attrs->server['DOCUMENT_URI'], $m)) {
Тестовый запуск
Запуск:# php /opt/phpdaemon/bin/phpd start
В файле phpd в качестве интерпретатора указан /opt/bin/php, поэтому нужен запуск в виде php /opt/phpdaemon/bin/phpd.
Проверяем, что все "взлетело":
# ps aux | grep phpd root 24225 0.5 1.3 95520 6968 ? SNs 14:15 0:00 phpd: master process www-data 24226 0.3 1.4 96040 7272 ? SN 14:15 0:00 phpd: IPC process www-data 24227 0.5 1.6 96592 8196 ? SNl 14:15 0:00 phpd: worker process root 24230 0.0 0.1 7572 868 pts/0 S+ 14:16 0:00 grep phpd # netstat -ntpa | grep phpd tcp 0 0 0.0.0.0:8047 0.0.0.0:* LISTEN 24225/phpd: master tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 24225/phpd: master
Если теперь вбить в браузере http://server-address:8080/ExampleWebSocket/ то должны увидеть следующее.
Кнопка Create WebSocket инициирует соединение, Ping - отправляет запро, Close WebSocket - закрывает соединение.
Посмотреть пакеты WS (в хроме) можно щелкнув на соответствующий запрос на установку WS соединения.
Остановить phpdaemon можно так:
# php /opt/phpdaemon/bin/phpd stop
init скрипт (из репо не подходит для squeeze), ротация логов и прочее - на ваше усмотрение.