> Что такое WebSocket и как он работает (Go)
Уровень: junior · Роль: backend · Категория: Технические вопросы
Компании: Aston
Стек: Go
> Пример ответа
Короткий ответ
WebSocket - это протокол поверх TCP, который обеспечивает постоянное двустороннее соединение между клиентом и сервером. В отличие от HTTP, где каждый запрос открывает новое соединение, WebSocket держит канал открытым, позволяя обеим сторонам отправлять сообщения в любой момент без повторного handshake. Работает через HTTP-апгрейд: клиент отправляет обычный HTTP-запрос с заголовком Upgrade: websocket, сервер отвечает 101 Switching Protocols, и дальше идёт бинарный или текстовый обмен кадрами.
Подробное объяснение
WebSocket решает проблему HTTP, который является request-response протоколом: сервер не может инициировать отправку данных клиенту без запроса. Раньше для этого использовали polling или long polling, но это создавало лишнюю нагрузку и задержки.
Процесс установки соединения:
- Клиент отправляет HTTP-запрос с заголовками
Upgrade: websocketиConnection: Upgrade, плюсSec-WebSocket-Key(случайная строка в base64). - Сервер проверяет заголовки, вычисляет
Sec-WebSocket-Acceptкак SHA-1 от конкатенации ключа и GUID258EAFA5-E914-47DA-95CA-C5AB0DC85B11, затем base64. - Сервер отвечает
101 Switching Protocolsс заголовкомSec-WebSocket-Accept. - Соединение переключается на WebSocket-протокол, дальше идёт обмен кадрами (frames).
Кадр состоит из заголовка (FIN, opcode, mask, length) и payload. Клиентские кадры обязательно маскируются (mask bit = 1), серверные - нет. Opcode определяет тип: text (1), binary (2), close (8), ping (9), pong (10).
Соединение закрывается через close-кадр, после чего TCP-соединение завершается.
В Go для работы с WebSocket обычно используют библиотеку gorilla/websocket или стандартный пакет golang.org/x/net/websocket, но gorilla - де-факто стандарт.
На практике
Для backend-разработчика на Go важно понимать:
- WebSocket-соединение занимает ресурсы: горутину на соединение, память на буферы. Нужно управлять лимитами и таймаутами.
- Нужно обрабатывать ping/pong, чтобы определять мёртвые соединения.
- Конкурентный доступ к соединению: писать в соединение можно только из одной горутины, иначе будет race condition. Обычно используют канал для отправки сообщений.
- WebSocket не гарантирует доставку и порядок - это не message queue. Для надёжности поверх WebSocket строят свои протоколы (ack, retry).
- Балансировка нагрузки: WebSocket-соединение привязано к конкретному серверу, нужен sticky sessions или отдельный pub/sub брокер (Redis, NATS) для синхронизации между инстансами.
Пример кода
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.Println(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 и отличие от HTTP. Упомяни, что WebSocket работает поверх TCP, а не заменяет его. Скажи про кадры и маскирование. Если спросят про Go - упомяни gorilla/websocket и проблему конкурентного доступа к соединению. Не углубляйся в бинарный формат кадра, если не просят. Хорошо показать понимание, зачем нужен ping/pong и как обрабатывать закрытие соединения.
Что проверяет интервьюер
- Понимание разницы между HTTP и WebSocket.
- Знание handshake-процедуры и заголовков.
- Понимание модели обмена сообщениями (full-duplex).
- Осознание ограничений: нет гарантии доставки, ресурсоёмкость, проблемы с масштабированием.
- Практические навыки: как обрабатывать конкурентность, таймауты, закрытие соединений.
Типичные ошибки
- Путают WebSocket с HTTP/2 server push или SSE (Server-Sent Events). SSE - односторонний, только сервер → клиент.
- Думают, что WebSocket сам по себе обеспечивает надёжную доставку - это не так, нужен свой слой подтверждений.
- Не учитывают, что клиентские кадры маскируются, а серверные нет - это требование протокола, а не деталь реализации.
- Пишут в соединение из нескольких горутин без синхронизации - это приводит к панике или повреждению данных.
- Забывают про heartbeat (ping/pong) и соединение молча умирает, а сервер держит мёртвые горутины и память.
> Похожие задачи по backend
Использовали ли Kotlin для написания автотестов
Приведите пример инкапсуляции
Как реализовать миграции базы данных
Что такое функция
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью