Как лучше всего развертывать новый код на действующем сайте (электронной коммерции)?
На данный момент я остановил 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 (или наоборот) вашей модели данных, это может привести к поломке, если это не предусмотрено командой разработчиков.
По опыту, поддержание такой согласованности посредством обновлений не является обязательным для большинства приложений. Правильное завершение работы, несмотря на время простоя, - хороший способ избежать проблем с согласованностью.