0

何百もの同時要求を wcf サービスに送信できるアプリケーションがあります。サービスは、http フェデレーション バインディングを公開しています。

現在、単一のクライアントと TPL を使用して、複数のスレッドでリクエストを送信しています。また、system.net の最大接続数の設定を 1000 に変更して、Windows が wcf を最大 2 つの同時要求に制限しないようにしました。

認証トークンなどを取得しているため、最初のリクエストに時間がかかることがわかります。その後、リクエスト時間は通常大幅に短縮され始めますが、断続的にスパイクが発生し、サーバー ログとは相関しません。

これが高スループットの非常にスケーラブルなクライアントにアプローチする最良の方法であるかどうか疑問に思っています。

複数のスレッド間で Client プロキシを共有し、複数のスレッド間で ChannelFactory を共有してみました。すべてのスレッドは TPL を使用して実行されます。

バインディングが表示されます

<basicHttpBinding>
        <binding name="Binding1" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:05:00" closeTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
          <security mode="TransportWithMessageCredential">
            <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
            <message clientCredentialType="UserName" algorithmSuite="Default"/>
          </security>
        </binding>
      </basicHttpBinding>
4

2 に答える 2

2

あなたは、単一のクライアント インスタンスを使用しており、TPL を使用して作業を展開していると述べています。WCF クライアント インスタンスは、技術的にはスレッド セーフではありません。クライアントを作成するコストは非常に安価であり、新しいインスタンスを作成することを恐れる必要はありませんClose()

次に、並行性を得るために TPL だけを使用するべきではありません。WCF 呼び出しを行っているときは、ネットワーク I/O とサーバーからの応答を待っていることがすべてです。クライアントで行っていることを確認する必要があるのは、非同期 WCF 契約を使用していることです。次に、これらを TPL と組み合わせてTask.Factory.FromAsync、呼び出しが返された後に実行する必要がある他のワークフローを連鎖させることができます。例えば:

[ServiceContract]
public interface IMyService
{
    [OperationContract(AsyncPattern=true)]
    IAsyncResult BeginDoSomething();
    SomeResultType EndDoSomething(IAsyncResult result);
}

// Somewhere in the client app you store your channel factory (these are "expensive", these you cache)
ChannelFactory<IMyService> channelFactory = new ChannelFactory<IMyService>();

public void MyClientMethod()
{
   // Create a client channel
   IMyService myServiceChannel = channelFactory.CreateChannel();

   // Use TPL's FromAsync to invoke the async WCF call and wrap that up with the familiar Task API
   Task<SomeResultType>.Factory.FromAsync(myServiceChannel.BeginDoSomething
                                          myServiceChannel.EndDoSomething,
                                          null)
                               .ContinueWith(antecdent =>
                               {
                                    try
                                    {
                                        // NOTE: exception will be thrown here if operation failed
                                        SomeResultType result = antecedent.Result;

                                        // ... continue processing the result ...
                                    }
                                    finally
                                    {
                                        // NOTE: depending on your configuration you might want to watch for errors and .Abort() here too
                                        ((IClientChannel)myServiceChannel).Close();
                                    }
                               });      
}

すべてのスケーラビリティは、そのクライアント呼び出しで非同期 I/O を使用することから得られます。

于 2012-04-11T21:58:00.490 に答える
1

WCFサービスとWCFクライアント(ClientBaseまたはChannelFactoryを直接使用)の両方での本番パフォーマンスの問題のいくつかは、オブジェクトの処理がお粗末なために.NETガベージコレクターが多くの作業を強制されるためです。パフォーマンスモニターを使用して、実行時に.NETガベージコレクターの動作をチェックし、これがスパイクの原因であるかどうかを確認します。

GCの問題である場合は、サービスとクライアントコードを確認する必要があります。サービスでは、オブジェクトインスタンスのスコープが可能な限り制限されていることを確認してください。これにより、インスタンスのほとんどがGen0でガベージコレクションされ、最も頻繁に発生します。クライアントコードも確認する必要がありますが、サービスコードでは特に重要です。

また、両方のサービス、特にクライアントで、IDisposableを実装するオブジェクトインスタンスが、WCFクライアントインスタンスのEXCEPTusingステートメントで適切にラップされていることを確認してください。WCFクライアントの適切な廃棄を処理するには、この簡単なブログ投稿で適切なパターンを確認してください。依存性注入コンテナを使用している場合、これは注意が必要です。理由の詳細については、「WCFを使用しない」を検索してください。BasicHttpBindingとWsHttpBindingの一部の構成では、ずさんな廃棄を処理できますが、セッションを使用するバインディングでは、GCの問題が発生しやすくなります。

于 2012-04-11T16:00:26.997 に答える