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;
ありがとうございました!