Chúng tôi có dịch vụ web và khách hàng C#, cả hai được tạo trong Visual Studio 2008 (dự án mới -> ứng dụng dịch vụ web ASP.Net). Dịch vụ được lưu trữ trên máy chủ Windows 2012 R2, IIS 8.5.Không đủ tài nguyên winsock
Khi khách hàng gửi dữ liệu đến dịch vụ của chúng tôi, chúng tôi chuyển tiếp nó đến dịch vụ của bên thứ ba, lưu kết quả vào cơ sở dữ liệu và gửi lại cho khách hàng.
Vấn đề là, trong một số trường hợp hiếm hoi, khi dịch vụ của chúng tôi chịu tải nặng (nhiều yêu cầu mỗi giây), nó bắt đầu ném 'Không đủ tài nguyên chiến thắng để hoàn thành việc khởi tạo kết nối socket'.
Chúng tôi thấy rằng dịch vụ web của chúng tôi đang mở nhiều kết nối TCP cho các dịch vụ của bên thứ ba và để chúng ở trạng thái TIME_WAIT. Khi số lượng kết nối như vậy đạt đến số lượng cao (khoảng 17000), toàn bộ máy chủ sẽ mất khả năng thực hiện bất kỳ kết nối mới nào. Mọi thứ từ máy tính từ xa đến trình duyệt internet đều ngừng hoạt động. Điều này kéo dài trong một vài phút, và sau đó, khi Windows bắt đầu đóng các kết nối đó, nó sẽ tiếp tục bình thường.
Để liên lạc với dịch vụ bên thứ 3, dịch vụ của chúng tôi chỉ sử dụng một phiên bản SoapClient trong toàn bộ thời gian sử dụng của nó. Nó được tạo ra khi khởi tạo và không bao giờ bị đóng hoặc bị phá hủy; các phiên bản mới không bao giờ được tạo.
BLIND.BLINDSoapClient client = new BLIND.BLINDSoapClient(base.binding, base.address);
Khi gửi dữ liệu đến các dịch vụ bên thứ 3 chúng tôi chỉ đơn giản là gọi phương thức web của mình, và để lại nó như thế mà không đóng, xử lý hoặc làm bất kỳ dọn dẹp:
BLIND.Answer answer = client.Search(...);
..save to database
return answer;
Có bất cứ điều gì chúng tôi có thể làm gì để tránh việc xây dựng các kết nối time_wait này?
Có cách nào tốt hơn để quản lý SoapClient (s)? Chúng ta có nên mở một ứng dụng xà phòng mới cho mọi yêu cầu và đóng chúng theo cách thủ công không?
Nếu đó là có liên quan, đây là cách ràng buộc của chúng tôi được thiết lập:
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;
Cảm ơn bạn!
Đây là lớp được tạo bởi studio trực quan khi chúng tôi thêm tham chiếu vào dịch vụ web của bên thứ ba. Nhấp chuột phải Tham khảo dịch vụ -> Thêm tham chiếu dịch vụ – dbrckovi