如何在运行空间池中多次使用相同的Exchange会话状态信息?

时间:2017-07-19 21:46:17

标签: multithreading powershell exchange-server session-state runspace

我正在尝试完全创建一个多线程脚本以获得速度,我编写的同步版本工作但速度很慢。我碰到了一堵墙,因为每个线程都在导入Exchange会话信息,它比同步代码慢或慢,特别是随着服务器数量的增加。

我确信有更好的方法,我相信这样做的正确方法是加载pssession一次并将其附加到运行空间池,但在我的搜索中我找不到如何的工作示例用Exchange做到这一点?

下面是我的异步vs同步比较。异步代码的运行时间为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;

1 个答案:

答案 0 :(得分:0)

同步列表并不是我想到的,只是将实时会话作为参数传递应该有效。在循环之前解析会话:

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

执行你的foreach然后将params添加到你的脚本块中,并为要导入的会话添加一个extraak参数:

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执行new-pssession可能会显着减少每个线程的加载时间。