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


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

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

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

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


28
2017-08-12 12:08


Источник




Ответы:


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

В противном случае, если это в системе 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 также.


13
2017-08-14 14:53



Будет ли сеанс паузы на этом сайте работать? - nicoX
Он перестает давать процессорное время Apache. Если вы попытались получить доступ к сайту в браузере, в то время как Apache приостановлен, браузер будет ждать подключения до тех пор, пока Apache не будет возобновлен (или время ожидания браузера, если Apache приостановлено дольше, чем период ожидания). Если кто-то находится в процессе загрузки файла, Apache прекратит отправлять данные, пока он приостановлен, опять же, потому что он не получает никакого процессорного времени. Опять же, это вызовет проблемы только в том случае, если Apache остановится так долго, что время передачи будет нарушено. - GargantuChet
Другими словами, сайт будет не отвечать на запросы, если Apache приостановлен, но ожидающие операции завершатся, когда они будут возобновлены. Пользователи не получат «отказ в подключении», и загрузка не будет прерываться, но операции будут продолжаться только при возобновлении Apache. Это обеспечит завершение существующих транзакций, но новые запросы будут обрабатываться только после того, как ваш новый контент будет перенесен на место. - GargantuChet
Обратите внимание, что на любом сайте с высоким трафиком это может очень легко убить ваш сервис Apache. 200 rq / s очень легко удалит ваш пул соединений, как только вы «разблокируете» ваш процесс Apache после перемещения (если переход займет некоторое время) - CloudWeavers
На сайте с высоким трафиком будет много запросов на рейс, которые будут завершены, когда Apache будет возобновлен. Это пошатнуло бы обработку новых запросов. Это также хороший аргумент в пользу того, что ваши настройки Apache (максимальное количество потоков / серверов / клиентов) являются разумными и соответственно настраивают отставание TCP. Хотя я смущен тем, что вы подразумеваете под «убийством» службы. Apache очень настраиваемый. - GargantuChet


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

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

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

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

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

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


32
2017-08-12 13:26



Самое простое решение всегда лучшее ... :-) Конечно, не стоит забывать упомянуть, что могут понадобиться некоторые FollowSymlinks и такие флаги apache в конфигурациях. - peterh
Обратите особое внимание на то, что сказал @PeterHorvath. Apache может быть очень сварливым при работе с символическими DocumentRoots. Обязательно тщательно проверяйте! - mhutter
@mhutter Спасибо :-) Что действительно проблематично в том, что включение FollowSymlinks на apache может привести к проблемам безопасности ... - peterh
Обновление символической ссылки не является атомной операцией. Даже используя что-то вроде ln -snf чтобы скрыть первоначальную символическую ссылку, основная операция - unlink а также symlink, Есть вероятность, что пользователи получат 404 во время обновления. Это не лучше, чем просто переименовать исходный каталог в сторону и переименовать новый на место (предполагая, что вы не пересекаете файловые системы). См. Ответ выше с галочкой рядом с ним, в котором рассматривается эта проблема. - GargantuChet


Переименование каталогов, не закрывая 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 системный вызов, не пытаясь быть умным.

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


14
2017-08-12 12:38



В моей системе Debian, mv имеет -T , который не позволяет ему следовать символической ссылке. Это позволит вам атомно переименовать public_html.new над public_html, предполагая, что оба являются софт-ссылками. - GargantuChet


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

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

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


11
2017-08-12 17:29



Я просто работал над этим ответом, когда увидел, что вы уже разместили его. Balancer + 2 сервера делают процесс невидимым и легче восстанавливаются после плохого обновления ... - Bart Silverstrim


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

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

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


9
2017-08-12 12:57





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

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


4
2017-08-12 14:59





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

# 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 mount вашего 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

3
2017-08-12 12:20



Будет ли команда удалять public_html и развертывать public_html_new в нее? - nicoX
@nicoX Нет, он скопирует только перемены. - peterh
@nicoX Это продолжается и то и другое структуры каталогов, и если он находит разницу (новый файл, измененный файл, удаленный файл), он изменяет второй каталог, соответствующий первому, по мере необходимости. Результат, если вы удалили public_html, а затем переместили public_html_new на свое место, но без возможности временной проблемы 404. - peterh
Нет, это не очень хорошая идея. В зависимости от изменений у вас может быть короткий период времени, когда код в public_html находится в противоречивом состоянии, и вы не хотите воспользоваться этим шансом. - Sven♦
@SvW Вы правы, моя идея только в порядке, если есть только незначительные изменения. Я продлил свой ответ. - peterh


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

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

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


1
2017-08-17 12:52