Определение простыми словами
WebSocket — это сетевой протокол, который превращает обычное HTTP-соединение в постоянный двунаправленный канал. После рукопожатия клиент и сервер начинают обмениваться кадрами в обе стороны без накладных расходов на новые запросы и заголовки. Стандарт зафиксирован в RFC 6455, поверх него работают популярные библиотеки socket.io, ws, SignalR и Phoenix Channels.
В отличие от привычного REST-цикла «запрос — ответ», WebSocket держит сессию открытой и позволяет серверу пушить события клиенту по мере их появления. Это снимает задержку, связанную с поллингом, и сокращает трафик: вместо десятков HTTP-запросов в минуту канал передаёт компактные бинарные или текстовые кадры.
Сравнение с альтернативами
| Технология | Направление | Транспорт | Где применяется |
|---|---|---|---|
| WebSocket | Полнодуплекс | TCP, апгрейд из HTTP/1.1 | Чаты, торговые терминалы, мультиплеер |
| Server-Sent Events | Только сервер → клиент | HTTP/1.1 long-lived | Ленты новостей, нотификации |
| Long Polling | Псевдо-двунаправленный | HTTP-запросы | Старые браузеры, простые уведомления |
| HTTP/2 Streams | Мультиплекс на сервер | Бинарный HTTP/2 | gRPC и push API |
Кейсы использования
- Чаты и мессенджеры с мгновенной доставкой сообщений и индикаторами «печатает».
- Финансовые терминалы и стримы биржевых котировок с обновлением десятки раз в секунду.
- Многопользовательские игры и совместные редакторы в духе Figma.
- Дашборды мониторинга, где метрики приходят с агентов в реальном времени.
- Сигналинг для WebRTC при установке P2P-видеозвонков.
Негативный сценарий: открытый WebSocket без heartbeat-кадров за прокси с короткими таймаутами молча умирает через минуту, и клиент думает, что соединение живое. Без серверной аутентификации каждого кадра канал становится уязвим к hijack-атакам — токен нужно проверять не только при апгрейде, но и при каждой команде.
Технические детали
# минимальный echo-сервер на Node.js c пакетом ws
cat > server.js <<'EOF'
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', ws => {
ws.on('message', msg => ws.send(`echo: ${msg}`));
setInterval(() => ws.ping(), 30000);
});
EOF
node server.js
# проксирование через nginx с поддержкой апгрейда
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 3600s;
}
# проверка апгрейда вручную
curl --include --no-buffer
--header "Connection: Upgrade"
--header "Upgrade: websocket"
--header "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ=="
--header "Sec-WebSocket-Version: 13"
http://example.com/ws/
Соединение начинается с обычного HTTP-запроса с заголовком Upgrade: websocket. Сервер отвечает кодом 101 Switching Protocols, и дальше канал говорит на бинарном протоколе из кадров с маской. Для продакшна обязательно включают TLS, схема меняется на wss://, а на стороне nginx увеличивают proxy_read_timeout, иначе балансировщик будет рвать длинные соединения.
🔥 Где это применяется
Частые вопросы
Чем WebSocket лучше long polling?
WebSocket держит одно постоянное соединение и не передаёт HTTP-заголовки на каждый кадр. За счёт этого задержка падает до миллисекунд, а нагрузка на сервер снижается на порядок при тысячах онлайновых клиентов.
Нужен ли WebSocket для редкого пуша?
Если событий мало и они идут только от сервера к клиенту, проще обойтись Server-Sent Events. Они работают через обычный HTTP, не требуют апгрейда и легко проксируются любыми CDN.
Как масштабировать WebSocket?
Используйте sticky-сессии на балансировщике, общий брокер сообщений (Redis Pub/Sub, NATS, Kafka) и горизонтальный автоскейл. Каждый узел держит свои соединения, а события расходятся через брокер.