Назад | Перейти на главную страницу

Развертывание нового кода в реальном времени

Как лучше всего развертывать новый код на действующем сайте (электронной коммерции)?

На данный момент я остановил apache на +/- 10 секунд при переименовании каталога public_html_new к public_html и стар до public_html_old. Это создает короткое время простоя, прежде чем я снова запущу Apache.

Тот же вопрос возникает при использовании Git для извлечения нового репозитория в live-каталог. Могу ли я вытащить репо, пока сайт активен? А как насчет того, чтобы мне тоже нужно было скопировать БД?

Во время сжатия живого сайта tar (резервное копирование) я заметил, что в каталоге мультимедиа произошли изменения. Это показало мне, что файлы продолжают периодически меняться. И если эти изменения могут помешать, если Apache не будет остановлен во время развертывания.

Самый быстрый и простой - использовать каталог версий, например

/var/www/version/01
/var/www/version/02

и используйте текущую символическую ссылку в качестве html_root:

/var/www/html -> /var/www/version/02

Эта техника прекрасно интегрируется в система контроля версий (svn, git, mercurial, ...), поскольку вы можете проверить ветки и теги, изменить символическую ссылку и перезагрузить Apache. В время простоя минимально используя эту технику, и это позволяет очень легкий откат.

Он также хорошо интегрируется с более сложной системой развертывания, такой как пакеты RPM или инфраструктура управления изменениями конфигурации (шеф-повар, марионетка и т. Д.).

Переименование каталогов без выключения Apache также должно работать. Это значительно сократит окно. mv public_html public_html_old && mv public_html_new public_html должен закончиться за доли секунды.

Пара недостатков заключается в том, что такой подход дает 404 на любой запрос, который все еще может произойти в течение окна. И если вы запустите указанную выше команду, не имея public_html_new каталог, он потерпит неудачу и оставит вас с сайтом, 404 по каждому запросу.

Атомарная работа с каталогами не поддерживается. Но вы можете сделать это с помощью символических ссылок. Вместо того, чтобы иметь каталог с именем public_html, имейте каталог с именем public_html.version-number и символическая ссылка под названием public_html указывая на этот каталог. Теперь вы можете создать каталог с именем public_html.new-version-number и новая символическая ссылка под названием public_html.new.

Затем вы можете переименовать public_html.new к public_html переключаться атомарно. Заметь mv "слишком умен", чтобы выполнить такое переименование, но это можно сделать, используя os.rename из python или чего-то еще, что вызовет rename системный вызов, не пытаясь быть умным.

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

Использование балансировщика нагрузки - хорошая идея. Если сайт достаточно важен, чтобы беспокоиться о нескольких секундах простоя, достаточно важно беспокоиться об отказоустойчивости.

Кроме того, если это в системе UNIX, вы можете приостановить Apache во время переименования (или обновления символической ссылки и т. Д.):

killall -STOP httpd  # Pause all httpd processes
mv public_html public_html_orig
mv public_html_new public_html
killall -CONT httpd  # Resume all httpd processes

Это не позволит Apache принимать новые запросы во время переименования. Если вы предпочитаете символические ссылки или какой-либо другой подход, можно использовать ту же идею:

killall -STOP httpd  # Pause all httpd processes
rm /var/www/html
ln -s /var/www/version/03 /var/www/html
killall -CONT httpd  # Resume all httpd processes

Обратите внимание, что любые ожидающие соединения или пакеты будут стоять в очереди в ОС. Для очень загруженного сайта рассмотрите возможность настройки ListenBacklog, если это подходит для вашего типа работника httpd, и проверьте настройки вашей ОС, связанные с невыполненным прослушиванием TCP.

Вы также можете изменить DocumentRoot в httpd.conf и выполнить плавный перезапуск (apachectl graceful). Недостатком здесь является повышенный риск ошибок, так как вам придется обновлять любые Directory конфигурация тоже.

Symlinks и mv - ваши друзья, однако, если вам действительно нужно, чтобы конечные пользователи не получали страницу с ошибкой при развертывании новой версии, у вас должен быть обратный прокси или балансировщик нагрузки перед как минимум двумя внутренними серверами (apache в твоем случае).

Во время развертывания вам просто нужно останавливать по одному бэкэнду за раз, развертывать новый код, перезапускать его, а затем выполнять итерацию с оставшимися бэкэндами.

Конечные пользователи всегда будут направляться через прокси на хорошие серверные части.

Если вы регулярно вносите изменения в производственную систему, я бы позаботился о структурированном жизненном цикле. Хорошая практика - Capistrano http://capistranorb.com/. Это решение с открытым исходным кодом для развертывания программного обеспечения на одном или нескольких серверах на нескольких платформах и конфигурациях.

Для Magento есть даже плагин: https://github.com/augustash/capistrano-ash/wiki/Magento-Example

Для одного сервера и почти бесшовных переходов я рекомендую использовать символические ссылки.

Я делаю это так: я фиксирую свои изменения из локальной среды разработки в онлайн-репозиторий Git, например Github. Моя производственная среда работает из удаленного репозитория, поэтому все, что мне нужно сделать, это ssh на сервер и запустить git pull обрушить последние изменения. Нет необходимости останавливать ваш веб-сервер.

Если в вашем проекте есть файлы, настройки и / или содержимое которых отличаются от вашей локальной версии (например, файлы конфигурации и загрузки мультимедиа), вы можете использовать переменные среды и / или добавить эти файлы / каталоги в .gitignore файл, чтобы предотвратить синхронизацию с репозиторием.

Моя первая идея:

# deploy into public_html_new, and then:
rsync -vaH --delete public_html_new/ public_html/

Хорошим решением было использование rsync. Он менял только реально измененные файлы. Остерегайтесь, здесь важны косые черты в конце дорожек.

Обычно apache не требует перезапуска, это не мир Java. Он проверяет наличие изменений в каждом файле php по запросу и автоматически перечитывает (и повторно токенизирует) при изменении.

Git pull был столь же эффективен, хотя его было немного сложнее написать. Конечно, это позволило использовать широкий спектр различных возможностей обнаружения слияния / изменения.

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

Если есть большие изменения, мое предложение было вашим первоначальным решением (два переименования).


Вот немного хардкорное, но 100% атомарное решение:

(1) выполните альтернативное монтирование файловой системы, в которой находится ваш magento:

mount /dev/sdXY /mnt/tmp

(2) сделать --bind смонтируйте свой public_html_new в public_html:

mount --bind /path/to/public_html_new /path/to/public_html

С этого момента apache увидит ваше новое развертывание. Замена 404 невозможна.

(3) выполните синхронизацию с помощью rsync, но в альтернативной точке монтирования):

rsync -vaH --delete /mnt/tmp/path/to/public_html_new/ /mnt/tmp/path/to/public_html/

(4) снимите крепление крепления

umount /path/to/public_html

Перемещение / замена http_public папку можно получить с помощью простых mv или ln -s команды или аналогичные, пока ваш http-сервер продолжает работать. Вы можете написать сценарий, чтобы значительно сократить время простоя, но внимательно проверьте коды возврата ваших команд в сценарии, если вы автоматизируете процесс.

Тем не менее, если вы хотите избежать простоев, вы применение также должны поддерживать это. Большинство приложений использует базу данных для обеспечения устойчивости. Если версия N вашего приложения не работает с версией N + 1 (или наоборот) вашей модели данных, это может привести к поломке, если это не предусмотрено командой разработчиков.

По опыту, поддержание такой согласованности посредством обновлений не является обязательным для большинства приложений. Правильное завершение работы, несмотря на время простоя, - хороший способ избежать проблем с согласованностью.