🔧

Масштабирование WebSocket-серверов на Go

Jul 9, 2024

Лекция: Масштабирование WebSocket-серверов на Go

Введение

Лектор: Александр Малин (компания Авито) Тема: Масштабирование WebSocket-серверов

  • Проект «Центрифуга»: Популярный сервер real-time сообщений с WebSocket протоколом.

    • Используется в Sports.ru, Юла, проектах Mail.ru, Goru, Avito и за рубежом (пример: Spurtan).
    • Уже 2 версия, базируется на библиотеке Centrifugal.
  • Работа в мессенджере Avito: WebSocket протокол, 12 миллионов пользователей, обслуживает современные приложения.

Что такое WebSocket?

  • Full-duplex соединение: Двусторонняя передача данных между клиентом и сервером.
  • Использование: Чаты, совместные приложения, стриминг акций и так далее.
  • Принципы работы:
    • Начало с HTTP-1.1 запроса, потом апгрейд до WebSocket.
    • Клиент и сервер обмениваются заголовками для установления TCP соединения.

Почему использовать WebSocket?

  • Простой протокол, поддержка всех современных платформ и браузеров.
  • Минимальный overhead (2–8 байт на фрейм).

Задачи нагруженного WebSocket-сервера

  1. Поддержка большого количества соединений.
  2. Отправка большого количества сообщений.
  3. Fall back на случай недоступности WebSocket соединения (fallback механизмы).
  4. Аутентификация и валидация соединений.
  5. Переживание массового reconnect при большом количестве пользователей.
  6. Не терять сообщения при reconnect.

Подготовка операционной системы

  • Лимит файловых дескрипторов: Поднять лимит, если нужно больше соединений.
  • Эфемерные порты: Увеличение лимита портов, если они исчерпываются.
  • Conntrack table: Увеличение размера таблицы соединений.
  • Настройка сетевого стека: Оптимизация для высокой нагрузки.

Уровень приложения

  • Golang библиотеки WebSocket:
    • Gorilla WebSocket (де-факто стандарт).
    • Gobwas WS (возможность оптимизаций).
    • Nhooyr WebSocket (новая, активно развивающаяся).
  • Оптимизация потребления памяти:
    • Переиспользование буферов.
    • Использование zero-copy upgrade (в Gobwas WS).
    • Лимит контекста: Создание кастомного контекста для управления жизненным циклом соединения.
  • Форматы сериализации: JSON, Protobuf, MessagePack.
  • Инвалидизация соединений: Пользователь может быть разлогинен, заблокирован и т.д.

Управление масштабируемостью

  • Введение брокера сообщений:
    • Работа через модель pub-sub.
    • Рекомендации по выбору брокеров: Redis (стабильный и производительный), Tarantool, Kafka (разные подходы и сценарии).

Борьба с массовым reconnect

  • Exponential backoff: Клиенты reconnect'ятся с увеличивающимися интервалами.
  • Bounded semaphore: Для управления конкурентным доступом к ресурсам.
  • JSON Web Tokens (JWT): Использование токенов с сроком действия для снижения нагрузки на backend при reconnect.

Заключение

  1. Использование эффективных форматов сериализации.
  2. Масштабирование через брокер сообщений.
  3. Работа с массовым reconnect через экспоненциальные схемы и ограничение семафорами.
  4. Центрифуга как готовое решение для масштабирования WebSocket-серверов.
  • Демонстрационный стенд: 1 миллион WebSocket соединений, 30 млн. сообщений в минуту, коннект-дисконнект рейт 200 тыс./сек.

Благодарности и вопросы

  • Лучший вопрос: про распределение нагрузки по топикам.