5

Visual Studio 2008 で作成された ac# Web サービスとクライアントがあります (新しいプロジェクト -> ASP.Net Web サービス アプリケーション)。サービスは、Windows サーバー 2012 R2、IIS 8.5 でホストされています。

クライアントがデータを当社のサービスに送信すると、それをサードパーティのサービスに転送し、結果をデータベースに保存してクライアントに返します。

問題は、ごくまれに、サービスの負荷が高い (1 秒あたりの要求数が多い) 場合に、「ソケット接続の開始を完了するのに十分な Winsock リソースがありません」というスローを開始することです。

私たちの Web サービスがサードパーティ サービスへの多くの TCP 接続を開き、それらを TIME_WAIT 状態のままにしていることがわかりました。このような接続の数が多数 (約 17000) に達すると、サーバー全体が新しい接続を確立できなくなります。リモート デスクトップからインターネット ブラウザまで、すべてが機能しなくなります。これは数分間続き、Windows がこれらの接続を閉じ始めると、通常どおりに再開します。

サード パーティ サービスとの通信のために、サービスはその全期間を通じて 1 つの SoapClient インスタンスのみを使用します。初期化時に作成され、閉じられたり破棄されたりすることはありません。新しいインスタンスが作成されることはありません。

BLIND.BLINDSoapClient client = new BLIND.BLINDSoapClient(base.binding, base.address);

データをサード パーティ サービスに送信するときは、その Web メソッドを呼び出すだけで、閉じたり、破棄したり、クリーンアップを実行したりせずにそのままにしておきます。

BLIND.Answer answer = client.Search(...);
..save to database
return answer;

この time_wait 接続の蓄積を回避するためにできることはありますか?

SoapClient(s) を管理するより良い方法はありますか? リクエストごとに新しい SOAP クライアントを開き、手動で閉じる必要がありますか?

関連する場合、バインディングの設定方法は次のとおりです。

      binding = new BasicHttpBinding();
      binding.Name = "SLTDSoap";
      binding.CloseTimeout = TimeSpan.FromSeconds(Timeout);
      binding.OpenTimeout = TimeSpan.FromSeconds(Timeout);
      binding.ReceiveTimeout = TimeSpan.FromSeconds(Timeout);
      binding.SendTimeout = TimeSpan.FromSeconds(Timeout);
      binding.AllowCookies = false;
      binding.BypassProxyOnLocal = false;
      binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
      binding.MaxBufferSize = 65536;
      binding.MaxBufferPoolSize = 524288;
      binding.MessageEncoding = WSMessageEncoding.Text;
      binding.TextEncoding = System.Text.Encoding.UTF8;
      binding.TransferMode = TransferMode.Buffered;
      binding.UseDefaultWebProxy = true;

      binding.ReaderQuotas.MaxDepth = 32;
      binding.ReaderQuotas.MaxStringContentLength = 8192;
      binding.ReaderQuotas.MaxArrayLength = 16384;
      binding.ReaderQuotas.MaxBytesPerRead = 4096;
      binding.ReaderQuotas.MaxNameTableCharCount = 16384;

      binding.Security.Mode = (_url.StartsWith("https:")) ? BasicHttpSecurityMode.Transport : BasicHttpSecurityMode.None;
      binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
      binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
      binding.Security.Transport.Realm = "";
      binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
      binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Default;

System.Net.ServicePointManager.DefaultConnectionLimit = 500;

ありがとうございました!

4

2 に答える 2

4

「不十分な winsock リソース」の問題を解決できたのではないかと思います。

次のレジストリ値を設定しました: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\MaxUserPort = 60000 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\TcpTimedWaitDelay = 30

ピーク時の本番環境で予想される最大負荷は、1 秒あたり 150 リクエストです。これは、Windows が解放を開始する前に、30 秒で 4500 の接続を作成することを意味します。これは 60000 をはるかに下回っており、この問題が再発しないようにする必要があります。

これらの設定で 3 日間にわたってシステムを 1 秒あたり 150 リクエストで実行したままにしましたが、問題は発生しませんでした。

于 2014-06-16T11:03:03.040 に答える