Возможно ли плавное развертывание с компонентными приложениями ASP.NET MVC? - PullRequest
12 голосов
/ 23 декабря 2010

Это, вероятно, не специфично для MVC, оно может также применяться к веб-формам ASP.NET, но мы до сих пор испытывали его на MVC2.

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

Ошибка сервера в «/» приложении.

Не удалось загрузить файл или сборку «Some.Assembly» или один из его зависимостей. Процесс не может получить доступ к файлу, потому что он используется другим процессом. (Исключение от HRESULT: 0x80070020)

Описание: необработанное исключение произошло во время исполнения текущий веб-запрос. Пожалуйста, просмотрите трассировка стека для получения дополнительной информации о ошибка и откуда она возникла код.

Сведения об исключении: System.IO.FileLoadException: не удалось загрузить файл или сборку Some.Assembly или одна из его зависимостей. процесс не может получить доступ к файлу, потому что он используется другим процессом. (Исключение из HRESULT: 0x80070020)

Информация о версии: Microsoft .NET Версия Framework: 4.0.30319; ASP.NET Версия: 4.0.30319.1

Вот следы стека, показанные на странице ошибки:

[FileLoadException: Could not load file or assembly 'Some.Assembly' or one of its dependencies. The process cannot access the file because it is being used by another process. (Exception from HRESULT: 0x80070020)]
   System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) +0
   System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) +39
   System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection, Boolean suppressSecurityChecks) +132
   System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) +144
   System.Reflection.Assembly.Load(String assemblyString) +28
   System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +46

[ConfigurationErrorsException: Could not load file or assembly 'Some.Assembly' or one of its dependencies. The process cannot access the file because it is being used by another process. (Exception from HRESULT: 0x80070020)]
   System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +618
   System.Web.Configuration.CompilationSection.LoadAllAssembliesFromAppDomainBinDirectory() +209
   System.Web.Configuration.CompilationSection.LoadAssembly(AssemblyInfo ai) +130
   System.Web.Compilation.BuildManager.GetReferencedAssemblies(CompilationSection compConfig) +178
   System.Web.Compilation.BuildManager.GetPreStartInitMethodsFromReferencedAssemblies() +94
   System.Web.Compilation.BuildManager.CallPreStartInitMethods() +332
   System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel, Exception appDomainCreationException) +591

[HttpException (0x80004005): Could not load file or assembly 'Some.Assembly' or one of its dependencies. The process cannot access the file because it is being used by another process. (Exception from HRESULT: 0x80070020)]
   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +8950644
   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +97
   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +256

Сборка, которая вызывает этот сбой (Some.Assembly), является не фактической веб-сборкой, а одним из других компонентов в разделе «Ссылки», подписанным знаком .snk.

Через 5-6 секунд сайт поднимается и ошибка исчезает.

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

P.S. Взаимное вращение IIS включено, оно по умолчанию в любом случае.

Вот компоненты:

  • A.dll
  • Some.Assembly.dll (<--- это сбой, зависит от A.dll) </li>
  • B.dll (зависит от A.dll и Some.Assembly.dll)
  • Web.dll (это веб-приложение, зависит от всего вышеперечисленного)

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

MSDeploy развертывает только двоичные файлы, а не источник.

Ответы [ 2 ]

20 голосов
/ 24 декабря 2010

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

Папки теневого копирования используются для этой цели:

Для чего нужна папка «Temporary ASP.NET Files»? (Мой ответ)

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

При развертывании приложения ASP.NET сайт будет плохо себя вести. Пока вы копируете свои сборки, эти файлы будут заблокированы (возможно, исключительно) любым процессом, который обрабатывает загрузку (WebDAV или FTP).

Это вызывает исключения, которые вы наблюдали, и, скорее всего, потому что механизм теневого копирования не может читать новые сборки, пока они не записаны (а WebDAV или FTP снимают блокировки записи).

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

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

В IIS нет встроенного механизма, обеспечивающего «атомарное» развертывание, то есть загрузите все свои вещи, а затем переключитесь на их выполнение. IIS будет продолжать обслуживать запросы к сайту, а ASP.NET будет продолжать обнаруживать изменения файлов при загрузке приложения.

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

App_Offline.htm - Скотт Гатри
App_Offline.htm и работа с функцией «IE Friendly Errors»

Вы также можете найти эту статью полезной:

Как: подготовиться к развертыванию веб-проекта

Существует несколько более сложная альтернатива, которая включает две папки, например:

d:\websites\site\www-A d:\websites\site\www-B

Работающий сайт указывает на d:\websites\site\www-A, а вы развертываете в d:\websites\site\www-B. Когда вы будете готовы, вы переключите сайт в папку d:\websites\site\www-B.

Когда вы приходите к развертыванию следующей сборки, вы развертываете в d:\websites\site\www-A и переключаетесь на нее, когда вы счастливы.

Недостатком является то, что вам нужно быть в тонусе и помнить, какая папка какая.

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

2 голосов
/ 23 декабря 2010

Мой сценарий развертывания останавливает веб-сайт и отображает страницу «Пожалуйста, подождите, пока сайт обновляется ...», которая обновляется каждые 15 секунд. Поскольку развертывание занимает менее минуты, похоже, это решает проблему.

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