> Что такое WebSocket и как он работает (Go)

Уровень: junior · Роль: backend · Категория: Технические вопросы

Компании: Wildberries

Стек: Go

> Пример ответа

Короткий ответ

WebSocket - это протокол поверх TCP, который обеспечивает постоянное двустороннее соединение между клиентом и сервером. В отличие от HTTP, где каждый запрос открывает новое соединение, WebSocket держит один канал открытым для обмена сообщениями в обе стороны. Работает так: клиент отправляет HTTP-запрос с заголовком Upgrade: websocket, сервер отвечает 101 Switching Protocols, после чего соединение переходит в режим full-duplex и остаётся активным до явного закрытия одной из сторон.

Подробное объяснение

WebSocket решает проблему HTTP, который является request-response протоколом: сервер не может сам инициировать отправку данных клиенту без запроса. Для real-time приложений (чаты, уведомления, котировки) это неудобно - приходилось использовать polling или long-polling.

Процесс установки соединения:

  1. Клиент отправляет обычный HTTP GET запрос с заголовками:

    • Upgrade: websocket
    • Connection: Upgrade
    • Sec-WebSocket-Key - случайная строка в base64
    • Sec-WebSocket-Version: 13
  2. Сервер проверяет заголовки, вычисляет Sec-WebSocket-Accept (SHA-1 от ключа + константа GUID, затем base64) и отвечает статусом 101 Switching Protocols.

  3. После этого TCP-соединение переходит в режим WebSocket. Данные передаются в виде фреймов (frames), каждый из которых имеет заголовок с opcode (text, binary, close, ping, pong).

Ключевые особенности:

  • Full-duplex - обе стороны могут отправлять данные в любой момент.
  • Низкий overhead - после handshake нет HTTP-заголовков, только лёгкие фреймы.
  • Поддержка бинарных данных - можно передавать не только текст, но и произвольные байты.
  • Keep-alive - соединение живёт, пока одна из сторон не отправит close frame или не оборвётся TCP.
  • Ping/Pong - встроенный механизм для проверки живости соединения и обхода NAT/proxy timeouts.

В Go для работы с WebSocket чаще всего используют библиотеку gorilla/websocket (хотя она в режиме maintenance) или nhooyr.io/websocket (теперь github.com/coder/websocket). Стандартная библиотека Go не имеет встроенной поддержки WebSocket.

На практике

Для backend-разработчика на Go важно понимать:

  • WebSocket-соединения держат ресурсы (goroutine на соединение, память на буферы). Нужно ограничивать количество одновременных соединений и устанавливать read/write deadlines.
  • Нужно обрабатывать ping/pong - иначе соединения будут висеть мёртвым грузом.
  • При масштабировании (несколько инстансов сервиса) нужен бэкенд для обмена сообщениями между инстансами - например, Redis pub/sub или NATS.
  • WebSocket не заменяет HTTP - это дополнение для real-time сценариев. REST остаётся для обычных запросов.
  • За прокси и балансировщиками нужно настраивать таймауты на idle-соединения, иначе они будут рваться.

Пример кода

GO
package main
import (
"log"
"net/http"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func(r *http.Request) bool {
return true // для примера, в проде проверяйте origin
},
}
func handleWS(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Print("upgrade failed:", err)
return
}
defer conn.Close()
for {
messageType, message, err := conn.ReadMessage()
if err != nil {
log.Println("read error:", err)
break
}
log.Printf("received: %s", message)
if err := conn.WriteMessage(messageType, message); err != nil {
log.Println("write error:", err)
break
}
}
}
func main() {
http.HandleFunc("/ws", handleWS)
log.Fatal(http.ListenAndServe(":8080", nil))
}

Как отвечать на собеседовании

Начните с короткого определения, затем опишите handshake - это покажет понимание того, как WebSocket работает на уровне протокола. Упомяните отличие от HTTP и от polling. Если спросят про Go - скажите, что используете gorilla/websocket или coder/websocket, и что в стандартной библиотеке WebSocket нет.

Хорошо добавить пример из практики: чат, уведомления, live-таблица. Покажите, что понимаете проблемы - управление соединениями, таймауты, масштабирование.

Что проверяет интервьюер

Интервьюер хочет убедиться, что вы:

  • Понимаете разницу между HTTP и WebSocket, и когда что применять.
  • Знаете, как происходит handshake и что такое 101 Switching Protocols.
  • Понимаете модель full-duplex и фреймовую структуру сообщений.
  • Осознаёте практические проблемы: лимиты соединений, deadlines, ping/pong, масштабирование.
  • Умеете написать простой echo-сервер на Go с использованием библиотеки.

Типичные ошибки

  • Путаница с HTTP/2 Server Push или SSE (Server-Sent Events) - это разные вещи.
  • Утверждение, что WebSocket работает поверх HTTP - на самом деле только handshake через HTTP, дальше чистый TCP.
  • Игнорирование CheckOrigin - в проде это дыра в безопасности.
  • Отсутствие обработки ping/pong - соединения будут разрываться.
  • Непонимание, что WebSocket-соединение занимает ресурсы - нельзя держать миллионы соединений на одном инстансе без планирования.
  • Забывают про defer conn.Close() или не обрабатывают ошибки чтения/записи - это приводит к утечкам goroutine.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью