PHP WebSocket: как сделать WebSocket на PHP

Короткий ответ: WebSocket на PHP делают не как обычный PHP-файл, который запускается на каждый запрос, а как долгоживущий процесс. Он постоянно слушает порт, принимает подключения и рассылает сообщения. Для этого используют библиотеки или runtimes: Ratchet, Swoole, RoadRunner, ReactPHP-стек и похожие решения

Почему обычный PHP-подход не подходит

Классический PHP под Apache/PHP-FPM живет в модели:

HTTP request -> PHP обработал -> response -> процесс свободен

WebSocket требует другого:

connect -> keep connection open -> messages -> close

Поэтому WebSocket-сервер на PHP должен быть отдельным процессом, который вы запускаете через CLI, supervisor или systemd

Минимальная схема

Browser -> Nginx -> PHP WebSocket process

Nginx принимает wss://, прокидывает Upgrade-заголовки, а PHP-процесс слушает внутренний порт

Примерный стек

Для учебного проекта можно посмотреть Ratchet, но для нового продакшена важно проверить актуальность библиотеки и совместимость с вашей версией PHP

Общая идея:

composer require cboden/ratchet

Затем создается класс обработчика сообщений и запускается сервер из CLI. Для серьезного проекта дополнительно нужны логирование, контроль памяти, reconnect-логика клиентов, авторизация и supervisor/systemd

Что хранить в PHP WebSocket сервере

Сервер может хранить список подключенных клиентов:

private SplObjectStorage $clients;

При подключении клиент добавляется, при отключении удаляется, при сообщении сервер рассылает данные нужным клиентам

Но не храните важное состояние только в памяти WebSocket-процесса. После перезапуска оно исчезнет. Пользователи, комнаты, сообщения и права должны жить в базе или другом устойчивом хранилище

Авторизация клиента

PHP WebSocket сервер должен понимать, кто подключился. Один из вариантов — передать короткоживущий токен при подключении или первым сообщением:

{
  "type": "auth",
  "token": "temporary-token"
}

После проверки сервер связывает соединение с user id. Не стоит доверять только параметру userId из клиента: его легко подменить. Проверяйте токен на стороне сервера и не отправляйте пользователю чужие события

Масштабирование

Один PHP WebSocket процесс может обслуживать ограниченное количество клиентов. Если процессов несколько, им нужен общий брокер: Redis, очередь сообщений или другой pub/sub. Тогда событие из backend-приложения попадет всем нужным WebSocket-процессам

Как связать с обычным PHP-приложением

Обычное приложение может писать событие в Redis или базу, а WebSocket-процесс читать и рассылать его клиентам:

Laravel/Symfony controller -> Redis pub/sub -> PHP WebSocket process -> Browser

Так HTTP-часть не должна знать о конкретных соединениях. Она публикует событие, а долгоживущий процесс доставляет его тем, кто сейчас подключен

Nginx proxy

location /ws {
  proxy_pass http://127.0.0.1:8080;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
  proxy_set_header Host $host;
}

Для публичного сайта добавьте TLS и используйте wss://

Частые ошибки

Первая ошибка — пытаться сделать WebSocket внутри обычного контроллера Laravel/Symfony без отдельного процесса

Вторая ошибка — запускать сервер в SSH-сессии и закрывать терминал. Используйте systemd или supervisor

Третья ошибка — не удалять отключенных клиентов из коллекции

Четвертая ошибка — не проверять совместимость библиотеки с текущей версией PHP

Пятая ошибка — отдавать WebSocket наружу без wss и авторизации

Шестая ошибка — смешивать PHP-FPM и WebSocket-процесс как одно и то же. Это разные процессы с разным жизненным циклом

Самопроверка

Поднимите PHP WebSocket сервер на локальном порту, подключитесь из браузера, отправьте ping, получите ответ. Затем перезапустите процесс и убедитесь, что он снова принимает подключения через supervisor/systemd

Что почитать дальше по WebSocket

Если нужен общий маршрут по теме, откройте рубрику WebSocket. Для соседних задач пригодятся эти разборы:

Оцените статью
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x