PowerShell 作业节流阻塞服务器
PowerShell Job throttle blocking the server
我遇到了一个奇怪的问题,我们的脚本服务器超载并且 运行 资源不足。我们有一个将数据从一个位置复制到另一个位置的脚本,这是在一个包含 200 多行文本的大型输入文件中定义的,格式为 'Source path, Destination path'.
我们现在正在尝试限制我们同时启动的最大作业数,我认为它运行良好。但是由于某种原因,当输入文件包含超过 94 行时,我们仍然 运行 耗尽服务器上的资源。经过一些测试后,这一点变得很明显。
我们尝试将带有 PowerShell 4.0 的 Windows 2008 R2 服务器升级到 4 个处理器和 8 GB RAM,但没有成功。所以我假设我的节流没有按设计工作。
错误代码:
Insufficient system resources exist to complete the requested service.
代码:
$MaxThreads = 4
$FunctionFeed = Import-Csv -Path $File -Delimiter ',' -Header 'Source', 'Destination'
$Jobs=@()
Function Wait-MaxRunningJobs {
Param (
$Name,
[Int]$MaxThreads
)
Process {
$Running = @($Name | where State -eq Running)
while ($Running.Count -ge $MaxThreads) {
$Finished = Wait-Job -Job $Name -Any
$Running = @($Name | where State -eq Running)
}
}
}
$ScriptBlock = {
Try {
Robocopy.exe $Using:Line.Source $Using:Line.Destination $Using:Line.File /MIR /Z /R:3 /W:15 /NP /MT:8 | Out-File $Using:LogFile
[PSCustomObject]@{
Source = if ($Using:Line.Source) {$Using:Line.Source} else {'NA'}
Target = if ($Using:Line.Destination) {$Using:Line.Destination} else {'NA'}
}
}
Catch {
"Robocopy | ERROR: $($Error[0].Exception.Message)" |
Out-File -LiteralPath $Using:LogFile
throw $($Error[0].Exception.Message)
}
}
ForEach ($Line in $FunctionFeed) {
$LogParams = @{
LogFolder = $LogFolder
Name = $Line.Destination + '.log'
Date = 'ScriptStartTime'
Unique = $True
}
$LogFile = New-LogFileNameHC @LogParams
' ' >> $LogFile # Avoid not being able to write to log
$Jobs += Start-Job -Name RoboCopy -ScriptBlock $ScriptBlock
Wait-MaxRunningJobs -Name $Jobs -MaxThreads $MaxThreads
}
if ($Jobs) {
Wait-Job -Job $Jobs
$JobResults = $Jobs | Receive-Job
}
我是不是漏掉了什么?感谢您的帮助。
您正在使用后台作业,实际上 运行 在本地计算机的远程会话中。根据会话配置中的设置,远程会话有意限制资源。您可以使用
检查当前设置
Get-PSSessionConfiguration
并调整设置以增加会话可用的资源
Set-PSSessionConfiguration
您可能需要进行一些测试,以确定您正在达到的资源限制,以及需要进行哪些调整才能使该特定应用程序正常工作。
通过将远程会话的 MaxMemoryPerShellMB 从 1GB 扩大到 2GB 解决了问题 here。请记住,正如 mjolinor 已经指出的那样,Start-Job 正在使用远程 PowerShell 会话,因此该变量适用于 PowerShell 作业。
解法:
# 'System.OutOfMemoryException error message' when running Robocopy and over 94 PowerShell-Jobs:
Get-Item WSMan:\localhost\Shell\MaxMemoryPerShellMB # Default 1024
Set-Item WSMan:\localhost\Shell\MaxMemoryPerShellMB 2048
# Set PowerShell plugins memory from 1 GB to 2 GB
Get-Item WSMan:\localhost\Plugin\Microsoft.PowerShell\Quotas\MaxMemoryPerShellMB # Default 1024
Set-Item WSMan:\localhost\Plugin\Microsoft.PowerShell\Quotas\MaxMemoryPerShellMB 2048
Restart-Service winrm
我遇到了一个奇怪的问题,我们的脚本服务器超载并且 运行 资源不足。我们有一个将数据从一个位置复制到另一个位置的脚本,这是在一个包含 200 多行文本的大型输入文件中定义的,格式为 'Source path, Destination path'.
我们现在正在尝试限制我们同时启动的最大作业数,我认为它运行良好。但是由于某种原因,当输入文件包含超过 94 行时,我们仍然 运行 耗尽服务器上的资源。经过一些测试后,这一点变得很明显。
我们尝试将带有 PowerShell 4.0 的 Windows 2008 R2 服务器升级到 4 个处理器和 8 GB RAM,但没有成功。所以我假设我的节流没有按设计工作。
错误代码:
Insufficient system resources exist to complete the requested service.
代码:
$MaxThreads = 4
$FunctionFeed = Import-Csv -Path $File -Delimiter ',' -Header 'Source', 'Destination'
$Jobs=@()
Function Wait-MaxRunningJobs {
Param (
$Name,
[Int]$MaxThreads
)
Process {
$Running = @($Name | where State -eq Running)
while ($Running.Count -ge $MaxThreads) {
$Finished = Wait-Job -Job $Name -Any
$Running = @($Name | where State -eq Running)
}
}
}
$ScriptBlock = {
Try {
Robocopy.exe $Using:Line.Source $Using:Line.Destination $Using:Line.File /MIR /Z /R:3 /W:15 /NP /MT:8 | Out-File $Using:LogFile
[PSCustomObject]@{
Source = if ($Using:Line.Source) {$Using:Line.Source} else {'NA'}
Target = if ($Using:Line.Destination) {$Using:Line.Destination} else {'NA'}
}
}
Catch {
"Robocopy | ERROR: $($Error[0].Exception.Message)" |
Out-File -LiteralPath $Using:LogFile
throw $($Error[0].Exception.Message)
}
}
ForEach ($Line in $FunctionFeed) {
$LogParams = @{
LogFolder = $LogFolder
Name = $Line.Destination + '.log'
Date = 'ScriptStartTime'
Unique = $True
}
$LogFile = New-LogFileNameHC @LogParams
' ' >> $LogFile # Avoid not being able to write to log
$Jobs += Start-Job -Name RoboCopy -ScriptBlock $ScriptBlock
Wait-MaxRunningJobs -Name $Jobs -MaxThreads $MaxThreads
}
if ($Jobs) {
Wait-Job -Job $Jobs
$JobResults = $Jobs | Receive-Job
}
我是不是漏掉了什么?感谢您的帮助。
您正在使用后台作业,实际上 运行 在本地计算机的远程会话中。根据会话配置中的设置,远程会话有意限制资源。您可以使用
检查当前设置Get-PSSessionConfiguration
并调整设置以增加会话可用的资源
Set-PSSessionConfiguration
您可能需要进行一些测试,以确定您正在达到的资源限制,以及需要进行哪些调整才能使该特定应用程序正常工作。
通过将远程会话的 MaxMemoryPerShellMB 从 1GB 扩大到 2GB 解决了问题 here。请记住,正如 mjolinor 已经指出的那样,Start-Job 正在使用远程 PowerShell 会话,因此该变量适用于 PowerShell 作业。
解法:
# 'System.OutOfMemoryException error message' when running Robocopy and over 94 PowerShell-Jobs:
Get-Item WSMan:\localhost\Shell\MaxMemoryPerShellMB # Default 1024
Set-Item WSMan:\localhost\Shell\MaxMemoryPerShellMB 2048
# Set PowerShell plugins memory from 1 GB to 2 GB
Get-Item WSMan:\localhost\Plugin\Microsoft.PowerShell\Quotas\MaxMemoryPerShellMB # Default 1024
Set-Item WSMan:\localhost\Plugin\Microsoft.PowerShell\Quotas\MaxMemoryPerShellMB 2048
Restart-Service winrm