Как развернуть приложение ASP.NET с нулевым временем простоя

StackOverflow https://stackoverflow.com/questions/148084

Вопрос

Чтобы развернуть новую версию нашего сайта, мы делаем следующее:

  1. Заархивируйте новый код и загрузите его на сервер.
  2. На действующем сервере удалите весь действующий код из каталога веб-сайта IIS.
  3. Извлеките новый zip-файл с кодом в теперь пустой каталог IIS.

Этот процесс запрограммирован и происходит довольно быстро, но при удалении старых файлов и развертывании новых файлов все равно может быть 10-20-секундный простой.

Есть какие-нибудь предложения по методу простоя в 0 секунд?

Это было полезно?

Решение

Вам нужны 2 сервера и балансировщик нагрузки.Вот по шагам:

  1. Включить весь трафик на Сервере 2
  2. Развертывание на сервере 1
  3. Тестовый сервер 1
  4. Включить весь трафик на Сервере 1
  5. Развертывание на сервере 2
  6. Тестовый сервер 2
  7. Включите трафик на обоих серверах

Дело в том, что даже в этом случае у вас все равно будут перезапуски приложений и потеря сеансов, если вы используете «закрепленные сеансы».Если у вас есть сеансы базы данных или сервер состояний, то все должно быть в порядке.

Другие советы

А Инструмент веб-развертывания Microsoft в некоторой степени поддерживает это:

Включает поддержку транзакционной файловой системы Windows (TXF).Когда поддержка TXF включена, файловые операции являются атомными;То есть они либо преуспевают, либо потерпят неудачу полностью.Это обеспечивает целостность данных и предотвращает существующие данные или файлы в «на полпути» или поврежденного состояния.В MS Deploy TXF отключен по умолчанию.

Кажется, транзакция рассчитана на всю синхронизацию.Кроме того, TxF — это функция Windows Server 2008, поэтому эта функция транзакций не будет работать с более ранними версиями.

Я считаю, что можно изменить ваш сценарий для нулевого простоя, используя папки в качестве версий и метабазу IIS:

  • для существующего пути/URL-адреса:
  • Скопируйте новый (или измененный) веб-сайт на сервер под
    • \веб\приложение\v2.1\
  • Измените метабазу IIS, чтобы изменить путь к веб-сайту.
    • от \веб\приложение\2.0\
    • к \веб\приложение\v2.1\

Этот метод предлагает следующие преимущества:

  • Если в новой версии возникнут проблемы, вы можете легко вернуться к версии 2.0.
  • Для развертывания на нескольких физических или виртуальных серверах вы можете использовать сценарий для развертывания файлов.Как только на всех серверах будет установлена ​​новая версия, вы сможете одновременно изменить метабазы ​​всех серверов с помощью инструмента веб-развертывания Microsoft.

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

Полное руководство можно найти здесь.

Недавно я прошел через это и нашел решение: настроить два сайта в IIS и переключаться между ними.

В моей конфигурации у меня был веб-каталог для каждого сайта A и B, например:C: intranet live a interface c: intranet live b interface

В IIS у меня есть два идентичных сайта (одинаковые порты, аутентификация и т. д.), каждый со своим собственным пулом приложений.Один из сайтов работает (А), а другой остановлен (Б).живой также имеет заголовок живого хоста.

Когда дело доходит до развертывания в реальном времени, я просто публикую в месте ОСТАНОВЛЕННОГО сайта.Поскольку я могу получить доступ к сайту B, используя его порт, я могу предварительно разогреть сайт, чтобы первый пользователь не вызывал запуск приложения.Затем с помощью пакетного файла я копирую заголовок живого хоста в B, останавливаю A и запускаю B.

Используя класс ServerManager Microsoft.Web.Administration, вы можете разработать собственный агент развертывания.

Хитрость заключается в изменении PhysicalPath VirtualDirectory, что приводит к атомарному онлайн-переключению между старыми и новыми веб-приложениями.

Имейте в виду, что это может привести к параллельному выполнению старых и новых доменов приложений!

Проблема в том, как синхронизировать изменения в базах данных и т. д.

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

Чтобы принудительно запустить домен приложения, вы должны выполнить HTTP-запрос (IIS 7.5 поддерживает функцию автозапуска).

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

(Я использую маркерный файл в веб -приложении, чтобы включить поведение ожидания Mutex) после запуска нового веб -приложения я удаляю файл маркера.

Хорошо, поскольку все отвергают ответ, который я написал еще в 2008 году *...

Я расскажу вам, как мы это делаем сейчас, в 2014 году.Мы больше не используем веб-сайты, поскольку теперь используем ASP.NET MVC.

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

Кроме того, мы не полагаемся на последний мастер от Microsoft — слишком медленный, слишком много скрытой магии и слишком склонный к смене имени.

Вот как мы это делаем:

  1. У нас есть этап после сборки, который копирует сгенерированные библиотеки DLL в папку «bin-pub».

  2. Мы используем Beyond Compare (отлично**) для проверки и синхронизации измененных файлов (через FTP, поскольку он широко поддерживается) с рабочим сервером.

  3. У нас есть защищенный URL-адрес на веб-сайте, содержащий кнопку, которая копирует все из «bin-pub» в «bin» (сначала создаётся резервная копия, чтобы обеспечить быстрый откат).На этом этапе приложение перезапускается.Затем наш ORM проверяет, есть ли какие-либо таблицы или столбцы, которые необходимо добавить, и создает их.

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

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

Таким образом, вам не нужно копировать весь веб-сайт в другой каталог, а только папку bin.Вы также имеете полный контроль над процессом и точно знаете, что меняется.

**Мы всегда быстро проверяем развертываемые изменения — в последнюю минуту двойная проверка, чтобы мы знали, что тестировать, и, если что-то сломается, мы были готовы.Мы используем Beyond Compare, потому что он позволяет легко различать файлы по FTP.Без БК я бы никогда этого не сделал, вы понятия не имеете, что перезаписываете.

* Прокрутите вниз, чтобы увидеть это :( Кстати, я бы больше не рекомендовал веб-сайты, потому что они медленнее создаются и могут сильно аварийно завершить работу с наполовину скомпилированными временными файлами.Мы использовали их раньше, потому что они позволяли более гибко развертывать файлы пофайлами.Очень быстро устраняется незначительная проблема, и вы можете точно видеть, что вы развертываете (конечно, если вы используете Beyond Compare — в противном случае забудьте об этом).

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

Я бы немного уточнил ответ Джорджа для одного сервера следующим образом:

  1. Используйте проект веб-развертывания для предварительной компиляции сайта в одну DLL.
  2. Заархивируйте новый сайт и загрузите его на сервер.
  3. Разархивируйте его в новую папку, расположенную в папке с подходящими разрешениями для сайта, чтобы разархивированные файлы правильно наследовали разрешения (возможно, e:\web, с подпапками v20090901, v20090916 и т. д.).
  4. Используйте диспетчер IIS, чтобы изменить имя папки, содержащей сайт.
  5. Сохраните старую папку на некоторое время, чтобы в случае возникновения проблем можно было вернуться к ней.

Шаг 4 приведет к перезапуску рабочего процесса IIS.

Это нулевое время простоя, если вы не используете сеансы InProc;вместо этого используйте режим SQL, если можете (еще лучше, полностью избегайте состояния сеанса).

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

Чтобы расширить ответ sklivvz, который основывался на наличии какого-то балансировщика нагрузки (или просто резервной копии на том же сервере)

  1. Направьте весь трафик на сайт/сервер 2.
  2. При необходимости подождите немного, чтобы как можно меньше пользователей имели ожидающие рабочие процессы в развернутой версии.
  3. Разверните на сайте/сервере 1 и прогрейте его, насколько это возможно.
  4. Выполнять миграцию базы данных транзакционно (стремитесь сделать это возможным)
  5. Немедленно направьте весь трафик на сайт/сервер 1.
  6. Развертывание на сайте/сервере 2
  7. Прямой трафик на оба сайта/сервера

Можно провести небольшое дымовое тестирование, создав снимок/копию базы данных, но это не всегда осуществимо.

Если возможно и необходимо, используйте «разницы в маршрутизации», например разные URL-адреса арендаторов (customerX.myapp.net) или разных пользователей, чтобы сначала выполнить развертывание в ничего не подозревающей группе «подопытных кроликов».Если ничего не получится, выпустите всем.

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

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

Вот как я это делаю:

Абсолютные минимальные системные требования:
1 сервер с

  • 1 балансировщик нагрузки/обратный прокси (например.nginx), работающий на порту 80
  • 2 ASP.NET-Core/mono back-proxy/fastcgi chroot-jails или docker-контейнеры, прослушивающие 2 разных TCP-порта
    (или даже просто два приложения обратного прокси на двух разных TCP-портах без какой-либо песочницы)

Рабочий процесс:

начать транзакцию myupdate

try
    Web-Service: Tell all applications on all web-servers to go into primary read-only mode 
    Application switch to primary read-only mode, and responds 
    Web sockets begin notifying all clients 
    Wait for all applications to respond

    wait (custom short interval)

    Web-Service: Tell all applications on all web-servers to go into secondary read-only mode 
    Application switch to secondary read-only mode (data-entry fuse)
    Updatedb - secondary read-only mode (switches database to read-only)

    Web-Service: Create backup of database 
    Web-Service: Restore backup to new database
    Web-Service: Update new database with new schema 

    Deploy new application to apt-repository 
    (for windows, you will have to write your own custom deployment web-service)
    ssh into every machine in array_of_new_webapps
    run apt-get update
    then either 
    apt-get dist-upgrade
    OR
    apt-get install <packagename>
    OR 
    apt-get install --only-upgrade <packagename>
    depending on what you need
    -- This deploys the new application to all new chroots (or servers/VMs)

    Test: Test new application under test.domain.xxx
    -- everything that fails should throw an exception here
    commit myupdate;

    Web-Service: Tell all applications to send web-socket request to reload the pages to all clients at time x (+/- random number)
    @client: notify of reload and that this causes loss of unsafed data, with option to abort 

    @ time x:  Switch load balancer from array_of_old_webapps to array_of_new_webapps 
    Decomission/Recycle array_of_old_webapps, etc.

catch
        rollback myupdate 
        switch to read-write mode
        Web-Service: Tell all applications to send web-socket request to unblock read-only mode
end try 

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

Не уверен, что это помогает в «веб-приложении» (я думаю, вы говорите, что вы это используете), поэтому мы всегда используем «веб-сайты».Кроме того, при развертывании «веб-сайтов» ваш сайт не перезапускается и все пользовательские сеансы не прерываются.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top