2016-06-15 7 views
0

複数のリモートホストでスクリプト(または複数のスクリプト)を呼び出す必要があります。パフォーマンスを向上させるために並行して実行する必要がある複数のホスト上の環境インストールとしてこれを検討してください。これらのスクリプトが呼び出されるように指示するアプリケーションは、C#で記述されています。 PowerShell C#ホストを使用して、リモートターゲットマシン上のスクリプトを呼び出しています。PowerShell C#ホスト - 複数の同時リモートコマンド呼び出し

例(私は、リモートマシン上で並列スクリプトの呼び出しを達成しようとしています):

Parallel.ForEach(allActions.GroupBy(a=>a.TargetHostname), hostActions => 
{ 
    foreach (var action in hostActions) 
    { 
     action.Execute(); // Implementation of "execute" will contain remote PowerShell call 
    } 
}); 

それぞれ「実行」メソッドは、その後、以下を呼び出しますでの実装:

public ICollection<string> InvokeCommandOnRemoteHost(string targetHost, string command, string arguments) 
    { 
     var runspaceConfiguration = RunspaceConfiguration.Create(); 
     using (var runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration)) 
     { 
      runspace.Open(); 

      using (var pipeline = runspace.CreatePipeline()) 
      { 
       var psCommand = new Command(@"..\Remote-CommandInvocation.ps1"); 
       psCommand.Parameters.Add("targetHost", targetHost); 
       psCommand.Parameters.Add("application", command); 
       psCommand.Parameters.Add("arguments", arguments); 

       pipeline.Commands.Add(psCommand); 

       var result = pipeline.Invoke(); 
       //. . . 

注:ただしRemote-CommandInvocation.ps1はリモートセッションを作成し、リモートPC上でコマンドを呼び出す( "new-pssession"または "enter-pssession"を使用して)。

しかし、私はrunspaceの作成にかなりの時間がかかることに気付きました。例えば、"RunspaceConfiguration.Create();"私のボックスで約500msかかる(VSプロファイリングによると)。 "runspace.Open();" 1.5秒かかる。コマンド実行あたりのコストはすべて2秒です。

明らかに、このコストはリモートコマンドの呼び出しごとに支払われるため、最適ではありません。

次の向上は、アプリケーションの存続期間RunspacePoolを共用して並列にコマンドを呼び出すときに、そこから実行空間を再利用することであった。

public RemoteCommandInvoker() // ctor, singleton class 
    { 
     var iss = InitialSessionState.CreateDefault2(); 
     rsp = RunspaceFactory.CreateRunspacePool(iss); 
     rsp.SetMinRunspaces(5); 
     rsp.SetMaxRunspaces(25); 
     rsp.ThreadOptions = PSThreadOptions.UseNewThread; 
     rsp.Open(); 
    } 

    public ICollection<string> InvokeCommandOnRemoteHost(string targetHost, string command, string arguments) 
    { 
     var resultList = new List<string>(); 

     var ps = PowerShell.Create(); 
     ps.RunspacePool = rsp; 
     ps.AddCommand(@"..\Remote-CommandInvocation.ps1"); 
     ps.AddParameter("targetHost", targetHost); 
     ps.AddParameter("application", command); 
     ps.AddParameter("arguments", arguments); 
     var result = ps.Invoke(); 
     //... 

実行空間プールの初期化のコストはほぼ同じであるが(〜2秒)、これはアプリケーションライフタイムごとに1回実行され、それ以降のすべてのコマンド呼び出しはすばやく実行されます。

質問:

これは、複数のリモートマシン上で複数のスクリプトの呼び出しを最適化するための正しいアプローチであり、またはそれは異なって行われ、またはより良い行われるべき?この場合、制限されたプールまたはリモートプールを使用する必要がありますか?

ありがとうございました。

答えて

1

は、リモート実行空間サンプルをチェックアウト:https://msdn.microsoft.com/en-us/library/ee706591(v=vs.85).aspx

あなたはおそらく、新しいPowerShellセッションを開始するためのPowerShellを呼び出すためにC#を使用していくつかの時間を失うことです。

私はこれがあなたのために少し速く動作するかもしれないと思う:

Collection<PSObject> results; 
WSManConnectionInfo connectionInfo = new WSManConnectionInfo() { ComputerName = "COMPUTER" }; 
using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo)) 
{ 
    runspace.Open(); 
    using (PowerShell ps = PowerShell.Create()) 
    { 
     ps.Runspace = runspace; 
     ps.AddScript("something to run"); 

     results = ps.Invoke(); 

     if(ps.HadErrors) 
     { 
      //Throw or log if you want 
      //ps.Streams.Error.ElementAt(0).Exception; 
     } 
    } 
    runspace.Close(); 
} 
関連する問題