1

我試圖創建一個多線程腳本完全爲速度的好處,我寫的同步版本的作品,但速度慢。因爲每個線程正在導入Exchange會話信息,所以我遇到了一堵牆,它與同步代碼一樣慢或慢,特別是隨着服務器數量的增加。如何在運行空間池中多次使用相同的Exchange會話狀態信息?

我確定有更好的方法,我相信這樣做的正確方法是將pssession加載一次並將其附加到運行空間池,但在我的搜索中找不到如何運行的示例與Exchange做到這一點?

下面是我的異步與同步比較。異步代碼的運行時間是12:41,同步代碼的時間是15:02。

cls 
$stopWatch = [System.Diagnostics.Stopwatch]::StartNew(); 
[DateTime]::Now.ToString(); 




    # Fill in these two values 
$connectionUri = "http://[something]/powershell"; 
$servers = @("server1","server2","server3","server4","server5","server6","server7","server8","server9","server10","server11","server12"); 
    # /fill 




# asynchronous 
Write-Host "Asynchronous"; 

# Create session state 

$myString = "this is session state!"; 
$sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault(); 
$sessionstate.Variables.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList "myString" ,$myString, "example string")); 

# Create runspace pool consisting of $numThreads runspaces 
$minimumAmountOfThreads = 1; 
$maximumAmountOfThreads= 15; 
$RunspacePool = [RunspaceFactory]::CreateRunspacePool($minimumAmountOfThreads, $maximumAmountOfThreads, $sessionState, $Host); 
$RunspacePool.Open(); 


$threads = @(); 
$Jobs = @(); 
$asynchronousThreadCount = 0; 
[int]$index = 0; 
foreach ($server in $servers) 
{ 
    $scriptBlock = "import-pssession (new-pssession -ConfigurationName Microsoft.Exchange -ConnectionUri $connectionUri) -AllowClobber; `$returnValue = @(); `$returnValue += Get-ExchangeServer -Identity $server; `$returnValue += Get-MailboxDatabase -Server $server; `$returnValue += Get-MailboxDatabase -Server $server -status; return `$returnValue;"; # working 

    $asynchronousThreadCount ++; 
    $runspaceObject = [PSCustomObject] @{ 
     Runspace = [PowerShell]::Create() 
     Invoker = $null 
    } 
    $runspaceObject.Runspace.RunSpacePool = $runspacePool; 
    $runspaceObject.Runspace.AddScript($scriptBlock) | Out-Null; 
    $runspaceObject.Runspace.AddArgument($server) | Out-Null; 
    $runspaceObject.Invoker = $runspaceObject.Runspace.BeginInvoke(); 
    $threads += $runspaceObject; 
    $elapsed = $StopWatch.Elapsed; 

    Write-Host "Asynchronous created thread $asynchronousThreadCount " $elapsed; 
    $index++; 
} 

Write-Host $threads.Count; 
Write-Host ""; 
Write-Host "Waiting.." -NoNewline; 
Do { 
    Write-Host "." -NoNewline; 
    Start-Sleep -Seconds 1; 
} While ($runspaceObject.Invoker.IsCompleted -contains $false); 

$resultsAsynchronous = @(); 

foreach ($tr in $threads) 
{ 
    $resultsAsynchronous += $tr.Runspace.EndInvoke($tr.Invoker); 
    $tr.Runspace.Dispose(); 
} 

$runspacePool.Close(); 
$runspacePool.Dispose();  

$elapsed = $StopWatch.Elapsed; 
Write-Host ""; 
Write-Host "Multithread elapsed time: $elapsed"; 
Write-Host "Asynchronous return value count " $resultsAsynchronous.Count; 

Write-Host ""; 
Write-Host ""; 
Write-Host ""; 







# synchronous 
Write-Host "Synchronous"; 

$StopWatch.Reset | Out-Null; 
import-pssession (new-pssession -ConfigurationName Microsoft.Exchange -ConnectionUri $connectionUri) -AllowClobber; 
$resultsSynchronous = @(); 
foreach ($server in $servers) 
{ 
    $resultsSynchronous += Get-ExchangeServer -Identity $server; 
    $resultsSynchronous += Get-MailboxDatabase -Server $server; 
    $resultsSynchronous += Get-MailboxDatabase -Server $server -status; 
} 

$elapsed = $StopWatch.Elapsed; 
Write-Host ""; 
Write-Host "Single thread elapsed time: $elapsed"; 
Write-Host "Synchronous return value count " $resultsSynchronous.Count; 
+0

您是否嘗試過使用'-AsJob'開關的同步方法?你可以使用'Get-Job'來監視任務。因爲這些命令被導入,它們會變得很慢。有許多方法可以將對象和變量導入到運行空間中,但正如您所知道的那樣,運行空間的運行非常迅速。 如果你打算使用運行空間,@boeprox在他的博客中有一個[你的方法](https://learn-powershell.net/2013/04/19/sharing-variables-and-live-objects-between- powershell-runspaces /),我已經用它作爲線程作業的指南多次,儘管不是用導入的pssessions。 – brendan62269

+0

感謝您回覆@ brendan62269,在研究了您提供的鏈接(感謝您)後,如果我理解正確,我相信他的示例是在哈希表中共享返回值。也許我錯過了它,但我怎麼能與.setVariable命令共享導入的會話?也許用sessionState.Modules.Add()命令?即使我不相信擁有物被認爲是一個模塊? – Jay

+0

也許這不是正確的方式。您是否嘗試先解析會話,然後將其用作參數?我在評論中沒有足夠的空間來舉例。所以我會寫它作爲答案。 – brendan62269

回答

0

同步的名單是不是真的是我腦子裏想的,或者說,只是路過現場會話作爲一個參數應該工作。循環之前解決會議:

$importSession = new-pssession -ConfigurationName Microsoft.Exchange -ConnectionUri $connectionUri 

做你的foreach,然後添加PARAMS到腳本塊和會話的additionak參數導入:

foreach ($server in $servers) 
{ 
    $scriptBlock = { 
     param($importSession, $server) 
     import-pssession $importSession 
     Get-ExchangeServer -Identity $server 
     Get-MailboxDatabase -Server $server 
     Get-MailboxDatabase -Server $server -status 
    } 

    $asynchronousThreadCount++; 
    $runspaceObject = [PSCustomObject] @{ 
     Runspace = [PowerShell]::Create() 
     Invoker = $null 
    } 
    $runspaceObject.Runspace.RunSpacePool = $runspacePool; 
    $runspaceObject.Runspace.AddScript($scriptBlock) | Out-Null; 
    $runspaceObject.Runspace.AddArgument($importSession) | Out-Null; 
    $runspaceObject.Runspace.AddArgument($server) | Out-Null; 
    $runspaceObject.Invoker = $runspaceObject.Runspace.BeginInvoke(); 
    $threads += $runspaceObject; 
    $elapsed = $StopWatch.Elapsed; 

    Write-Host "Asynchronous created thread $asynchronousThreadCount " $elapsed; 
    $index++; 
} 

我無法驗證會工作,但我認爲不必每次都要對http://[something]/powershell進行一次新的調整,這可能會顯着減少每個線程的加載時間。

相關問題