Прежде чем начать писать свой вебсокет-сервер, я выбирал из готовых продуктов, и на тот момент их было всего два: phpdaemon и ratchet.
phpdaemon
1400 звёзд на гитхабе
- зависит от установки библиотеки libevent
- протоколы: HTTP, FastCGI, FlashPolicy, Ident, Socks4/5.
Ratchet
3600 звёзд на гитхабе
- тянет за собой около десятка зависимостей
- протоколы: websocket, http, wamp
- поддержка windows
- нет ssl
Эти библиотеки были очень монструозны и при этом не соответствовали моим внутренним требованиям:
- отсутствие зависимостей
- наличие таймеров
Таймеры мне нужны были для написания игры на вебсокетах для расчёта взаимодействий между всеми пользователями каждые 0.05 секунды.
В итоге я написал библиотеку для себя и поделился ею с сообществом на гитхабе. Сделал несколько демок (в том числе игру «танчики»). Переписал стороннюю игру (с разрешения авторов) с node.js на свою библиотеку. Делал нагрузочное тестирование. Демки работали годами без перезагрузки. Старался отвечать на тикеты в течения дня. Всё это показывало, что моя библиотека может быть использована на продакшене и многие её использовали.
Была единственная проблема. Мне хватало моей библиотеки для использования в своих проектах, а вот другим нет. Они хотели, чтобы я её развивал, а мне это было не нужно. Кому-то требовалась поддержка windows, а кому-то ssl, pg_notify, safari, pthreads и многое другое. Открытые тикеты с запросами на реализацию различного функционала висят годами.
Не так давно, я решил пересмотреть ещё раз, какие продукты могут быть полезны для пользователей моей библиотеки и был приятно удивлён, что кроме двух проектов, описанных выше появился ещё третий. Он полностью удовлетворял моим запросам и даже больше.
Workerman
4500 звёзд на гитхабе
- отсутствие зависимостей
- протоколы: websocket, http/https, tcp, сustom
- поддержка таймеров
- интеграция с react-компонентами
- поддержка windows
Первый его релиз был ещё два года назад, но почему-то всё новые и новые люди начинали пользоваться моей библиотекой для новых проектов. Я ещё могу понять, что ею пользуются на старых проектах (работает — не трогай), но на новых… — для меня это была загадка.
Если загуглить «php websocket», то первая страница — это моя статья на Хабре, а вторая — «Ratchet», который кому-то может показаться сложным и он выберет из-за этого мою библиотеку или вообще откажется от идеи делать вебсокеты.
Что ж, пришло время исправить эту досадную ошибку и донести до как можно большего количества людей о существовании такой библиотеки как Workerman и привести несколько примеров по её использованию.
На главной странице проекта в гитхабе уже есть несколько примеров. Рассмотрим один из них:
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
// Create a Websocket server
$ws_worker = new Worker("websocket://0.0.0.0:8000");
// 4 processes
$ws_worker->count = 4;
// Emitted when new connection come
$ws_worker->onConnect = function($connection)
{
echo "New connection\n";
};
// Emitted when data received
$ws_worker->onMessage = function($connection, $data)
{
// Send hello $data
$connection->send('hello ' . $data);
};
// Emitted when connection closed
$ws_worker->onClose = function($connection)
{
echo "Connection closed\n";
};
// Run worker
Worker::runAll();
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
// #### create socket and listen 1234 port ####
$tcp_worker = new Worker("tcp://0.0.0.0:1234");
// 4 processes
$tcp_worker->count = 4;
// Emitted when new connection come
$tcp_worker->onConnect = function($connection)
{
echo "New Connection\n";
};
// Emitted when data received
$tcp_worker->onMessage = function($connection, $data)
{
// send data to client
$connection->send("hello $data \n");
};
// Emitted when new connection come
$tcp_worker->onClose = function($connection)
{
echo "Connection closed\n";
};
Worker::runAll();
Чтобы запустить пример, нужно установить workerwan:
composer require workerman/workerman
Пример можно запустить с помощью команды
php test.php start
и в консоли мы увидим:----------------------- WORKERMAN -----------------------------
Workerman version:3.3.6 PHP version:7.0.15-0ubuntu0.16.10.4
------------------------ WORKERS -------------------------------
user worker listen processes status
morozovsk none websocket://0.0.0.0:8000 1 [OK]
----------------------------------------------------------------
php test.php start
php test.php start -d -демонизировать скрипт
php test.php status
php test.php stop
php test.php restart
php test.php restart -d
php test.php reload
В принципе, используя первый пример можно сделать чат на вебсокетах и других примеров не нужно. Но за несколько лет я понял, что в основном пользователям моей библиотеки был нужен пример того как можно отправить из своего кода на php уведомление выбранному пользователю, а не всем одновременно, как часто бывает в примерах.
Например:
- пользователь #1 лайкает фотографию пользователя #2 и мы хотим отправить пользователю #2 об этом уведомление, если он сейчас на сайте.
- на сайте появилось новое объявление и мы хотим отправить уведомление нашему модератору,
чтобы он его проверил
Из двух примеров выше можно собрать один, который будет делать то что нам нужно:
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
// массив для связи соединения пользователя и необходимого нам параметра
$users = [];
// создаём ws-сервер, к которому будут подключаться все наши пользователи
$ws_worker = new Worker("websocket://0.0.0.0:8000");
// создаём обработчик, который будет выполняться при запуске ws-сервера
$ws_worker->onWorkerStart = function() use (&$users)
{
// создаём локальный tcp-сервер, чтобы отправлять на него сообщения из кода нашего сайта
$inner_tcp_worker = new Worker("tcp://127.0.0.1:1234");
// создаём обработчик сообщений, который будет срабатывать,
// когда на локальный tcp-сокет приходит сообщение
$inner_tcp_worker->onMessage = function($connection, $data) use (&$users) {
$data = json_decode($data);
// отправляем сообщение пользователю по userId
if (isset($users[$data->user])) {
$webconnection = $users[$data->user];
$webconnection->send($data->message);
}
};
$inner_tcp_worker->listen();
};
$ws_worker->onConnect = function($connection) use (&$users)
{
$connection->onWebSocketConnect = function($connection) use (&$users)
{
// при подключении нового пользователя сохраняем get-параметр, который же сами и передали со страницы сайта
$users[$_GET['user']] = $connection;
// вместо get-параметра можно также использовать параметр из cookie, например $_COOKIE['PHPSESSID']
};
};
$ws_worker->onClose = function($connection) use(&$users)
{
// удаляем параметр при отключении пользователя
$user = array_search($connection, $users);
unset($users[$user]);
};
// Run worker
Worker::runAll();
код клиента client.html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script>
ws = new WebSocket("ws://127.0.0.1:8000/?user=tester01");
ws.onmessage = function(evt) {alert(evt.data);};
</script>
</head>
</html>
код отправки сообщений с нашего сайта send.php:
<?php
$localsocket = 'tcp://127.0.0.1:1234';
$user = 'tester01';
$message = 'test';
// соединяемся с локальным tcp-сервером
$instance = stream_socket_client($localsocket);
// отправляем сообщение
fwrite($instance, json_encode(['user' => $user, 'message' => $message]) . "\n");
Справедливости ради я решил написать такой же пример для ratchet, но документация мне не помогла, как 3 года назад. Зато на stackoverflow предложили немного костыльный, но рабочий вариант: соединяться из своего php-скрипта по ws-соединению. Конечно это не так же просто как соединиться с tcp-сокетом с помощью stream_socket_client и отправить сообщение с помощью fwrite. Но уже что-то.
Плюс ещё остался для меня незакрытый вопрос: поддерживает ли ratchet возможность запуска нескольких воркеров и если да, то как в таком случае отправлять сообщение одному пользователю, ведь не понятно на каком он воркере. На workerman это можно сделать так.
В общем, я выбрал для себя библиотеку Workerman и рекомендую переходить на неё пользователям моей библиотеки. Все примеры лежат на гитхабе.
Update: в комментариях рекомендуют swoole. Я натыкался на эту библиотеку ранее, но у меня сложилось ложное впечатление, что что она не поддерживает php7 и после этого она выпала из моего круга зрения. А зря. Интересная библиотека.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Комментарии (53)
DeLuxis
10.07.2017 06:59+1Забавно видеть Ratchet, Workerman и Swoole в вышестоящем комментарии выделенных цветом уже когда-то посещенных ссылок. На Workerman вовсе стоит звездочка.
Однако я использую ваше решение так как изначально начал реализовывать на нем. Пришлось в некоторых местах костылить, в частности из-за необходимости запуска рассылки в отдельном процессе. Делал тогда на 5.6, поэтому использовал форк, предварительно закрывая соединение к базе.
Сейчас перейдя на 7.0 очень хочу переписать на pthreads. И все это не вмешиваясь в исходники вашей библиотеки. Да костыльно, мне это не нравится, но времени нет.
В планах переписать websocket сервер на Golang. Преимуществ там уйма и PHP просто не предназначен для решения таких типов задач.SerafimArts
10.07.2017 09:45Преимущество у Go перед PHP ровно одно — это скорость. А какие ещё, раз уж вы говорите об "уйме"? По-мне, так наоборот.
DeLuxis
10.07.2017 09:53+11. Компилируемый, не надо тянуть интерпретатор и другие сопутствующие минусы.
2. Готовые библиотеки для сокетов, в том числе веб.
3. С легкостью держит большое количество клиентов.
4. pthreads в php все же является сторонним решением.
И мне просто он нравится, хочу задействовать по полной программе.SerafimArts
10.07.2017 11:48+1- Это преимущество высосано из пальца, будем чествными.
- Это не преимущество, под пых их на несколько порядков больше.
- Зависит от реализации, конечно же, но в целом да, вы повторили мой пункт о скорости.
- Тот же самый пункт о скорости.
В целом, кроме повтора тезиса "он быстрее" я не услышал никаких реальных оправданий его использования. Ну разве, только "он мне нравится", лично для меня это был самый убедительный аргумент. Т.к. язык, на котором нравится писать будет на порядок профитнее в умелых руках. Но это уже сугубо личное для каждого.
Если постараться оценивать объективно, то пых и мощнее как язык, и экосистема в "веб-сфере" у него на порядок взрослее, и при базе на том же swoole, есть подозрения, что будет побыстрее большинства реализаций на Go, но это вообще не точно =)
speller
11.07.2017 03:02«На порядок» = «в 10 раз». «Несколько порядков» = «в 100 раз», «в 1000 раз» и т.д. На будущее )
krocos
10.07.2017 13:58Лично меня смущает в переходе на го, не то, что птреды сторонние, ибо написаны Ваткинсом, который дофига в пхп вложил, не тем, что php резкий как незнаючто с 7ой версии, а то, что я не хочу становиться автором какой-нить навороченой либы для, например, каких-нить офисных документов… Ну, короче говоря, боязнь недостатка пакетов.
krocos
10.07.2017 11:31Тоже были порывы использовать pthreads. Но показалось хлопотным собирать php с zts постоянно. Но потом нам стало очевидным, что лучший способ параллелить задачи на php – очерди. Тем более есть такие прекрасные решения как beanstalk и rabbitmq.
Gemorroj
10.07.2017 07:14-1ssl в ratchet завезли, но в еще не выпущеной ветке 0.4 (https://github.com/ratchetphp/Ratchet/commit/369227dc1c0e5e016e729d8ab4789a0fd0ba85e4)
krocos
10.07.2017 11:32А ProxyPass через апач вроде хорошо работает, и более простое решение имхо, особенно учитывая certbot
MetaDone
10.07.2017 08:51+1существует еще https://github.com/amphp/socket
krocos
10.07.2017 11:56Ну это типа react'а, но поверх надо же еще веб-сокеты нагородить. Проще воспольльзоваться либой где уже есть этот функционал? Хотя как сокет это имхо очень прилично, но вот именно я не разобрался нормально, мне показалось, что сложней чем реакт. Я еще подумал, что проще тогда swoole.
MetaDone
10.07.2017 12:05виноват, слегка попутал со ссылкой
вот правильная — https://github.com/amphp/websocketkrocos
10.07.2017 12:37О, а я чет не стал искать, но уже всё есть, круто. Я сильно не вдавался в детали, посмотрел несколько примеров и мне кажется, что на колбэках как-то попроще будет, чем на елде выезжать :)
SerafimArts
10.07.2017 17:41+1Да Amp вообще довольно дикая штука и написана большей половиной в хипстерском функциональном стиле. Лично у меня, как и любого php-шника, пережившего "эпоху DLE" (ну т.е. докомпозеровские времена) развилась фобия подобных штук. Не, ну хоть бы в класс закатали, да статики наружу прокинули бы...
Так что учитывая всё это, я отдаю свой голос за React-based штукенции и даже не по причине йилдов, а просто код кажется более опрятным и читаемым, нежели пачка хелпер-функций ядра.
MetaDone
10.07.2017 18:07Да Amp вообще довольно дикая штука и написана большей половиной в хипстерском функциональном стиле
а можно пример? бегло пробежался по репозиториям — вроде все нормSerafimArts
10.07.2017 20:41Прям самое сердце этой либы: https://github.com/amphp/amp/blob/master/lib/functions.php Сейчас уже поопрятнее стало, с год назад вообще жуть творилась в этом файлике. Тысяча строк функций и процедурок.
mayorovp
10.07.2017 21:04+1Сейчас — обычная либа для асинхронности. Ни вижу ничего особо страшного, всего-то сделали аналог async/await через генераторы. Обычное дело для языков, где еще нет async/await, но уже есть генераторы. Через это прошли Python, C# и Javascript. Теперь вот очередь PHP.
Вот год назад, согласен — был кошмар. Только не надо называть таку свалку из функций "функциональным стилем" — в ФП любят чистые функции, а там первая же функция — с сайд-эффектом.
SerafimArts
10.07.2017 21:45"функциональный стиль" я для красного словца упомянул с некоторой толикой иронии над JS. Нынче просто они любят подобную шляпу разводить и считают это нормой. Правда, в защиту можно сказать, что почти всегда она не уезжает за пределы модуля, но не суть. Надеюсь перерастут, как PHP в своё время, исходники какого-нибудь Ангулара почти что вменяемые, даже. Далеко не уровня Symfony или Laravel, но некоторый прогресс есть.
Ну и смотрели\использовали эту либу в продакшене как раз год назад примерно, вот и запомнился этот файлик и любовь мейнтейнеров к километровй кучке функций. Потом забили болт и переехали на Газзл, т.к. на тот момент она (библиотека Amp, а точнее сборка Artax) все логи спамила ошибками (которые гасятся через собаку, что не отменяет наличие самих сообщений об ошибках). Сейчас, к слову, они тоже остались, но не в таком количестве, конечно.
krocos
10.07.2017 11:28+2Да, есть еще Swoole, но вот мы не используем его ибо у него с таск-воркерами (как нам показалось) странно сделано (жеско задается кол-во воркеров только при старте и, если передать таск несуществующему воркеру, то будет капец). Ну, а в целом Swoole – первый кандидат. Про него даже писали (точно не помню где), что из php сделали nodejs.
А вообще мы используем Ratchet. А схема работы в тяжелых случаях такая. Сам WS-сервер работает как шина, тоесть только передает сообщения. Ну и вот когда, например, приходит rpc-вызов на тяжелый таск, то это сообщение отправляется в очередь. Собственно это – элемент масштабирования. Можно поднять сколько надо воркеров, да еще и на разных серверах, если не будет хватать «сработки» при текущем количестве консумеров.
Для нас было самым большим открытием – это как вернуть ответ. Сначала консумер сообщался с ws-сервером по ws же протоколу. Но так мы имеем мега оверхэд по вермени затрачиваемому на само соединение. Особенно это заметно когда передается очень много сообщений на ws. Надо было как-то упростить схему. После продолжительных поисков был найден React Child Process Component. Он решил все проблемы с производительностью. И ответ теперь возвращается так: В loop react'а добавляется дочерний процесс, который поднимает ratchet же tcp-сервер. Тоесть консумер передает ответ через небольшую обертку над fsockopen на tcp сервер, который является процессом петли ws сервера и ему (дочернему процессу) остается только выдать сообщение в stdout и он попадет в onData обработчик дочернего процесса. А тут уже можно выбрать соединение и отправить ответ.
Тут остается только не забывать передавать sigterm на дочерние процессы-серверы-слушатели ответов, когда гасите сервер. Да, тут еще подоспела новая возможность PHP – pcntl_async_signals(). Специально для ratchet'а наверно писали, для диспатчинга в нем сигналов :)
Собственно поэтому и используем Ratchet, ибо подходит хорошо по производительности и степени удобства при конструировании сервера.mayorovp
10.07.2017 11:33-1А через очередь ответ не передать никак?
krocos
10.07.2017 11:46Через очередь в ту же самую петлю событий, ответить в тот же сокет, который прислал запрос? То есть, тут вопрос в том, как в петлю событий добавить прослушку сокетов ws и amqp?
mayorovp
10.07.2017 13:44Ну, должен же тут быть какой-то способ. Вряд ли вы — первый кому захотелось обрабатывать ws и amqp в одном цикле.
krocos
10.07.2017 14:03Так наверняка на всех этих либах есть способ, но вот я считаю, что он, в смысле понимания, должен быть прост, а, в смысле скорости, не уступать другим решениям. Мне показалось что ратчет поверх реакта с дочерними процессами в петле событий – это самое и быстрое и простое одновременно. То есть, баланс скорости и простоты соблюден хорошо.
А еще, это дает свободу творчества :) Можно в этом дочернем процессе что угодно сделать. Хоть еще дочерних процессов напихать, каждый из которых сам сокет сервер. Кароче, как я и говорил, понятное и производительное решение.mayorovp
10.07.2017 14:11Э… а что сложного в подходе вида "вот ws-сокет, вот amqp-сокет, вот мы их слушаем в цикле"?
krocos
10.07.2017 14:29Теоретически – ничего. Но это надо уметь напрограмировать так, что бы моск не вытек. Надо еще, помимо того, что добавить второй сокет на прослушку, понимать начать AMQP протокол (ну или любой другой, то есть, данные из сокета надо как-то же обрабатывать). Поэтому, нужны знания stream_socket_client и прочих функций или их оберток в той либе, которую вы используете. А тут получается, что дополнительные процессы добавляются в петлю, посредством прослушки stdout процесса. То есть, тут теория еще проще. Мы знаем, что слушаем появление данных, да еще и в красивой и удобной обертке. Я бы сравнил это с maven :) Плагины писать просто и можно делать на любом другом языке, ибо общение между плагинами и maven идет через stdout/stdin, если я не ошибаюсь. Вы понимаете преимущество возможности запустить процесс и слушать его stdput? Это же не обязательно может быть php, а, например, тот же го.
mayorovp
10.07.2017 14:39В том же цикле что и сокеты? Вы понимаете, что stdout процесса сильнее отличается от сокета чем amqp от ws?
krocos
10.07.2017 15:44Да я-то про это и говорю, что не напрямую подключать заморочки, а подключать процессы, которые сами по себе могут быть чем угодно: сокетным сервером, который консумит amqp или квэрит данные из бд, или еще чем угодно и на чем угодно написаным, хоть на джаве, хоть на го… Ну вы поняли. Главное, что бы сам вебсокет оставался тупой шиной с легким подключением этих процессов. Это, заметте, быстрая и простая передача данных. Вот пример (я его еще в другом ответе ниже оставил): gist
BoShurik
10.07.2017 14:22krocos
10.07.2017 15:09Бесспорно, вы красиво всё добавили в петлю, но:
— Это дополнительные либы
— Дополнительная теория
А что, если (тфутфуконечно) начнется усложение, увеличение нагрузки?
Надо знать как пользоваться \React\Promise\all, \Bunny\Async\Client, React\ZMQ\Context…
Не проще ли как-то так?
Как мне кажется, это более универсально. Я имею в виду добавление получения данных откуда-то в сокет.BoShurik
10.07.2017 15:45+1Надо сказать, что минусы применимы и к вашему методу :)
- Дополнительная теория (реализация очень близка к моей)
- Надо знать как пользоваться
React\ChildProcess\Process
krocos
10.07.2017 15:54С одной стороны вы правы, что надо знать «модуль» реакта, но в моем примере минус исчислимый – один, а в вашем примере, количество минусов может варьироваться в зависимости от того, что надо подключать к петле событий, тоесть:
— Теория/абстракции несравнимо проще (либо промисы/контексты/корутины/елды/ватева, либо in/out/err выхлоп процесса)
— Универсальность: можно подключить программу на любом языке, которая являться может чем угодно
Мне кажется или мы про Яблоки vs. Апельсины? :)mayorovp
10.07.2017 15:58Видите ли — дочерний процесс, он не из воздуха берется. Его тоже еще надо написать.
Если вам дочерний процесс достался от другого разработчика — то, конечно же, проще запустить его как вы показали. Но если стоит задача переслать запрос от ws-клиента в amqp-очередь, а потом вернуть клиенту ответ — то проще обойтись без дочернего процесса: будет на 1 требующий изучения слой меньше.
krocos
10.07.2017 16:04На один ли меньше? Надо «подключить» к петле промис/контекст/корутину/елду или как там называется абстракция которую запрограммировали разработчики, что бы подключить реакцию на данные из сокета… В общем не меньше. Подключать придется. Но можно изучать как подключать каждое что там надо подключить или 1 метод. Поэтому я и считаю, что это проще/меньше теории и универсальней.
mayorovp
10.07.2017 16:13Нет, вам надо один раз разобраться как передавать асинхронные события в вашу петлю, после чего использовать этот способ где угодно. Базовых абстракций всего две — колбеки и корутины, обе сводятся к месту, где вы можете написать какой пожелаете код.
PS надоело читать ругательства вместо аргументов. Ловите минус в карму за "елду".
krocos
10.07.2017 16:15В общем, суть не в том, что делает сам процесс, а в методе подключения реакции на данные в сервер. Мы изначально не разделили понятия. Я говорю про то, как подключить данные, а не как получать, когда они придут.
BoShurik
10.07.2017 16:15Мне кажется или мы про Яблоки vs. Апельсины? :)
Весьма вероятно :)
Ваша универсальность тоже имеет свои границы.
Во-первых, не понятно как быть если процесс отвалился с ошибкой? Во-вторых, придется как-то парсить stdout, т.к. он все-таки предназначен для чтения пользователем, а не машиной.krocos
10.07.2017 16:30Вы же знаете, что подключаете? Скрипт, который вы написали или сторонняя программа через обертку? В любом случае, не стоит конечно подключать что-то абсолютно не имея представления о том что там идет в вывод…
На счет ошибок: еще есть stderr.
На счет выпадения скрипта полностью. Есть возможность сделать так:
$process->on('exit', function($exitCode, $termSignal) use ($process) {
$process->start($server->loop);
// или через фабрику
});
А в целом конечно лучше через обертку запускать (хотя это тоже под большим вопросом), которая сама будет там ответственна за перезапуск отвалившихся частей.
Полагаю, лучше всё это на практике потестить.BoShurik
10.07.2017 16:47+1И тут мы пришли к тому, что вам писал mayorovp. На один слой больше за счет такой вот обертки.
Либо имеем нарушение принципа единственной ответственности, когда вебсокет сервер у нас еще занимается парсингом вывода и перезапуском упавших процессов.krocos
10.07.2017 17:21-1«нарушение принципа единственной ответственности»
Вебсокет сервер при методе, который я описываю, продолжает выполнять 1 роль – быть тупой шиной и перегонять данные от бэкенда к клиентам.
«парсингом вывода»
Это делают процессы, которые он запускает
«и перезапуском упавших процессов»
По этой де логике можно сказать, что, да, мы нарушаем принцип единой ответственности ибо сервер реагирует не только на ondata, но и на onopen, onclose, onerror, вызывает методы контроллеров при событиях…
Либо мы не понимаем друг-друга, либо вы – знатные тролли, господа :)
porn
10.07.2017 11:29+1Ещё есть voryx/thruway. Поддерживает WAMPv2. Бандл для симфони.
samizdam
11.07.2017 19:56Ну, это вообще-то либа с WAMP-роутером и клиентами, а не чисто веб-сокет.
Для вебсокета, она как раз использует Ratchet (как один из возможных транспортов).porn
11.07.2017 21:58Да, так и есть. Это по сути готовое решение, причём очень неплохое. Нам ведь бизнес-задачи нужно решать?
408dev
10.07.2017 17:36+1У автора отличная библиотека для вебсокетов, но использовав ее для интенсивных нагрузок, периодически (может быть раз в день, без видимой зависимости от внешних факторов) возникал block на пару минут на записи в поток (синхронные сокеты). Хотя все теоретические тонкие моменты были предусмотрены (проверка готовности, проверки полных отправленных данных и тп). На Ratchet-е все ок.
Но коментарий не камень в огород, а благодарность за работу — либка хорошо написана и было удобно использовать!
igordata
11.07.2017 19:25+2После знакомства с https://github.com/centrifugal/centrifugo я для себя этот вопрос закрыл раз и навсегда
Спасибо fzambiaFesor
12.07.2017 01:21Аналогично, уже 2 проекта с ним делаем, до этого писали свои поделки на socket-io. Был один проект на Ratchet года 2 назад и как-то что-то не рекомендую больше никому так делать.
samizdam
12.07.2017 11:43Был один проект на Ratchet года 2 назад и как-то что-то не рекомендую больше никому так делать.
А не поделитесь какие именно проблемы? В разработке и (или) эксплуатации?Fesor
12.07.2017 21:10В разработке он не так удобен как связка из php + nodejs + socket-io через zeromq какой. На тот момент были какие-то проблемы с реализацией протокола, всех нюансов уже не упомню. Ну и отдельная проблема — найти библиотеки с учетом event loop и т.д. практически невозможно, потому по итогу вышло всеравно так что от основного приложения мы отделили это все через zeromq. А если так — то на кой черт websockts на php непонятно.
korvinko
11.07.2017 22:15+2Когда начинали проект решили попробовать centrifugo, как оказалось этот проект идеально нам подходит. По набору возможностей и эффективности впереди Ratchet и вообще любого web socket сервера что я пробовал. Автор оперативно отвечает на issue и принимает feature request. Спасибо fzambia за плодотворное сотрудничество.
SerafimArts
Ещё Swoole потеряли