7

.Net 3.5 を使用して、IIS Express (最終的には完全な IIS) でホストされているかなり単純な WCF Web サービスがあります。service メソッドはかなり面白くありません。

[ServiceContract]
public class MySvc
{
    [OperationContract]
    public Stuff MyMethod(string input)
    {
        Stuff result = DoSomething();
        return result;
    }
}

サービス構成もかなり一般的です。

<system.serviceModel>
    <services>
        <service behaviorConfiguration="MySvcBehavior" name="MySvc">
            <endpoint address="" binding="wsHttpBinding" contract="MySvc">
                <identity>
                    <dns value="localhost"/>
                </identity>
            </endpoint>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="MySvcBehavior">
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>

サービスは、ASPX アプリケーションのコード ビハインドによって使用されます。サービス参照があり、同様に興味深いコードがいくつかあります。

MySvcClient svc = new MySvcClient();
Stuff result = svc.MyMethod("foo");

一度に 1 つの要求である限り、すべてが正常に機能し、クライアント コードは期待される結果を取得します。わーい。

問題は、非常に原始的なストレス テストを行ったときに発生します。クライアントの ASPX ページをブラウザーに読み込み、F5 キーを押したままにします。IIS Express ウィンドウを見ると、最初は結果がステータス 200 として返されますが、数分後にステータス 500 が表示され始めます。この時点で、IIS Express を再起動するまで、サービスはステータス 500 でのみ応答します。(10分程度の待ち時間が目安です。)

クライアント コードにブレークポイントを設定すると、「サーバー上で保留中の安全な会話が多すぎます。後で再試行してください」という完全な戻りメッセージが表示されます。

サーバー コードにブレークポイントを設定すると、コードが呼び出されていないことがわかります。そのため、呼び出しとコードの実際の開始の間のどこかで失敗しています。

私のオンライン検索はあまり有望ではありませんでした.maxPendingSessionsプロパティをオーバーライドするためにカスタムバインディングを作成するという同じ提案と、「[名前のない]構成ファイル設定があると誰かが私に言った」で始まるスレッドにつながりました。 Microsoft がこれをバグとして認識していると主張する壊れたリンク。

maxPendingSessions プロパティに関するリンクには、タイムアウトが 2 分の 128 接続の制限が記載されており、私のテスト方法が一部の接続を中断する場所を確実に確認できます。これは、明らかに悪いテスト方法論の予想される結果ですか? または、これを改善するために構成で何かを行うことができますか?

4

4 に答える 4

4

クライアント側が接続に「使用」を使用していないため、サーバー上で無数の接続が開いているようです。

于 2013-03-20T16:58:58.617 に答える
1

最初に、サーバー クラス マシン上の完全な IIS でこれをテストすることをお勧めします。クライアント OS で IIS Express をパフォーマンス テストに使用することは信頼できません。
それでも問題が解決しない場合は、スロットルを調べて maxConcurrentCalls を制限してください。http://msdn.microsoft.com/en-us/library/vstudio/ms735114(v=vs.90).aspx

于 2013-03-21T09:38:37.710 に答える
1

using ステートメントを推奨する方へ: クライアントを閉じるために using ステートメントを使用しないでください。

http://msdn.microsoft.com/en-us/library/aa355056.aspxを参照してください。

クライアントを閉じる代わりに、次のスニペットを使用する必要があります。

try
{
    ...
    client.Close();
}
catch (CommunicationException e)
{
    ...
    client.Abort();
}
catch (TimeoutException e)
{
    ...
    client.Abort();
}
catch (Exception e)
{
    ...
    client.Abort();
    throw;
}

または、明示的な例外をキャッシュしたくない場合は、単にバニラ キャッチを使用します。通信オブジェクトに障害が発生していない場合は、リソースを最大限に活用する操作を再試行できるため、明示的な例外をキャッチしたい場合があります。

サーバーで保留中の会話の問題については、クライアントを正しく閉じると、これはあまり一般的ではなくなりますが、サーバー側のコードに長時間実行されている操作があり、クライアントがキューに入っている場合は、まだ表示されることがあります. この場合、MaxPendingChannels の値を増やすには、クライアント側と受信側の構成ファイルの両方でカスタム バインディングを使用するか、サービスを開始する前に受信側でバインディングをプログラムで変更する必要があります。.NET 3.5 を使用している場合、MaxPendingChannels のデフォルト値は実際には 4 です。値は、.NET 3.0 では 128 であるとされています。どちらも低いと思います。

http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/745b95d2-1480-4618-89f5-1339d6ee228dを参照してください。

于 2013-04-09T16:06:14.150 に答える
0

対象のサーバーへの接続が多すぎます。適切な方法で接続を閉じるには、いくつかの方法があります。既に述べたようusingに、WCF プロキシには常にステートメントが必要です。

それ以外にも、プロキシを開くときにリクエストを行う必要があるというバグがありました(ありますか?)。プロキシを作成するとき、プロキシは約 2 分間、サーバーにリクエストを送信することができます。存在する場合は、タイマーを無効にして、プロキシのクリーンアップを許可します。リクエストが行われなかった場合、プロキシは実際に接続を閉じる前にタイムアウトを待機します。今回はそうではないかもしれませんが、完全を期すために追加しました。

これを回避する 1 つの方法は、(ASP.NET) キャッシュを利用することです。System.Web.Caching.Cacheはこれの良い候補です。これにより、特定の (最終的にスライドする) 期間の結果をキャッシュできます。このようにして、たとえば 2 分ごとに 1 つのリクエストのみが行われます。これにより、Web サイト/Web サービスは非常にスケーラブルになります。たとえば、1 分あたり 1000 件のリクエストがある場合、同じサービス コールに対して 1 つの接続のみが使用されました。

これを行う別の方法は、リクエストが高価で待つ価値がない場合、事前にリクエストを行い、レスポンスをキャッシュすることです (ala cron、タスクスケジューラ、または単に別のスレッド)。これにより、ページをすばやく取得できます。

それ以外は、サーバーを正しく構成する必要があります。1 つのクライアントから 128 の同時接続を開く必要はありません。これを、クライアントあたり 8 接続などに制限してみてください。これにより、複数のクライアントを同時に処理できます。また、適切なタイムアウトを設定してみてください。クライアントが接続を閉じるのを 5 分間待っても、実際にはスループットは向上しません。

メッセージの非同期処理も検討してください。追加の接続を処理するために、サービスが I/O で待機する必要がある時間を使用します。WCF サービスが何をしているのかわからないので、これは関係ないかもしれません。

于 2013-03-21T08:18:34.417 に答える