3

投稿が長くなって申し訳ありませんが、私の状況を引き起こす可能性のあることがたくさんあり、他の投稿に基づいて行ったすべての設定変更を含めようとしました. つまり、私の WCF サービスは、一度に 3 つまたは 4 つの同時クライアント要求に制限されているようです。アプリケーション プールの最大ワーカー プロセス数を高く (約 10) 設定するか、サービス動作の ConcurrencyMode を複数に設定すると、スループットが大幅に向上します (数倍速くなります)。ただし、これらは実際の問題に対する回避策のように見え、独自の問題をもたらします。私は間違っていますか、それとも IIS は負荷を処理するために 1 つのワーカー プロセス内で WCF サービスの多くのインスタンス (数十以上) を起動できるはずですか? どこかに設定がないことはわかっていますが、見つかりません。

編集:これまでの提案を試してみると、私の計算はスループットに欠けていることに気付きました。ForEach ループを使用すると、サーバーで推定同時処理が 20 秒台前半 (タスクあたりの期間 * タスク数 / 合計実行時間) になります。これは、実行されている実際の作業 (スリープ 10 秒) に対してはまだ低いように見えますが、馬鹿げたほど低くはありません。

2番目の編集: @Pabloのコメントを回答としてマークしました。彼の回答と彼のリンクにより、パフォーマンスが大幅に向上する情報が得られたためです(約3倍だと思います)。ただし、フォローアップの質問をしたいと思います-WCF / IIS で同時要求を処理するための合理的な期待は何ですか? CPU、メモリ、および IO がボトルネックではないと仮定すると、リクエストを処理するための (CPU あたりの) 実際の制限/期待値はどれくらいですか? 私が探しているのは、CPU (またはワーカー プロセス) を追加しない限り、おそらくこれ以上大きなブーストを得ることはできないだろうという経験則です。再度、感謝します。

(Windows 2008 Server では、IIS によってホストされ、1 プロセッサ)
WCF Service Config (省略形):

<?xml version="1.0"?>
<configuration>
  <configSections>
  <system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
    <services>
      <service name="FMHIRWCFSvc.IRService" behaviorConfiguration="IRServiceBehavior">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="Binding1" contract="FMHIRWCFSvc.IIRService" />
      </service>
    </services>
    <bindings>
      <basicHttpBinding>
        <binding name="Binding1" maxReceivedMessageSize="104857600">
          <readerQuotas maxArrayLength="104857600"/>
          <security mode="Transport">
            <transport clientCredentialType="None"/>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="IRServiceBehavior">
          <serviceMetadata httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceThrottling
              maxConcurrentCalls = "500"
              maxConcurrentSessions = "500"
              maxConcurrentInstances = "500"
            />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
  <applicationSettings>
    <FMHIRWCFSvc.Properties.Settings>
      <setting name="FMHIRWCFSvc_ir_dev_websvc_IRWebService40" serializeAs="String">
        <value>http://ir-dev-websvc/imageright.webservice/IRWebService40.asmx</value>
      </setting>
    </FMHIRWCFSvc.Properties.Settings>
  </applicationSettings>
  <system.net>
    <connectionManagement>
      <add address="*" maxconnection="500"/>
    </connectionManagement>
  </system.net>
</configuration>

クライアント構成 (省略):

<?xml version="1.0"?>
<configuration>
  <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IIRService" closeTimeout="00:01:00"
          openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
          allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
          maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
          messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
          useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Windows" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="https://{myserveraddress}/FMHIRWCFSvc/IRService.svc"
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IIRService"
        contract="wcf_local.IIRService" name="BasicHttpBinding_IIRService" />
    </client>
  </system.serviceModel>
  <system.net>
    <connectionManagement>
      <add address="*" maxconnection="500"/>
    </connectionManagement>
  </system.net>
</configuration>

クライアント メソッド呼び出し:

static void WCFTesting()
{
    ConcurrentQueue<Exception> exceptionList = new ConcurrentQueue<Exception>();
    int[] taskList = new int[250];
    Parallel.ForEach(taskList, theTask => 
    {
        try
        {
            // Create the WCF client
            BasicHttpBinding binding = new BasicHttpBinding {
                Security = { Mode = BasicHttpSecurityMode.Transport },
                SendTimeout = TimeSpan.FromSeconds(20)
            };
            EndpointAddress endpointAddress = new EndpointAddress("https://{myserveraddress}/FMHIRWCFSvc/IRService.svc");
            IRServiceClient wcfClient = new IRServiceClient(binding, endpointAddress);

            // Call wcf service method that sleeps 10 seconds and returns
            wcfClient.TestCall();
        }
        catch (Exception exception) {
            // Store off exceptions for later processing
            exceptionList.Enqueue(exception);
        }
    });
}

WCF サービス コード:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
...
public string TestCall()
{
    Thread.Sleep(10000);
    return null;
}

洞察や提案をありがとう!

4

2 に答える 2

1

使用しているテスト メカニズムが完全に正しいとは限りません。

を使用Parallel.For()しても、250 個のワーカーが並行して作成されるわけではありません。この場合、ベンチマークをクライアントのプロセッサ構成に最適なものに制限しているように見え、サーバーが処理できるものを実際にテストしていません。

本当に 250 の並列スレッドを呼び出して、それがどのように反応するかを確認したい場合は、すべてのスレッドを手動で作成できます。そのような:

        var exceptionList = new ConcurrentQueue<Exception>();
        const int max = 250;
        int numberOfTasks = max;
        var signal = new ManualResetEvent(false);
        for (var i = 0; i < max; i++)
        {
            var thread = new Thread(() =>
            {
                try
                {
                    // Create the WCF client
                    BasicHttpBinding binding = new BasicHttpBinding
                    {
                        Security = { Mode = BasicHttpSecurityMode.Transport },
                        SendTimeout = TimeSpan.FromSeconds(20)
                    };
                    EndpointAddress endpointAddress = new EndpointAddress("https://{myserveraddress}/FMHIRWCFSvc/IRService.svc");
                    IRServiceClient wcfClient = new IRServiceClient(binding, endpointAddress);

                    // Call wcf service method that sleeps 10 seconds and returns
                    wcfClient.TestCall();
                }
                catch (Exception exception)
                {
                    // Store off exceptions for later processing
                    exceptionList.Enqueue(exception);
                }

                if (Interlocked.Decrement(ref numberOfTasks) == 0) signal.Set();
            });
            thread.Start();
        }
        signal.WaitOne();
于 2012-07-12T22:31:56.147 に答える
0

Parallel.ForEachTask.Startほぼ同じコードになります。タスクが同時に実行されることは保証されていません。

WCF サービスリンクへの非同期呼び出しでテストすることをお勧めします。

于 2012-07-12T22:42:09.703 に答える