8

呼び出す必要がある URL が数十万あります。これらは、それらを処理し、ステータス コードをテーブルに書き込むアプリケーション サーバーへの呼び出しです。応答 (成功/失敗) を待つ必要はありません。サーバーが要求を受け取っただけです。また、Tomcat が処理できる同時要求の数を調べていないため、一度に実行できる同時ジョブの数を指定できるようにしたいと考えています。

これは私がこれまでに得たものであり、基本的には、URL呼び出しではなく、他の誰かが同様のことを試みたものです。テキスト ファイルには、それぞれの行に各 URL が含まれています。URL は次のようになります。

http://webserver:8080/app/mwo/services/create?server=ServerName&e1user=admin&newMWONum=123456&sourceMWONum=0&tagNum=33-A-1B

そしてコード:

$maxConcurrentJobs = 10
$content = Get-Content -Path "C:\Temp\urls.txt"

foreach ($url in $content) {
    $running = @(Get-Job | Where-Object { $_.State -eq 'Running' })
    if ($running.Count -le $maxConcurrentJobs) {
        Start-Job {
             Invoke-WebRequest -UseBasicParsing -Uri $using:url
        }
    } else {
         $running | Wait-Job -Any
    }
    Get-Job | Receive-Job
}

私が抱えている問題は、「ジョブ」ごとに 2 つのエラーが発生することであり、その理由がわかりません。URL 配列 $content をダンプすると問題なく表示され、Invoke-WebRequest を 1 つずつ実行するとエラーなく動作します。

126    Job126          BackgroundJob   Running       True            localhost            ...                
Invalid URI: The hostname could not be parsed.
    + CategoryInfo          : NotSpecified: (:) [Invoke-RestMethod], UriFormatException
    + FullyQualifiedErrorId : System.UriFormatException,Microsoft.PowerShell.Commands.InvokeRestMethodComman 
   d
    + PSComputerName        : localhost

Invalid URI: The hostname could not be parsed.
    + CategoryInfo          : NotSpecified: (:) [Invoke-RestMethod], UriFormatException
    + FullyQualifiedErrorId : System.UriFormatException,Microsoft.PowerShell.Commands.InvokeRestMethodComman 
   d
    + PSComputerName        : localhost

ヘルプまたは代替の実装をいただければ幸いです。私はPowerShellを使用しないことにオープンですが、Windows 7デスクトップまたはWindows 2008 R2サーバーに限定されており、ネットワークの遅延を削減するために、URLでlocalhostを使用してサーバー自体で最終スクリプトを実行することになるでしょう。

4

3 に答える 3

14

ジョブを使用すると、新しいジョブごとに新しいプロセスが生成されるため、大量のオーバーヘッドが発生します。

代わりに実行空間を使用してください!

$maxConcurrentJobs = 10
$content = Get-Content -Path "C:\Temp\urls.txt"

# Create a runspace pool where $maxConcurrentJobs is the 
# maximum number of runspaces allowed to run concurrently    
$Runspace = [runspacefactory]::CreateRunspacePool(1,$maxConcurrentJobs)

# Open the runspace pool (very important)
$Runspace.Open()

foreach ($url in $content) {
    # Create a new PowerShell instance and tell it to execute in our runspace pool
    $ps = [powershell]::Create()
    $ps.RunspacePool = $Runspace

    # Attach some code to it
    [void]$ps.AddCommand("Invoke-WebRequest").AddParameter("UseBasicParsing",$true).AddParameter("Uri",$url)

    # Begin execution asynchronously (returns immediately)
    [void]$ps.BeginInvoke()

    # Give feedback on how far we are
    Write-Host ("Initiated request for {0}" -f $url)
}

リンクされた ServerFault の投稿に記載されているようInvoke-Parallelに、基本的に上記のことを行う のような、より一般的なソリューションを使用することもできます

于 2015-07-20T19:43:57.223 に答える
1

I agree with the top post to use Runspaces. However the provided code doesn't show how to get data back from the request. Here's a PowerShell module recently published to my GitHub page:

https://github.com/phbits/AsyncHttps.

It will submit async HTTP requests to a single domain over SSL/TLS (TCP port 443). Here's an Example from the README.md

Import-Module AsyncHttps
Invoke-AsyncHttps -DnsName www.contoso.com -UriPaths $('dir1','dir2','dir3')

It returns a System.Object[] containing the results of each request. The result properties are as follows:

Uri       - Request Uri
Status    - Http Status Code or Exception Message
BeginTime - Job Start Time
EndTime   - Job End Time

After looking at your example, you'll probably need to make the following modifications:

  1. Allow usage of an alternative port (webserver:8080). The easiest would be to update the URI in the scriptblock. Alternatively add another parameter to the module and scriptblock just for the port.
  2. Test that Query Parameters are properly formatted and not mangled by percent encoding when used in the HTTP request. Consider skipping the use of UriBuilder in the scriptblock as long as your list of Uri Paths are known to be OK.
于 2019-05-07T19:53:53.953 に答える