> Что такое 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.
Процесс установки соединения:
-
Клиент отправляет обычный HTTP GET запрос с заголовками:
Upgrade: websocketConnection: UpgradeSec-WebSocket-Key- случайная строка в base64Sec-WebSocket-Version: 13
-
Сервер проверяет заголовки, вычисляет
Sec-WebSocket-Accept(SHA-1 от ключа + константа GUID, затем base64) и отвечает статусом101 Switching Protocols. -
После этого 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-соединения, иначе они будут рваться.
Пример кода
GOpackage mainimport ("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.
> Похожие задачи по backend
Какой план действий при перегрузке CPU и срабатывании алерта
В чем разница наследования в Go и классического наследования
Писали ли интеграционные тесты или моки для сервисов с Dependency Injection
Что лучше использовать в Go: int8, int32, int64 или просто int
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью