SharePoint / sp-dev-docs

SharePoint & Viva Connections Developer Documentation
https://docs.microsoft.com/en-us/sharepoint/dev/
Creative Commons Attribution 4.0 International
1.24k stars 1k forks source link

CSOM for Core (Microsoft.SharePointOnline.CSOM) causes Socket Exhaustion #7885

Open lengkeng opened 2 years ago

lengkeng commented 2 years ago

Target SharePoint environment

SharePoint Online

What SharePoint development model, framework, SDK or API is this about?

SharePoint CSOM

Developer environment

Windows

What browser(s) / client(s) have you tested

Additional environment details

Describe the bug / error

CSOM Core uses HttpWebRequest, which creates new instances of HttpClient, and could exhausts the available TCP sockets on a system quickly. See references:

To exacerbate the issue, .Net 5 no longer supports System.Net.ServicePointManager, which used to allow us to set the DefaultConnectionLimit, and HttpClient in .Net 5 allows for int.Max of connections per destination server by default. As a result of this combination, under high volume in .Net 5, we need to be able to limit the number of connections per destination server. In .Net 5 and .Net 6, the recommended way to do this is by passing in a SocketsHttpHandler or an HttpClient.

Steps to reproduce

  1. Making a ton of CSOM calls over a period of time
  2. Run netstat -ano and inspect the number of TCP connections in TIME_AWAIT

Expected behavior

CSOM core to use HttpClient and allow caller to pass in a HttpMessageHandler (such as SocketsHttpHandler) instead of HttpWebRequest, as recommended in documentation https://docs.microsoft.com/en-us/dotnet/core/compatibility/networking/6.0/webrequest-deprecated

ghost commented 2 years ago

Thank you for reporting this issue. We will be triaging your incoming issue as soon as possible.

patrikhellgren commented 2 years ago

@lengkeng There is a SPWebRequestExecutor that uses HttpClient available in PnP.Framework and this can be used instead of the default SPWebRequestExecutor in CSOM. You can use the static HttpClient available in PnP.Framework (like in the example) or you can provide your own. See pnp/pnpframework#261 for more info.

Usage example:

var authManager = new PnP.Framework.AuthenticationManager(clientId, certificate, tenantId);
var clientContext = authManager.GetContext(siteUrl);
clientContext.WebRequestExecutorFactory = new HttpClientWebRequestExecutorFactory(PnPHttpClient.Instance.GetHttpClient());
clientContext.Load(clientContext.Web, w => w.Title);
await clientContext.ExecuteQueryRetryAsync();
AJIXuMuK commented 2 years ago

@lengkeng - will @patrikhellgren approach work for you?

lengkeng commented 2 years ago

Hey sorry for the late response. Thank you for the suggestion @patrikhellgren We have been looking into this option. I will update here as soon as we have a result.

lengkeng commented 2 years ago

Folks, we ended up cloning just one file - HttpClientWebRequestExecutorFactory. It ran locally fine on .net 48 but we are seeing an issue running on .net 5 in AKS. Unfortunately I don't have the details but just want to update this thread before I go OOO for a few days. I will update again when we have more info.