Розгортання нового коду в прямому ефірі


29

Яка найкраща практика розгортати новий код на веб-сайті (електронна комерція)?

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

Це ж питання стосується використання Git для того, щоб перетягнути нове репо в прямий каталог. Чи можу я витягнути репо, поки сайт активний? А як щодо того, якщо мені також потрібно скопіювати БД?

Під час стиснення tar (резервного копіювання) живого сайту я помітив, що в каталозі медіа відбулися зміни. Це вказувало мені, що файли періодично змінюються. І якщо ці зміни можуть заважати, якщо Apache не буде зупинено під час розгортання.

Відповіді:


13

Використання балансира навантаження - хороша ідея. Якщо сайт досить важливий, щоб турбуватися про кілька секунд простою, досить важливо потурбуватися про відмовостійкість.

Це вбік, якщо це в системі 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конфігурацію.


Чи буде сеанс паузи на цьому веб-сайті все ще запущений?
nicoX

4
Він припиняє давати час процесора Apache. Якщо ви спробували отримати доступ до сайту в браузері, поки Apache призупинено, браузер буде чекати підключення, поки Apache не відновиться (або час вимкнення браузера, якщо Apache призупинено довше, ніж період очікування). Якщо хтось завантажує файл, Apache перестане надсилати дані під час призупинення, оскільки це не отримує жодного часу процесора. Знову це спричинить проблеми лише в тому випадку, якщо Apache зупиняється настільки довго, що час перенесення вичерпається.
GargantuChet

5
По-іншому, сайт буде не реагувати, поки Apache призупинено, але очікувані операції завершаться, коли він буде відновлений. Користувачі не отримають "відмовлено у з'єднанні", а завантаження не порушиться, але операції триватимуть лише тоді, коли Apache буде відновлено. Це забезпечить завершення існуючих транзакцій, але нові запити будуть оброблені лише після переміщення вашого нового вмісту.
GargantuChet

1
Зауважте, що на будь-якому веб-сайті з високим трафіком це може дуже легко вбити вашу службу Apache. 200 rq / s дуже легко потрапить у ваш пул зв’язків, як тільки ви "розблокуєте" процес Apache після переїзду (якщо перехід триває певний час)
CloudWeavers

1
На веб-сайті з високим трафіком буде багато запитів на польоту, коли закінчиться, коли Apache відновиться. Це призведе до поетапної обробки нових запитів. Це також хороший аргумент для того, щоб переконатися, що ваші налаштування Apache (максимальна кількість потоків / серверів / клієнтів) є розумними, і відповідно налаштувати відставання TCP. Хоча я плутаю те, що ви маєте на увазі під "вбивством" служби. Apache дуже настроюється.
GargantuChet

32

Найшвидше і найпростіше - використовувати каталог версій, такий як

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

і використовувати поточне символічне посилання як вашу html_root:

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

Цей прийом ідеально інтегрується в систему контролю версій (svn, git, mercurial, ...), оскільки ви можете перевірити гілки та теги, змінити символічне посилання та перезавантажити Apache. За допомогою цієї методики простої мінімальні , і це дозволяє дуже просто відкати .

Він також добре інтегрується з більш складною системою розгортання, наприклад, RPM-пакетами або інфраструктурою управління зміною конфігурації (шеф-кухар, ляльковий тощо).


4
Найпростіші рішення завжди найкращі ... :-) Звичайно, не забудьте згадати, що можуть знадобитися деякі FollowSymlinks та подібні прапори apache у налаштуваннях.
Peterh каже відновити Моніку

Будьте особливо уважні у тому, що сказав @PeterHorvath. Apache може бути дуже бурхливим під час роботи з символічно пов'язаними DocumentRoots. Обов’язково ретельно перевіряйте!
mhutter

@mhutter Дякую :-) Що насправді проблематично, це те, що включення FollowSymlinks на apache може спричинити проблеми із безпекою ...
peterh каже відновити Моніку

Оновлення симпосилання не є атомною операцією. Навіть використовуючи щось на кшталт ln -snfклобування оригінальної симпосилання, основна операція - це unlinkі symlink. Користувачі можуть отримати 404 під час оновлення. Це не краще, ніж просто перейменувати оригінальний каталог і перейменувати новий на місце (якщо ви не перетинаєте файлові системи). Дивіться відповідь вище з галочкою поруч, яка вирішує цю проблему.
GargantuChet

14

Перейменування каталогів без вимкнення 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.renamepython або будь-якого іншого, що викликає renameсистемний виклик, не намагаючись бути розумним.

Що робити з базою даних, залежить від того, яку базу даних ви використовуєте, і для чого ви її використовуєте. Вам потрібно надати набагато більше деталей про базу даних, перш ніж ми зможемо дати вам хорошу відповідь на цю частину вашого питання.


1
У моїй системі Debian mvє -Tопція, яка не дозволяє їй слідувати за посиланням. Це дозволить вам атомарному перейменувати public_html.newбільш public_html, якщо припустити , як м'які посилання.
GargantuChet

11

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

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

Кінцеві користувачі завжди будуть спрямовані на хороші пропозиції через проксі.


4
Я тільки працював над цією відповіддю, коли побачив, що ви її вже розмістили. Сервери Balancer + 2 роблять процес невидимим і простіше відновитись після поганого оновлення ...
Bart Silverstrim

9

Якщо ви регулярно застосовуєте зміни у виробничій системі, я б подбав про структурований життєвий цикл. Гарна практика - це Capistrano http://capistranorb.com/ . Це рішення з відкритим кодом для розгортання програмного забезпечення на одному або декількох серверах на декількох платформах і конфігураціях.

Для Magento є навіть плагін: https://github.com/augustash/capistrano-ash/wiki/Magento-Example

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


4

Як я це роблю, я здійснюю зміни від мого локального середовища розробників до інтернет-сховища Git, такого як Github. Моє виробниче середовище працює з віддаленого сховища, тому все, що мені потрібно зробити, - це ssh на сервер і запустіть, git pullщоб збити останні зміни. Не потрібно зупиняти свій веб-сервер.

Якщо у вашому проекті є файли, налаштування та / або вміст яких відрізняються від локальної версії (наприклад, файли конфігурації та завантаження медіа), ви можете використовувати змінні середовища та / або додати ці файли / каталоги до .gitignoreфайлу, щоб запобігти синхронізації з сховищем.


3

Моя перша ідея:

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

Хорошим рішенням було використання rsync. Він змінив лише дійсно змінені файли. Будьте обережні, підстрибування в кінці від патьоків тут важливі.

Зазвичай apache не потребує перезавантаження, це не світ java. Він перевіряє на зміну кожного файлу php за запитом і автоматично читає (і повторно маркує) зміни.

Git pull були аналогічно ефективними, хоча сценарій був трохи складніше. Звичайно, це дозволило отримати широкий спектр різних можливостей виявлення злиття / зміни.

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

Якщо є великі зміни, то моя пропозиція була вашим початковим рішенням (дві перейменування).


Ось трохи хардкор, але 100% атомне рішення:

(1) зробіть альтернативне змонтування частини вашої файлової системи, де знаходиться ваш магент:

mount /dev/sdXY /mnt/tmp

(2) зробіть --bindкріплення свого public_html_new для public_html:

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

З цього моменту апаш побачить ваше нове розгортання. Будь-яка зміна 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

Чи видалить команду public_html і розгорне в ній public_html_new?
nicoX

@nicoX Ні, він буде копіювати лише зміни.
Peterh каже відновити Моніку

@nicoX Це відбувається через обидві структури каталогів, і якщо він знаходить різницю (новий файл, модифікований файл, видалений файл), він змінює другий каталог, щоб відповідати першому, як це потрібно. Результат, якщо ви видалили public_html, а потім перемістили public_html_new на його місце, але без жодної можливості тимчасової проблеми 404.
Peterh каже відновити Моніку

1
Ні, це не дуже гарна ідея. Залежно від змін, може виникнути короткий проміжок часу, коли код public_htmlзнаходиться в непослідовному стані, і ви не хочете скористатися цим шансом.
Sven

@SvW Ви маєте рацію, моя думка нормальна, якщо є лише незначні зміни. Відповідно я продовжив свою відповідь.
Peterh каже відновити Моніку

1

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

Однак, якщо ви не хочете простою, програма також повинна підтримувати це. Більшість додатків використовує базу даних для постійності. Якщо версія N вашої програми переплутається з версією N + 1 (або з реверсом) вашої моделі даних, це може порушити ситуацію, якщо це не передбачено командою розробників.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.