Разработка WebSocket-сервиса для 1С-Битрикс
WebSocket — это постоянное двустороннее соединение между браузером и сервером. В отличие от HTTP, где клиент всегда инициирует запрос, через WebSocket сервер сам push-ит данные клиенту в реальном времени. Для 1С-Битрикс это открывает сценарии, которые невозможны стандартными средствами: мгновенные уведомления о новом заказе без перезагрузки страницы, онлайн-чат между покупателем и менеджером, обновление остатков в корзине при изменении на складе.
Почему не polling
Альтернатива WebSocket — polling: браузер каждые N секунд запрашивает «есть ли новые данные?». При 100 одновременных пользователях и интервале 5 секунд — 20 запросов в секунду к серверу. Большинство пустые. WebSocket держит одно соединение на клиента: сервер отправляет данные только когда они есть.
Long polling (HTTP-соединение держится открытым до появления данных) — компромисс. Проще реализовать, но хуже масштабируется.
Технологический стек
Ratchet (PHP). Библиотека для WebSocket на чистом PHP (cboden/ratchet). Работает как отдельный long-running процесс на нестандартном порту (8080, 9090). Простая интеграция с существующим PHP-кодом Битрикс.
Swoole. PHP-расширение с высокопроизводительным асинхронным сервером. Выдерживает тысячи соединений. Требует установки расширения на сервере.
Node.js + Socket.io. Отдельный сервис на Node.js. Хорошая экосистема, высокая производительность. Интеграция с Битрикс — через Redis pub/sub: Битрикс публикует событие в Redis, Node.js получает и рассылает клиентам.
Centrifugo. Готовый WebSocket-сервер (Go), специально для real-time приложений. Поддерживает комнаты (channels), history, присутствие (presence). Самый быстрый путь к production-ready решению без написания WebSocket-сервера с нуля.
Архитектура с Centrifugo
Centrifugo — отдельный сервис, Битрикс взаимодействует с ним через HTTP API:
Браузер ←→ WebSocket ←→ Centrifugo ←→ Redis
↑
Битрикс публикует события
При событии в Битрикс (новый заказ, изменение статуса) — PHP-код публикует в канал Centrifugo:
$centrifugo = new CentrifugoClient('http://centrifugo:8000', $apiKey);
$centrifugo->publish('orders:' . $managerId, [
'event' => 'new_order',
'order_id' => $orderId,
'customer' => $customerName,
'amount' => $amount,
]);
Браузер, подписанный на канал orders:{managerId}, мгновенно получает событие без polling.
Авторизация каналов. Centrifugo поддерживает JWT-авторизацию каналов. При подключении браузер передаёт JWT, Centrifugo проверяет через эндпоинт Битрикс — имеет ли этот пользователь право подписаться на канал.
Архитектура с Ratchet
Для более тесной интеграции с Битрикс — собственный WebSocket-сервер на Ratchet. Запускается как daemon:
php /local/cli/websocket_server.php
// websocket_server.php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
$server = IoServer::factory(
new HttpServer(
new WsServer(
new BitrixWebSocketHandler()
)
),
8080
);
$server->run();
BitrixWebSocketHandler реализует \Ratchet\MessageComponentInterface:
-
onOpen($conn)— новое соединение, авторизуем пользователя -
onMessage($from, $msg)— сообщение от клиента -
onClose($conn)— закрытие соединения -
onError($conn, $e)— ошибка
Хранение соединений: SplObjectStorage с привязкой user_id → connection. При публикации события находим соединения нужного пользователя и отправляем данные.
Связь с Битрикс: Ratchet работает в отдельном процессе и не имеет доступа к сессиям PHP. Данные из Битрикс передаём через Redis pub/sub — Битрикс публикует, Ratchet читает и рассылает клиентам.
Сценарии использования
Уведомления менеджера о новом заказе. При создании заказа Битрикс публикует событие в канал менеджера. Браузер показывает toast-уведомление без перезагрузки страницы.
Онлайн-чат. Покупатель пишет в чат на сайте → сообщение через WebSocket → Битрикс записывает в БД → уведомление оператору через WebSocket. Стандартный открытый канал Битрикс24 работает аналогично, но для интернет-магазина на коробочном Битрикс нужна кастомная реализация.
Обновление остатков. При изменении остатков на складе (через 1С-обмен) — push всем клиентам, у которых товар в корзине. «К сожалению, товар X только что закончился на складе».
Статус заказа в реальном времени. Покупатель на странице «Мой заказ» — при изменении статуса заказа (курьер выехал, доставлен) страница обновляется без перезагрузки.
Frontend: подключение к WebSocket
const ws = new WebSocket('wss://example.com:8080');
ws.onopen = () => {
// Авторизуемся, передаём JWT
ws.send(JSON.stringify({ type: 'auth', token: userJwt }));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.event === 'new_order') {
showNotification(`Новый заказ #${data.order_id} на ${data.amount} ₽`);
}
};
ws.onclose = () => {
// Переподключение с exponential backoff
setTimeout(() => connectWebSocket(), 3000);
};
Переподключение при разрыве — обязательно. Мобильные сети нестабильны, соединение может прерваться.
Деплой и инфраструктура
WebSocket-сервер — это long-running процесс, не FPM-воркер. Запуск через Supervisor (автоматический рестарт при падении):
[program:websocket]
command=php /var/www/local/cli/websocket_server.php
autostart=true
autorestart=true
stderr_logfile=/var/log/websocket.err.log
Nginx проксирует WebSocket-соединения на Ratchet/Centrifugo:
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_read_timeout 86400;
}
Масштабирование: при нескольких серверах приложения нужен Redis pub/sub как шина между серверами — клиент подключён к серверу А, событие пришло на сервер Б, Redis доставляет на сервер А.
Этапы разработки
| Этап | Содержание | Срок |
|---|---|---|
| Выбор технологии | Centrifugo vs Ratchet vs Node.js, оценка инфраструктуры | 2–3 дня |
| WebSocket-сервер | Базовая инфраструктура, авторизация | 1 неделя |
| Интеграция с Битрикс | Redis pub/sub, публикация событий из PHP | 3–5 дней |
| Frontend-клиент | JS-клиент, переподключение, обработка событий | 3–5 дней |
| Конкретные сценарии | Уведомления, чат, обновление данных | 1–2 недели |
| Деплой и мониторинг | Supervisor, Nginx, метрики соединений | 3–5 дней |
WebSocket — инфраструктурное решение, которое добавляет сложность. Оправдано там, где задержка в несколько секунд критична для UX. Для уведомлений, которые можно показать при следующем переходе по странице, — избыточно.







