Узкое место в развертывании компонентов управления выпуском vNext
Мы используем Release Management 2015 с шаблонами выпуска vNext. У нас есть развертывание компонентов на основе DSC на основе Powershell для каждой части нашего приложения, и фактически у нас есть два отдельных приложения, которые развертываются и находятся в активной разработке и часто развертываются практически одновременно.
Мы очень часто получаем следующую ошибку во время развертываний:
OperationFailedException: новое развертывание не допускается, так как выполняется другое развертывание. Повторите попытку развертывания через некоторое время.
Полная трассировка стека показывает, что ошибка исходит не от самого Powershell, а от системы Release Management, которая отвечает за выполнение сценария powershell на целевой машине:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Microsoft.TeamFoundation.Release.Common.Helpers.OperationFailedException: New deployment is not allowed as an another deployment is in progress. Retry the deployment after sometime.
at Microsoft.TeamFoundation.Release.EnvironmentProvider.OnPrem.Implementation.OnPremDeploymentProvider.ReadDeploymentResponse(DeploymentResponse response)
at Microsoft.TeamFoundation.Release.EnvironmentProvider.OnPrem.Implementation.OnPremDeploymentProvider.RunScript(String scriptPath, String configurationPath, MachineSpecification machine, StorageSpecification storage, Dictionary`2 configurationVariables)
at Microsoft.TeamFoundation.Release.MonitorServices.Dsc.OnPrem.OnPremDeploymentActions.InvokePlatform(String activityId, MachineSpecification machineSpecification, StorageSpecification storageSpecification, String scriptPath, String configurationPath, Dictionary`2 configurationVariables)
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Microsoft.TeamFoundation.Release.DeploymentAgent.Services.Deployer.Dsc.DscComponentInstaller.InvokeMethodByReflection(String methodArguments)
Вышеуказанная ошибка приводит к сбою всего развертывания, и мы вынуждены повторить этап или все развертывание, чтобы завершить его.
Есть два сценария, которые вызывают это:
- Два шаблона выпуска одновременно выполняют свои скрипты powershell на одном целевом сервере.
- Один шаблон выпуска имеет параллельный поток управления, который содержит два разных компонента, которые оба выполняют сценарии на одном целевом сервере.
Другими словами, механизм, который Release Management использует для выполнения сценария powershell на удаленном сервере, может казаться, что он выполняет только один сценарий за раз, и у него нет возможности ждать / удерживать, пока другие не завершат работу.
Эта разновидность имеет смысл, если рассматриваемый скрипт активно изменяет сервер, на котором он выполняется, но в нашем случае сервер действует как промежуточная область для запуска скрипта. "Настоящая" цель сценария не имеет ничего общего с сервером, на котором выполняется PowerShell.
Помимо наличия компонента "сервер на одновременно развернутый компонент" (вау), какова здесь работа? Это кажется серьезным упущением, и это серьезно заставляет меня задуматься о том, чтобы вообще отказаться от Управления релизами.
2 ответа
Как я объяснил в другой статье сегодня, способ развертывания MS Release Management немного нелогичен: вместо того, чтобы просто выполнить сценарий развертывания Powershell на целевом сервере с помощью PSRemoting, он использует PSRemoting для установки службы Windows (VisualStudioRemoteDeployer.exe
) на целевом сервере. Затем эта служба запускает сценарий развертывания локально, и сервер MSRM регулярно опрашивает эту службу Windows (см. Здесь), чтобы определить, завершено ли ее развертывание.
Я подозреваю, что эта странная настройка как-то связана с тем, чтобы избежать проблемы двойного перехода - так что он позволяет вашему сценарию выполнить второй переход с целевого сервера на другой сервер, например, для вызова веб-службы.
В любом случае, эта служба Windows, вероятно, образует узкое место, потому что может быть только один такой экземпляр, работающий на сервер, - следовательно, тот факт, что параллельное развертывание компонентов на одном и том же сервере, похоже, конфликтует.
Я думаю, что ваши проблемы возникают из-за того, что вы выбрали установку, в которой "сервер выступает в качестве промежуточной области для запуска сценария" - MS Release Management 2013/2015 не очень хорошо работает в этом сценарии (как вы узнали), Вы должны действительно развернуть свои компоненты непосредственно на целевых серверах, на которых они должны быть установлены, таким образом избегая узкого места промежуточной области.
В следующей версии MS Release Management будут использоваться агенты развертывания, которые будут служить промежуточной точкой, с которой компоненты будут развернуты на других серверах. Это помогает уменьшить количество соединений, которые вы должны разрешить в брандмауэре между MS Release Management и целевыми серверами (возможно, именно поэтому вы выбрали настройку промежуточной области), но при этом разрешить параллельное (или, по крайней мере, поставленное в очередь) развертывание.
У меня была проблема с запуском скриптов Powershell на удаленных серверах. Я закончил тем, что пошел немного другим маршрутом. Вместо этого я просто запускаю обычную команду Powershell с Invoke-Command
блок. Я считаю, что вы должны быть в состоянии запустить это параллельно.
Function Get-PSCredential($User,$Password) {
$SecPass = ConvertTo-SecureString -AsPlainText -String $Password -Force
$Creds = New-Object System.Management.Automation.PSCredential -ArgumentList $User,$SecPass
Return $Creds
}
$credential = Get-PSCredential -User $deployUser -Password $deployPass
$session = New-PSSession YourServerName -Credential $credential
Invoke-Command -Session $session -ScriptBlock {
# do your work here
}
Если вы работаете как учетная запись службы, которая имеет доступ к компьютеру, вы сможете удалить учетные данные и просто идти с
$session = New-PSSession YourServerName
Я только начал использовать Управление релизами на этой неделе, так что это казалось лучшим способом за это короткое время.
Кроме того, если вы никогда не использовали Invoke-Command
раньше все внутри блока скрипта находится в своей области видимости, поэтому вам нужно передать в него переменные, используя -ArgumentList
если у тебя есть. Проверьте эту статью, если у вас есть еще вопросы по этому поводу.