我需要在多个远程主机上调用脚本(或多个脚本)。将此视为多个主机上的环境安装,应并行完成以提高性能。指示调用这些脚本的应用程序是用C#编写的。我正在使用PowerShell C#Host调用远程目标计算机上的脚本。
示例(我试图在远程计算机上实现并行脚本调用):
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”)。
但我注意到创建运行空间需要相当长的时间,例如调用“RunspaceConfiguration.Create();”在我的盒子上需要大约500毫秒(根据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秒),但现在每个应用程序生命周期执行一次,所有进一步的命令调用都发生得足够快。
问题:
这是优化多个远程计算机上多个脚本调用的正确方法,还是应该以不同方式完成,或者做得更好?在这种情况下是否应使用约束池或远程池?
感谢。
答案 0 :(得分:1)
查看远程运行空间样本:https://msdn.microsoft.com/en-us/library/ee706591(v=vs.85).aspx
通过使用C#调用PowerShell来启动新的PowerShell会话,您可能会浪费一些时间。
我认为这对您来说可能会更快一点:
zip(*[i] * 2)