Развертывание (единственного node) веб-приложения Django с практически нулевым временем простоя на EC2
Вопрос: Каковы хорошие стратегии достижения 0 (или как можно ближе к 0) времени простоя при использовании Django?
Большинство ответов, которые я читал, говорят "используйте юг" или "используйте ткань", но это очень расплывчатый ответ ИМХО. Я фактически использую оба, и я все еще задаюсь вопросом, как достичь нулевого времени простоя как можно больше.
Некоторые сведения:
У меня есть приложение Django с приличным размером, которое я размещаю на EC2. Я использую Юг для переноса схем и данных, а также fabric с boto для автоматизации повторяющихся задач развертывания/резервного копирования, которые запускаются с помощью набора Jenkins (сервер непрерывной интеграции). Используемая база данных является стандартным экземпляром PostgreSQL 9.0.
У меня есть...
-
промежуточного сервера, который постоянно редактируется нашей командой со всем новым контентом и загружается с последним и самым лучшим кодом и...
-
живой сервер, который продолжает меняться с учетными записями пользователей и пользовательскими данными - все записано в PostgreSQL.
Текущая стратегия развертывания:
При развертывании нового кода и содержимого создаются два моментальных снимка EC2 на обоих серверах (live и staging). Живой эфир переключается на страницу "Обновление нового контента"...
Время простоя начинается.
Сервер live-clone переносится в ту же версию схемы, что и сервер промежуточного уровня (с использованием юга). Создается дамп только таблиц и последовательностей, которые я хочу сохранить из живых (в частности, учетные записи пользователей вместе с их данными). Как только это будет сделано, дамп будет загружен на сервер клонирования. Таблицы, которые были сохранены в реальном времени, усекаются и данные вставляются. По мере того, как данные на моем живом сервере растут, на этот раз явно увеличивается.
Как только нагрузка будет завершена, эластичные ips живого сервера будут заменены на стадион-клон (и, таким образом, он стал новым живым). Экземпляр live и экземпляр live-clone завершаются.
Время простоя.
Да, это работает, но по мере роста данных мое "виртуальное" нулевое время простоя становится все дальше и дальше. Конечно, что-то, что перешло мне в голову, - это как-то использовать репликацию и начать изучать репликацию PostgreSQL и "в конечном итоге последовательные" подходы. Я знаю, что есть какая-то магия, которую я мог бы сделать, возможно, с балансировщиками нагрузки, но проблема создания учетных записей в то же время делает ее сложной.
На что бы вы порекомендовали меня?
Обновление
У меня есть типичное приложение Django node.. Я надеялся на решение, которое будет углубляться с конкретными проблемами django. Например, идея использования поддержки Django для нескольких баз данных с настраиваемыми маршрутизаторами наряду с репликацией перешла мне в голову. Есть вопросы, связанные с тем, на что я надеюсь, что ответ затронет.
Ответы
Ответ 1
Что может заинтересовать, это техника под названием Canary Releasing. В прошлом году я увидел отличную презентацию Jez Humble на конференции по программному обеспечению в Амстердаме; речь шла о выпуске с низким уровнем риска, слайды здесь.
Идея состоит в том, чтобы не переключать сразу все системы, а отправлять небольшой набор пользователей в новую версию. Только когда все показатели производительности новых систем, как и ожидалось, переключились на другие. Я знаю, что этот метод также используется большими сайтами, такими как facebook.
Ответ 2
Живой сервер не должен мигрировать. Этот сервер должен быть доступен с двух промежуточных серверов, server0 и server1. Первоначально сервер0 является живым, и изменения вносятся в server1. Когда вы хотите сменить программное обеспечение, переключитесь на живые серверы. Что касается нового контента, это не должно быть на промежуточном сервере. Это должно быть на реальном сервере. Добавьте столбец в свои таблицы с номером версии для таблиц содержимого и измените базу кода, чтобы использовать правильный номер версии контента. Разрабатывайте программное обеспечение для копирования старых версий в новые строки с обновленными номерами версий по мере необходимости. Поместите текущий номер версии в свои settings.py на server0 и server1, чтобы у вас было центральное место для программного обеспечения, которое можно было бы использовать при выборе данных, или создать приложение для доступа к базе данных, которое можно обновить, чтобы получить правильные версии контента. Конечно, для файлов шаблонов они могут быть на каждом сервере и будут подходящими.
Этот подход устранит простоя. Вам придется переписать часть своего программного обеспечения, но если вы найдете общий метод доступа, такой как метод доступа к базе данных, который вы можете изменить, вы можете обнаружить, что это не так много. Первоначальные инвестиции в создание системы, которая специально поддерживает мгновенное переключение систем, будут в меньшей степени работать в долгосрочной перспективе и будут масштабироваться до любого размера контента.
Ответ 3
Если я правильно понимаю, проблема заключается в том, что ваше приложение не работает, а данные восстанавливаются в новую базу данных вместе со схемой.
Почему вы создаете новый сервер в первую очередь? Почему бы не перенести базу данных на место (конечно, после того, как вы тщательно протестировали миграцию), и, как только это будет сделано, обновите код и "перезапустите" свои процессы (например, gunicorn может принять сигнал HUP, который сделает он перезагружает приложение, не отбрасывая соединения в очереди).
Во многих миграциях не будет необходимости блокировать таблицы базы данных, поэтому это безопасно. Для остальных есть другие способы сделать это.
Например, если вы хотите добавить новый столбец, который должен быть заполнен с правильными данными, вы можете сделать это в следующих шагах (кратко описано):
- Добавьте столбец как принимающий значения NULL и сделайте запись django в этот столбец, чтобы новые записи имели правильные данные.
- Заполните заполняющие записи.
- Создайте django для чтения из нового столбца.
Ответ 4
Чтобы достичь 0 времени простоя, вы должны иметь как минимум 2 сервера + балансировщик. И обновляйте их последовательно. Если вы хотите обновить как базу данных, так и приложение - и иметь 0 простоя - у вас должно быть 2 сервера db. Никаких чудес, ни серебряной пули, ни джанго вы не уйдете из проблем с развертыванием.