LongPolling работает так, что клиент подключается к серверу по протоколу http(s) и зависает, пока сервер не ответит. После этого создается новое подключение. Это подключение происходит абсолютно стандартным образом с отправкой всех заголовков и cookie. Для каждого такого подключения апач (или другой сервер) создает изолированный процесс.
WebSocket в свою очередь подключается к специальному серверу по отдельному протоколу ws(s). Выходит, что есть всего один процесс, в котором должна проходить авторизация, и велика вероятность утечек памяти. Но преимущества этого подхода в том, что есть постоянное подключение, что обеспечивает моментальную реакцию на события. Помимо прочего, в случае работы с WS не обязательно хранить сообщения где-то в БД, чтобы ничего не было потеряно при переподключении.
Вопрос вот в чем: есть ли что-то среднее между LP и WS?
Работает по протоколу http(s) со всеми плюшками (headers и cookies)
Можно написать простой PHP скрипт, который будет запускаться по запросу и обрабатывать все эти подключения, а не пилить полноценный WS сервер, который нужно будет еще мониторить и следить за тем, чтобы он правильно работал. (P.S. Я в проекте единственный разработчик/дизайнер/верстальщик/сис.админ/другое слово, поэтому не хочется добавлять себе еще хлопот)
Для каждого подключения спаунит отдельный процесс, изолированный от других подключений
Имеет постоянное подключение. И чтобы можно было отправлять сообщения хотя бы в одну сторону (сервер => клиент)
Подробнее о том, в чем собственно проблема.
В проекте используется framework Yii2 с местной системой авторизации и со всеми его плюшками. Описанный мною подход позволил бы мне аутентифицировать пользователя встроенными в framework методами, а саму логику внедрить в action контроллера.
В противном случае мне нужно будет написать отдельный сервер или использовать готовое решение и как-то интегрировать его с фреймворком.
Смотрел в строну Workerman. Опять же возникает вопросы аутентификации, поддержки сервера в рабочем состоянии при утечках и крашах (supervisord?), перезапуска при деплое
Если я где-то заблуждаюсь, тыкните, пожалуйста, пальцем.
Ответ
Достойных альтернатив для WebSocket в наше время считайте что нет. Или WebSocket, или всевозможные костыли. Если без костылей, то...
Первое, что нужно сделать: настроить nginx для передачи WebSocket соединений дальше по цепочке. Так, все ваши клиенты будут работать с nginx, а не напрямую с вашими другими программами. Сохраняются и используются все достоинства nginx. Не нужно использовать выделенный порт. Не нужно настраивать HTTPS дважды. Не нужно перезапускать какие-то другие программы после обновления сертификатов Let's Encrypt.
Настройка делается в четыре строчки:
location /mywsapp {
proxy_pass http://mywsbackend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Дальше, нужна альтернатива самостоятельной обработке входящих соединений WebSocket. Такая программа будет брать на себя обработку входящих WS соединений во всей их сложности, оставляя вам лишь обработку входящих сообщений и отправку исходящих.
websocketd
Например, программа websocketd работает как inetd, только для процессов. При новом соединении запускается ваша программа, которой нужно читать стандартный вход и писать в стандартный выход. Можно не читать, только писать. Пример использования в другом ответе.
";
}
Всевозможные заголовки, которые отправляет ваш клиент, доступны через переменные окружения. Например, куки видны в $_ENV['HTTP_COOKIE'] и так далее.
Вашим требованиям в части запуска процесса по факту подключения этот подход соответствует. Есть недостатки: если вам повезёт вырасти до сотен или тысяч одномоментных подключений, то это будет означать сотни и тысячи висящих в памяти процессов PHP. Впрочем, об этом можно будет подумать потом.
Кроме ограничений по памяти, постоянно работающие процессы PHP создают ещё одну проблему: если вам захочется обновить их логику, то вам потребуется механизм отключения всех таких процессов.
nchan
Если забыть про некоторые требования, то модуль nchan для nginx может ещё больше абстрагировать работу с сообщениями. Для каждого подключающегося клиента вы выделяете какой-то длинный и секретный ID (что-то типа номера почтового ящика), по которому тот подключается к nchan и ждёт сообщения. Вы, со своей стороны, по этому же ID отправляете сообщения по простому HTTP. Если у вас появится больше одного сервера, то забирать сообщения nchan может из Redis.
Установка проще не может быть:
sudo apt install libnginx-mod-nchan
Пример конфигурации.
Недостатки: увеличенная сложность конфигурации nginx и всей архитектуры системы, необходимость хранить идентификаторы клиентов за пределами $_SESSION.
Достоинства: не нужно для каждого соединения держать процесс PHP.
Список будет пополняться.
Комментариев нет:
Отправить комментарий