Введение
Сбои сети, смена устройств и ошибки согласования медиаданных могут затронуть любое приложение для видеосвязи в реальном времени. Надежное приложение должно рассматривать подобные ситуации как ожидаемые сбои и иметь четкую стратегию восстановления для каждого из них.
В этой статье рассматриваются практические шаблоны повторных попыток и восстановления для Vonage Video API Web SDK. Вы узнаете, как обрабатывать ошибки при подключении к сеансу, публикации медиаданных, подписке на потоки и устранении проблем с захватом аудио.
Главный принцип прост: повторяйте попытку только тогда, когда это безопасно, очищайте ресурсы при необходимости и предотвращайте одновременный запуск нескольких попыток восстановления.
Безопасный повторный вызов session.connect()
Попытка подключения может завершиться ошибкой из-за временных проблем с сетью или сигнализацией. Когда ваше приложение решает повторить попытку подключения, сначала убедитесь, что предыдущая попытка была корректно завершена с очисткой ресурсов.
Отключение перед повторной попыткой
Вызовите session.disconnect(), прежде чем запускать новую попытку session.connect(). Это гарантирует, что ваше приложение не продолжит выполнять повторные попытки с устаревшим состоянием сеанса.
Вместо того чтобы встраивать логику повторных попыток непосредственно в каждую операцию API, вы можете использовать многоразовый вспомогательный компонент (хэлпер).
Функция shouldRetry определяет, безопасно ли повторить операцию при возникновении ошибки. Возвращайте true только для тех ошибок, которые ваше приложение определило как временные или устранимые. Функция getDelay управляет временем ожидания перед каждой новой попыткой, что позволяет настраивать тайминги без изменения самой логики повтора. Значение maxAttempts задает общее количество попыток.
Такой подход возвращает успешный результат сразу же после успешного выполнения операции и прекращает попытки, если ошибку небезопасно повторять или достигнуто максимальное число попыток.
Затем вы можете использовать хэлпер для управления попытками подключения:
В этом примере используется максимум три попытки с линейной задержкой. Задержки составляют:
- 3 секунды перед второй попыткой
3 секунды перед второй попыткой
- 6 секунд перед третьей попыткой
6 секунд перед третьей попыткой
Если вашему приложению требуется другая политика восстановления, сделайте конфигурацию повторов настраиваемой, а не изменяйте саму реализацию.
Обратите внимание, что количество попыток и интервалы времени между ними носят рекомендательный характер. Вы всегда можете скорректировать их для достижения желаемой производительности на вашей стороне.
Понимание повторных попыток на уровне SDK и приложения
SDK может уже выполнять внутреннее восстановление на некоторых этапах подключения. Поэтому логику повторных попыток на уровне приложения следует рассматривать как дополнительный уровень восстановления.
Прежде чем полагаться на определенное поведение повтора, проверьте актуальное поведение SDK в соответствующей документации Vonage Video API.
Обработка ошибок session.publish()
Публикация медиаданных состоит из нескольких этапов. Разделение этих этапов помогает решить, должно ли приложение повторить попытку, запросить действие от пользователя или пересоздать паблишер.
Понимание инициализации паблишера и публикации
Рабочий процесс публикации может включать две разные операции:
- OT.initPublisher() инициализирует доступ к медиаустройствам и создает паблишер.
OT.initPublisher() инициализирует доступ к медиаустройствам и создает паблишер.
- session.publish(publisher) публикует эти медиаданные в сеансе.
session.publish(publisher) публикует эти медиаданные в сеансе.
Проблемы во время инициализации могут потребовать иной стратегии восстановления, чем проблемы, возникающие при публикации уже инициализированного паблишера.
Например, проблема с доступом к камере обычно требует вмешательства пользователя. Временный сбой сети может быть кандидатом на повторную попытку.
Избегайте одинакового отношения ко всем ошибкам публикации.
Классификация ошибок перед повторной попыткой
Ошибки публикации могут иметь разные причины. Некоторые из них могут быть связаны с временными условиями сети или согласования медиаданных, в то время как другие требуют действий пользователя или изменений в приложении.
Следующие ошибки подходят для повторных попыток:
Ошибка
Описание
OT_TIMEOUT (1500)
Тайм-аут согласования ICE/SDP
OT_ICE_WORKFLOW_FAILED
Сбой рабочего процесса ICE
OT_CREATE_PEER_CONNECTION_FAILED
Сбой настройки однорангового соединения
OT_MEDIA_ERR_ABORTED
Операция с медиаданными была прервана
OT_MEDIA_ERR_NETWORK
Ошибка сети передачи медиаданных
OT_MEDIA_ERR_DECODE
Ошибка декодирования медиаданных
OT_MEDIA_ERR_SRC_NOT_SUPPORTED
Источник медиаданных не поддерживается
OT_SET_REMOTE_DESCRIPTION_FAILED
Сбой удаленного описания SDP
OT_UNEXPECTED_SERVER_RESPONSE
Непредвиденный ответ сервера, который может быть временным
Ошибки, требующие вмешательства пользователя или восстановления приложения, не должны повторяться автоматически:
Ошибка
Рекомендуемое действие
OT_NOT_CONNECTED
Убедитесь, что сеанс полностью подключен перед началом публикации
OT_PERMISSION_DENIED
Попросите пользователя предоставить разрешение на использование камеры или микрофона
Используйте явный список ошибок, которые ваше приложение считает безопасными для повторной попытки:
Использование явного списка разрешенных элементов (allowlist) безопаснее, чем повторение попытки при любой ошибке, которая не помечена как неудаляемая. Неизвестные ошибки следует логировать и исследовать, а не повторять автоматически.
Перед публикацией убедитесь, что эти имена ошибок и рекомендации по повторным попыткам соответствуют версии JavaScript SDK Vonage Video API, используемой вашим приложением.
Реализация безопасной стратегии повтора публикации
В следующем примере операция публикации отделена от политики повторных попыток:
Здесь shouldRetry использует функцию isRetryablePublishError для повтора только тех ошибок, которые входят в явный список разрешенных. Функция getDelay увеличивает интервал ожидания для последующих попыток, начиная с 2 секунд. Измените maxAttempts или значения задержки в соответствии с требованиями вашего приложения к восстановлению.
В результате временные сбои публикации могут быть повторены без автоматического повторения ошибок, требующих вмешательства пользователя или изменения приложения.
Этот пример делает политику повторов более простой для изменения без модификации самой операции публикации.
Он также делает различия между попытками (attempts) и повторами (retries) очевидными. В этом примере maxAttempts: 3 означает, что приложение делает не более трех попыток в общей сложности.
Предотвращение одновременных попыток публикации
Не допускайте одновременного выполнения нескольких операций session.publish() для одного и того же процесса публикации.
Простая защита состояния может предотвратить одновременные попытки восстановления:
Защитная переменная isPublishing предотвращает запуск второго процесса публикации, пока выполняется первый. Если публикация уже идет, функция немедленно возвращает управление. Блок finally сбрасывает состояние защиты независимо от того, завершилась ли публикация успехом или ошибкой, позволяя запустить последующую попытку публикации.
Эта простая защита полезна для единичного процесса публикации. В более крупном приложении с несколькими паблишерами используйте раздельное состояние для каждого паблишера вместо одной общей переменной.
В крупном приложении рассмотрите возможность управления этим состоянием в специализированном компоненте жизненного цикла паблишера, а не с помощью одной глобальной переменной.
Очистка неисправных паблишеров
Паблишер, который невозможно использовать повторно, следует очистить перед тем, как ваше приложение создаст замену.
Тем не менее, избегайте скрытой замены паблишера внутри обработчика событий без обновления остального состояния приложения.
Вместо этого централизуйте создание и настройку паблишера.
Этот паттерн гарантирует, что каждый новый издатель получает одинаковые обработчики событий и конфигурацию.
Например, если вы воссоздаете издателя, не забудьте зарегистрировать обработчики для таких событий, как:
- destroyed
destroyed
- mediaStopped
mediaStopped
- audioAcquisitionProblem
audioAcquisitionProblem
- audioAcquisitionProblemResolved
audioAcquisitionProblemResolved
Вновь созданный издатель является новым объектом и не наследует автоматически слушателей, привязанных к предыдущему издателю.
Тщательно обрабатывайте событие mediaStopped
В поддерживаемых средах медиапоток может остановиться во время трансляции. Рассматривайте это как событие восстановления, но убедитесь, что одновременно выполняется только один рабочий процесс восстановления.
Логирование непредвиденных ошибок предпочтительнее их скрытого игнорирования. Тогда ваше приложение сможет отличать ожидаемые состояния жизненного цикла от реальных сбоев восстановления.
Точный рабочий процесс восстановления должен учитывать, можно ли еще использовать существующего издателя или необходимо создать нового.
Рекомендуемые правила восстановления трансляции
Используйте четкий процесс принятия решений при сбоях публикации:
Условие
Рекомендуемое действие
Пользователь отклоняет разрешение на доступ к устройству
Запросите действие пользователя; не повторяйте попытки автоматически бесконечно
Инициализация издателя завершается с ошибкой из-за проблемы с постоянной конфигурацией
Устраните проблему в конфигурации перед повторной попыткой
Происходит запротоколированный временный сбой сети
Повторите попытку, используя ограниченную политику повторов
Издатель уничтожен
Создайте и настройте нового издателя
Запрошено несколько попыток публикации
Сериализуйте операции
Происходит неизвестная ошибка
Залогируйте и исследуйте ошибку, вместо того чтобы повторять попытку автоматически
Этот подход позволяет избежать предположения, что все ошибки имеют одну и ту же причину.
Повторите session.subscribe() после тайм-аута
Подписка может завершиться сбоем из-за временных условий сети или согласования медиаданных.
Если ваше приложение решило, что ошибку подписки безопасно повторить, сначала убедитесь, что поток все еще доступен.
Убедитесь, что поток все еще существует
Поток может исчезнуть в промежутке между неудачной попыткой и повторной попыткой.
Если приложение получило событие streamDestroyed, не повторяйте подписку для старого потока. Вместо этого дождитесь соответствующего события жизненного цикла потока и подпишитесь на доступный поток.
Затем вы можете добавить логику повтора вокруг подписки:
Настраивайте shouldRetry так, чтобы он возвращал true только для ошибок, которые были проверены и признаны безопасными для повтора.
Учитывайте экспоненциальную задержку и случайное отклонение (jitter)
Когда множество клиентов сталкиваются с одной и той же временной ошибкой, повторные попытки ровно в одно и то же время могут создать очередной всплеск запросов.
Добавление небольшого случайного отклонения позволяет распределить попытки повтора:
Используйте политику повторов, которая соответствует требованиям вашего приложения и ожидаемому пользовательскому опыту.
Обратите внимание, что мы рекомендуем 3 секунды в качестве базовой длительности между повторными попытками; однако вы всегда можете изменить ее под свой сценарий использования. Пожалуйста, не устанавливайте слишком малый интервал, чтобы избежать перегрузок и критических ситуаций.
Восстановление после проблем с захватом аудио
Успешная публикация не гарантирует, что звук будет передаваться на протяжении всей сессии.
SDK может предоставлять события, которые указывают на проблему с захватом аудио и, в некоторых случаях, на то, что проблема была решена.
Обработка временных проблем
Если ваше приложение получает событие audioAcquisitionProblem, изучите детали события и используйте запротоколированную стратегию восстановления для указанной причины.
Для состояния, определяемого с помощью статистики, ваше приложение может предпочесть немного подождать перед принятием мер.
Не предполагайте, что альтернативный идентификатор устройства доступен всегда. Если ваше приложение планирует переключить аудиоустройство, объясните, как оно выбирает это устройство и что происходит, когда замена недоступна.
Обработка разрешенных проблем
Если проблема разрешается до истечения времени ожидания восстановления, отмените отложенное действие по восстановлению.
Явная обработка завершенных треков
Не рассматривайте каждый метод события, кроме getStats, как одинаковый сбой.
Вместо этого явно обрабатывайте запротоколированные значения событий:
Это предотвращает случайный запуск деструктивного поведения восстановления из-за неожиданных значений.
Рекомендуемые настройки повторов
Следующие настройки представляют собой отправную точку. Настройте их в соответствии с требованиями вашего приложения.
Параметр
Рекомендуемое начальное значение
Примечания
Максимальное количество попыток подключения
Ограничивает время, затрачиваемое на повторные попытки
Задержка повторного подключения
Линейное увеличение интервала (backoff)
Увеличивайте задержку между попытками
Максимальное количество попыток публикации
Повторяйте только проверенные временные ошибки
Задержка повтора публикации
2 секунды с последующим увеличением
Избегайте немедленных повторяющихся попыток
Задержка повтора подписки
Не менее 3 секунд
Сначала убедитесь, что поток все еще существует
Случайное отклонение (jitter) для повторов
Необязательно
Помогает распределить одновременные повторные попытки
Неизвестные ошибки
Не повторяйте попытку автоматически
Залогируйте и исследуйте причину сбоя
Внедрение восстановления в жизненный цикл приложения
Надежное восстановление — это не просто повторный вызов операции.
Полный рабочий процесс восстановления должен отвечать на следующие вопросы:
- Является ли сбой временным?
Является ли сбой временным?
- Безопасно ли повторять попытку?
Безопасно ли повторять попытку?
- Нужно ли очищать предыдущий объект?
Нужно ли очищать предыдущий объект?
- Изменилось ли состояние сессии или потока?
Изменилось ли состояние сессии или потока?
- Может ли уже выполняться другая попытка восстановления?
Может ли уже выполняться другая попытка восстановления?
- Требуется ли вводу пользователя со стороны приложения?
Требуется ли вводу пользователя со стороны приложения?
- Что должно произойти после того, как все попытки потерпят неудачу?
Что должно произойти после того, как все попытки потерпят неудачу?
Централизация поведения повторов упрощает последовательное применение этих решений.
Это также соответствует принципам качественного проектирования программного обеспечения благодаря разделению:
- выполняемой операции
выполняемой операции
- политики повторов
политики повторов
- классификации ошибок
классификации ошибок
- управления жизненным циклом издателя
управления жизненным циклом издателя
Это снижает дублирование и упрощает расширение стратегии восстановления по мере изменения вашего приложения.
Дальнейшие действия
Команда Vonage Video API продолжает повышать отказоустойчивость и улучшать поведение восстановления в SDK. Будущие релизы SDK внедрят еще больше встроенной отказоустойчивости, уменьшая объем логики восстановления, которую приложениям приходится обслуживать самостоятельно.
По мере развития функций отказоустойчивости на уровне SDK пересмотрите логику повторов на уровне вашего приложения, чтобы убедиться, что она дополняет SDK, а не дублирует его поведение без необходимости.
Вы также можете изучить приложение Vonage Video React в качестве примера структуры приложения, ориентированного на продакшн. Внимательно изучите реализацию и адаптируйте паттерны восстановления к текущей версии SDK и требованиям вашего приложения.
- Публикация диагностики
Публикация диагностики
Заключение
Надежные видеоприложения должны быть готовы к временным сбоям и обрабатывать их с помощью продуманных стратегий восстановления.
Наиболее важными паттернами являются:
- очистка состояния сессии перед повторной попыткой подключения
очистка состояния сессии перед повторной попыткой подключения
- разграничение ошибок, требующих вмешательства пользователя, и ошибок, которые можно повторить
разграничение ошибок, требующих вмешательства пользователя, и ошибок, которые можно повторить
- использование явных белых списков (allowlists) для ошибок, допускающих повтор
использование явных белых списков (allowlists) для ошибок, допускающих повтор
- предотвращение одновременных операций публикации и восстановления
предотвращение одновременных операций публикации и восстановления
- проверка существования потока перед повторной попыткой подписки
проверка существования потока перед повторной попыткой подписки
- управление очисткой и воссозданием издателя через согласованный жизненный цикл
управление очисткой и воссозданием издателя через согласованный жизненный цикл
- мониторинг проблем захвата аудио и использование подходящей стратегии восстановления
мониторинг проблем захвата аудио и использование подходящей стратегии восстановления
Прежде чем добавлять автоматические повторные попытки, проверьте поведение конкретной версии SDK, которую использует ваше приложение. Политика повторных попыток должна основываться на документированном поведении и быть протестирована на реалистичных сбоях сети и устройств.












