winsock资源不足

本文关键字:资源 winsock | 更新日期: 2023-09-27 18:08:12

我们有一个c# web服务和客户端,都是在Visual Studio 2008(新项目-> ASP)中创建的。Net web服务应用程序)。服务托管在Windows server 2012 R2, IIS 8.5.

当客户端将数据发送到我们的服务时,我们将其转发给第三方服务,将结果保存到数据库并返回给客户端。

问题是,在一些罕见的情况下,当我们的服务处于高负载(每秒许多请求)时,它开始抛出' winsock资源不足,无法完成套接字连接初始化'。

我们发现我们的web服务正在打开许多TCP连接到第三方服务,并使它们处于TIME_WAIT状态。当此类连接的数量达到很高的数量(大约17000)时,整个服务器将失去建立任何新连接的能力。从远程桌面到互联网浏览器,一切都停止工作。这将持续几分钟,然后,当Windows开始关闭这些连接时,它将正常恢复。

对于与第三方服务的通信,我们的服务在整个生命周期中只使用一个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 ?我们应该为每个请求打开一个新的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;

谢谢!

winsock资源不足

我想我们可能已经解决了" winsock资源不足"的问题。

我们设置了以下注册表值:HKEY_LOCAL_MACHINE'SYSTEM'CurrentControlSet'services'Tcpip'Parameters'MaxUserPort = 60000HKEY_LOCAL_MACHINE'SYSTEM'CurrentControlSet'services'Tcpip'Parameters'TcpTimedWaitDelay = 30

在峰值时刻,我们对生产环境的最大预期负载是每秒150个请求。这意味着在windows开始释放连接之前,我们将在30秒内创建4500个连接。这远远低于60000,应该确保这个问题不会再发生。

我们让系统以每秒150个请求的速度运行了3天,问题没有发生。

根据您的推荐,BLIND.BLINDSoapClient继承自System.ServiceModel.ClientBase。这个类是IDisposable,这意味着你应该总是处置它,当你完成它(在后台它调用关闭-关闭通信对象在后台)。

即:

using(var client = new BLIND.BLINDSoapClient(base.binding, base.address)) {
  // enjoy client
}

最终可能会有一些限制使您的服务器崩溃。您可以:

  1. 在iis上设置允许访问站点/web服务的请求数量限制-参见http://www.iis.net/configreference/system.applicationhost/sites/sitedefaults/limits,在重载情况下,您对web服务的调用偶尔会失败-但在客户端
  2. 将您的web服务从一个盒子解决方案移动到web farm解决方案(一个盒子作为负载平衡器,根据当前负载将请求委托给多个盒子)
  3. 将您的web服务移动到云-如亚马逊或Azure(相同的2)。,只是你不需要关心负载均衡器)