对图形 api 的调用失败,并出现莫名其妙的日志,并且未捕获套接字异常

问题描述 投票:0回答:1

描述错误 调用 graph.microsoft.com 时,我们遇到间歇性故障。该异常不是很清楚,并且调试该问题非常困难。我实际上无法在本地重现它。

我们的应用程序是在 Kubernetes 上运行的 .net core 2.1 应用程序。我们尝试使用以下代码获取用户会员资格

var memberIds = await graphClient.Me.TransitiveMemberOf.Request(userOptions).GetAsync();
userMemberships = memberIds.Select(o => o.Id).ToList();

while (memberIds.NextPageRequest != null)
{
     memberIds = await memberIds.NextPageRequest.GetAsync();
     userMemberships.AddRange(memberIds.Select(o => o.Id).ToList());
}

从跟踪中并不清楚错误实际上在哪里,但上面的行是我们称为图形的唯一行,因此我们尝试将其包装在 try catch 中:

try {
 // get members
} catch(ServiceException e) {
  // log something
}

这是异常跟踪:

System.Net.Http.HttpRequestException:
   at System.Net.Http.ConnectHelper+<EstablishSslConnectionAsyncCore>d__5.MoveNext (System.Net.Http, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Threading.Tasks.ValueTask`1.get_Result (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Net.Http.HttpConnectionPool+<CreateConnectionAsync>d__44.MoveNext (System.Net.Http, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Threading.Tasks.ValueTask`1.get_Result (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Net.Http.HttpConnectionPool+<WaitForCreatedConnectionAsync>d__49.MoveNext (System.Net.Http, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Threading.Tasks.ValueTask`1.get_Result (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Net.Http.HttpConnectionPool+<SendWithRetryAsync>d__39.MoveNext (System.Net.Http, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter.GetResult (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Net.Http.AuthenticationHelper+<SendWithAuthAsync>d__17.MoveNext (System.Net.Http, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter.GetResult (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Net.Http.RedirectHandler+<SendAsync>d__4.MoveNext (System.Net.Http, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter.GetResult (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Net.Http.DiagnosticsHandler+<SendAsync>d__2.MoveNext (System.Net.Http, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
Inner exception System.IO.IOException handled at System.Net.Http.ConnectHelper+<EstablishSslConnectionAsyncCore>d__5.MoveNext:
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Net.Security.SslState.StartSendBlob (System.Net.Security, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Net.Security.SslState.ForceAuthentication (System.Net.Security, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Net.Security.SslState.ProcessAuthentication (System.Net.Security, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Net.Security.SslStream.BeginAuthenticateAsClient (System.Net.Security, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Net.Security.SslStream+<>c.<AuthenticateAsClientAsync>b__47_0 (System.Net.Security, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncImpl (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Threading.Tasks.TaskFactory.FromAsync (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Threading.Tasks.TaskFactory.FromAsync (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Net.Security.SslStream.AuthenticateAsClientAsync (System.Net.Security, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Net.Http.ConnectHelper+<EstablishSslConnectionAsyncCore>d__5.MoveNext (System.Net.Http, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
Inner exception System.Net.Sockets.SocketException handled at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw:

异常信息

The SSL connection could not be established, see inner exception. Unable to read data from the transport connection: Connection reset by peer. Connection reset by peer

重现 我无法重现。我已经通过在本地计算机上阻止 graph.microsoft.com 设法强制出现类似的异常。这给了我以下内容: 点击这里查看截图 这个错误实际上是在 try catch 中捕获的,所以我很困惑为什么另一个错误没有捕获。

预期行为 我期望 ServiceException 更好地解释问题以及如何解决它

套装版 Microsoft.Graph:v1.17.0 Microsoft.Graph.Core:v1.18.0

其他背景 我读了一点,这可能是由于套接字饥饿造成的。有什么方法可以避免每次都创建新的图形服务实例。我找不到太多材料来告诉我这是否可能。我知道您可以使用 httpclient 实例来做到这一点并继续重用它。我可以看到有一个 GraphClientFactory,但没有说明如何使用它或是否可以重用它。

如果您能提供见解,那就太好了。谢谢

c# .net-core microsoft-graph-api socketexception microsoft-graph-sdks
1个回答
0
投票

您似乎正在使用Graph API SDK。在无法看到您的 Startup.cs 的情况下,我将继续建议使用 GraphServiceClient 进行依赖项注入:

GraphAPI.cs

public class GraphAPI
{
    public static GraphServiceClient Initialize(IConfiguration config)
    {
        return new GraphServiceClient
            (
                new ClientSecretCredential
                (
                    "[TenantID]",
                    "[ClientID]",
                    "[ClientSecret]",
                    new TokenCredentialOptions { AuthorityHost = AzureAuthorityHosts.AzurePublicCloud }
                ),
                new[] { "https://graph.microsoft.com/.default" }
            );
    }
}

启动.cs

public void ConfigureServices(IServiceCollection services)
{
    ...
    // graph api
    services.AddScoped(svc => GraphAPI.Initialize(Configuration));
    ...
}

GraphServiceClient 应该能够处理套接字实例。如果您想更好地控制整个工作流程,我建议您使用 IHttpClientFactory 创建您自己的 HttpClient 并直接调用 Graph REST API。这是我使用此 API 的首选方式。它提高了整个应用程序的性能。它不会在出现问题时抛出异常,而是返回一个 HTTP 响应代码,这在后端更容易、更快。

© www.soinside.com 2019 - 2024. All rights reserved.