Вчера вместе с командой мы обсуждали возможность использования развертываний с нулевым временем простоя для поддержки нашего одностраничного приложения.
Обсуждая это, мы выявили один крайний случай. После того, как пользователь загрузит страницу в своем браузере, ее нельзя удалить из памяти, пока он не перезагрузит страницу. Это означает, что если пользователь загружает страницу и начинает работать с веб-сайтом (например, начинает печатать длинную статью, как это делаю я сейчас), то он не может получить ее обновленную версию, пока не перезагрузит страницу.
Мы могли бы проигнорировать тот факт, что пользователь видит старую версию приложения в своем браузере, но есть 2 пункта, перечисленные ниже.
- В случае, если мы внесем критическое изменение в HTTP Api, который используется для обслуживания спа, пользователь не сможет сохранить свою статью (потеря данных!) Или может получить другую ошибку при выполнении другого действия, связанного с серверной частью.
- Когда пользователь переходит на новую страницу без перезагрузки SPA, он может получить шаблон следующей страницы или некоторого элемента управления, несовместимого с внешним старым контейнером. Это может привести к нарушению разметки или логики приложения.
- Мы не можем заставить пользователя повторно войти в систему, так как он может печатать свою статью, и это просто плохой UX.
Принимая во внимание все эти моменты, можно предложить следующее решение:
- Пользователь 1 загружает v1 SPA в свой браузер.
- Наряду с токеном аутентификации в браузер отправляется информация о версии (например, с помощью JWT).
- Мы хотим развернуть v2 версию нашего приложения. Мы раскручиваем версию v2, но не отключаем v1.
- Пользователь 2 загружает версию 2 SPA в свой браузер.
- Пользователь 1 переходит на следующую страницу в SPA. Балансировщик нагрузки проверяет информацию о версии в своем токене и направляет трафик пользователя 1 на сервер v1.
- Пользователь 2 таким же образом перенаправляется на v2.
- Пользователь 1 выходит из приложения и закрывает браузер.
- Пользователь 1 снова входит в систему - на этот раз он получает v2.
- После того, как приложение v1 долгое время не получает трафика, оно утилизируется.
Однако при таком подходе возможно иметь несколько версий, более двух (например, если пользователь остается в сети целый день или два). Это означает, что мы не сможем перенести базу данных на новую схему, пока последний пользователь не выйдет из системы (представьте, как это может работать для таких сайтов, как Facebook). Наличие нескольких версий не проблема, однако такие инструменты, как Docker и Rancher, позволяют нам это легко сделать.
Также на шаге 7. Пользователь должен перезагрузить страницу или закрыть браузер, иначе он все равно будет работать с v1, и мы не сможем заставить его перейти к следующей версии.
У меня вопрос: какой подход вы используете, чтобы добиться нулевого времени простоя / сине-зеленого развертывания одностраничных приложений?
Как вы управляете временем жизни «синей» версии вашего приложения при переключении трафика на «зеленую» версию, особенно в отношении существующих «синих» клиентских приложений.
Вы решили эти проблемы, знаете ли вы какое-нибудь другое решение?