Reconnection handling

В современных веб-приложениях поддержка стабильного соединения с сервером критична, особенно при использовании WebSocket или EventSource для потоковой передачи данных. Фреймворк Fresh предоставляет эффективные механизмы для управления переподключениями, обеспечивая надежность и минимизацию потери данных.

Основные принципы

Переподключение — процесс автоматического восстановления соединения при его разрыве. В Fresh оно реализуется с учетом нескольких ключевых факторов:

  • Детектирование разрыва. Fresh отслеживает состояние соединений через встроенные события close, error или нестандартные состояния, предоставляемые WebSocket API.
  • Интервалы повторной попытки. Вместо мгновенного повторного подключения используется стратегия экспоненциального увеличения интервала (Exponential Backoff), что снижает нагрузку на сервер и предотвращает лавинообразные подключения.
  • Ограничение количества попыток. Для избежания бесконечных циклов переподключений задаются лимиты: максимальное число попыток и максимальный интервал ожидания.

Настройка переподключений

В Fresh конфигурация переподключения выполняется через объект reconnectionOptions. Основные параметры:

const options = {
  maxAttempts: 10,       // Максимальное количество попыток переподключения
  initialDelay: 1000,    // Начальная задержка в миллисекундах
  maxDelay: 30000,       // Максимальная задержка между попытками
  backoffFactor: 1.5     // Множитель экспоненциального роста
};

Принцип работы:

  1. При потере соединения первая попытка выполняется через initialDelay.
  2. Если повторное подключение не удалось, задержка умножается на backoffFactor.
  3. Процесс продолжается до достижения maxDelay или maxAttempts.

Обработка событий переподключения

Fresh позволяет отслеживать ключевые события жизненного цикла соединения:

  • onReconnectAttempt — вызывается перед каждой попыткой переподключения.
  • onReconnectSuccess — срабатывает при успешном восстановлении соединения.
  • onReconnectFailure — вызывается при исчерпании всех попыток.

Пример использования:

socket.onReconnectAttempt((attempt, delay) => {
  console.log(`Попытка ${attempt}, следующая через ${delay} мс`);
});

socket.onReconnectSuccess(() => {
  console.log('Соединение восстановлено');
});

socket.onReconnectFailure(() => {
  console.warn('Не удалось восстановить соединение после всех попыток');
});

Стратегии восстановления состояния

При переподключении важно не только восстановить канал связи, но и синхронизировать состояние приложения:

  • Повторная подписка на каналы. Если приложение использует несколько подписок (channels, topics), необходимо автоматически повторно подписаться после восстановления соединения.
  • Повторная отправка несохраненных данных. Любые действия пользователя, не подтвержденные сервером, должны быть повторены или синхронизированы.
  • Обновление UI. Интерфейс должен корректно отображать статус соединения, чтобы пользователь видел текущую доступность сервиса.

Пример повторной подписки:

function resubscribe(socket) {
  const channels = ['chat', 'notifications'];
  channels.forEach(channel => socket.subscribe(channel));
}

socket.onReconnectSuccess(() => {
  resubscribe(socket);
});

Защита от перегрузки сервера

При массовых отключениях пользователей существует риск одновременных попыток подключения. Fresh рекомендует:

  • Использовать рандомизацию задержки при повторных попытках (jitter) для размывания пиков нагрузки.
  • Ограничивать максимальное количество одновременных переподключений через серверные политики.
  • Комбинировать стратегию экспоненциального бэкоффа с ограничениями по количеству попыток.

Интеграция с современными API

Fresh поддерживает как WebSocket, так и EventSource. Особенности:

  • WebSocket: двунаправленная связь, возможность отправки сообщений с клиента на сервер при переподключении.
  • EventSource: односторонняя передача, требует ручного управления переподключениями и состояния.

Настройка EventSource с переподключением:

function createEventSource(url) {
  let attempts = 0;
  let delay = 1000;

  function connect() {
    const es = new EventSource(url);

    es.ono pen = () => {
      attempts = 0;
      console.log('Соединение установлено');
    };

    es.oner ror = () => {
      es.close();
      if (attempts < 10) {
        setTimeout(() => {
          attempts++;
          delay = Math.min(delay * 1.5, 30000);
          connect();
        }, delay);
      }
    };

    return es;
  }

  return connect();
}

Логирование и мониторинг

Для комплексного контроля переподключений важно:

  • Логировать все события close, error и переподключения.
  • Собрать статистику по успешным и неудачным попыткам.
  • Использовать метрики для оценки нагрузки и оптимизации интервалов.

Эффективная реализация переподключения в Fresh минимизирует потерю данных, повышает надежность и улучшает пользовательский опыт при нестабильном соединении.