简体   繁体   English

Microsoft Graph API 超时异常

[英]Microsoft Graph API timeout exception

I'm using Microsoft Graph API library (C#) and wondering if anyone has experienced this:我正在使用 Microsoft Graph API 库 (C#),想知道是否有人遇到过这种情况:
Many of my graph API calls time out from time to time.我的许多图形 API 调用有时会超时。
This can happen to any API call, from getting current user profile to getting sharepoint documents, and so on.这可能发生在任何 API 调用上,从获取当前用户配置文件到获取共享点文档等等。 I've tried updating Microsoft Graph API and dependent Nuget packages to the latest versions, but it doesn't help.我已尝试将 Microsoft Graph API 和依赖的 Nuget 包更新到最新版本,但没有帮助。

To clarify, this application is a Windows console application.澄清一下,这个应用程序是一个 Windows 控制台应用程序。 On Azure side, it is registered as a native application.在 Azure 端,它被注册为本机应用程序。 As a test application, it is a single-threaded application.作为测试应用程序,它是一个单线程应用程序。 No concurrency, race conditions involved.没有并发,涉及竞争条件。 Code logic is as simple as代码逻辑很简单

  1. User logs in.用户登录。
  2. The program makes a Graph API call (shown in eg.1) to get user's profile and this API call times out.该程序进行图形 API 调用(如 eg.1 所示)以获取用户的配置文件,此 API 调用超时。

eg 1.例如 1。

var currentUser = graphClient.Me.Request().GetAsync().Result;

eg 2.例如 2。

var site = _graphClient.Sites[SharePointSiteId].Request().GetAsync().Result;

The symptom is after a minute or two, it throws an AggregationException(because of TPL) which includes a TimeOutException.症状是在一两分钟后,它抛出一个包含 TimeOutException 的 AggregationException(由于 TPL)。
No unauthorized exception.没有未经授权的例外。

I want to know what could be the possible cause and how I can avoid that.我想知道可能的原因是什么以及如何避免这种情况。


UPDATE: Here's a screenshot when the exception happens.更新:这是发生异常时的屏幕截图。 在此处输入图像描述


UPDATE 2: I've tried replacing all the API calls to use "await" directly to wait for results.更新 2:我尝试将所有 API 调用替换为直接使用“await”来等待结果。 because this example code is a console application.因为这个示例代码是一个控制台应用程序。 I put我放

static void Main(string[] args)
{
    // using Stephen Cleary's nuget package: Nito.AsyncEx.Tasks
    MainImp().WaitAndUnwrapException();
}

static async Task MainImp()
{
    // ...
    // Graph API calls

This exception is still thrown from this simple API call:这个简单的 API 调用仍然会抛出此异常:

var currentUser = await graphClient.Me.Request().GetAsync();

An unhandled exception of type 'Microsoft.Graph.ServiceException' occurred in mscorlib.dll Additional information: Code: timeout mscorlib.dll 中出现类型为“Microsoft.Graph.ServiceException”的未处理异常附加信息:代码:超时

Here's the full call stack这是完整的调用堆栈

at Microsoft.Graph.HttpProvider.d__19.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Graph.HttpProvider.d__18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Graph.BaseRequest.d__35.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Graph.BaseRequest.d__31 1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Graph.UserRequest.<GetAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter在 Microsoft.Graph.HttpProvider.d__19.MoveNext() --- 从先前抛出异常的位置开始的堆栈跟踪结束 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)在 System.Runtime.CompilerServices。 TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)在 Microsoft.Graph.HttpProvider.d__18.MoveNext() --- 从先前抛出异常的位置开始的堆栈跟踪结束 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 在 Microsoft.Graph.BaseRequest.d__35.MoveNext() --- 从先前抛出异常的位置开始的堆栈跟踪结束 --- 在 System.Runtime.CompilerServices。 TaskAwaiter.ThrowForNonSuccess(任务任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)在 Microsoft.Graph.BaseRequest.d__31 1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Graph.UserRequest.<GetAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter 1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Graph.UserRequest.<GetAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter 1.GetResult() at SharePointConsoleApp.Program.d__14.MoveNext() in D:\TestProjects\SharePointConsoleApp\Program.cs:line 133 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Nito.AsyncEx.Synchronous.TaskExtensions.WaitAndUnwrapException 1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Graph.UserRequest.<GetAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter 1.GetResult() at SharePointConsoleApp.Program.d__14.MoveNext() in D:\TestProjects\SharePointConsoleApp\Program.cs:line 133 --- 从抛出异常的先前位置开始的堆栈跟踪结束 --- 在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)在 Nito.AsyncEx.Synchronous.TaskExtensions.WaitAndUnwrapException (Task task) at SharePointConsoleApp.Program.Main(String[] args) in D:\TestProjects\SharePointConsoleApp\Program.cs:line 50 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() (任务任务)在 D:\TestProjects\SharePointConsoleApp\Program.cs 中的 SharePointConsoleApp.Program.Main(String[] args):System.AppDomain 的第 50 行。_nExecuteAssembly(RuntimeAssembly 程序集,String[] args)在 System.AppDomain。在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)在 System.Threading.ThreadHelper.ThreadStart_Context(对象状态)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback 回调,对象状态,布尔值 preserveSyncCtx) (ExecutionContext executionContext,ContextCallback 回调,对象状态)在 System.Threading.ThreadHelper.ThreadStart()

First of all if it's an application with user interaction you should never do blocking ( .Wait() or .Result ) calls on the main thread, this will lock-up your application for further user interaction. 首先,如果它是一个具有用户交互的应用程序,则不应该在主线程上执行阻塞( .Wait().Result )调用,这将锁定您的应用程序以进行进一步的用户交互。

So you need to start by using async code, this is a sample of an async Button_Click handler. 因此,您需要从使用异步代码开始,这是异步Button_Click处理程序的示例。 It will give you a warning, but this seems to be one of the use-cases of an async void. 它会给你一个警告,但这似乎是异步void的用例之一。

private async void Button_Click(object sender, RoutedEventArgs 
{
    var currentUser = await graphClient.Me.Request().GetAsync();
    // Presumably do something with the response
    labelUser.Text = currentUser.DisplayName;
}

Few days ago I found a nice video about common async/await mistakes 几天前,我发现了一个关于常见异步/等待错误的精彩视频

You seem to be talking about a console app running on windows. 您似乎在谈论在Windows上运行的控制台应用程序。

As of C# 7.1 you can also have an public static Task Main(string[] args) as starting point. 从C#7.1开始,您还可以使用public static Task Main(string[] args)作为起点。 Then your application would look like this: 然后您的应用程序将如下所示:

public static async Task Main(string[] args) {
  // Create the client here.....
  var graphClient = .....;
  // Await every call to the graphclient
  var currentUser = await graphClient.Me.Request().GetAsync();
  // Do something with the user

}

Maybe the reponse(payload) you get is very huge that while it processes the request times out? 也许你得到的响应(有效载荷)是非常巨大的,而它处理请求超时? I had this issue frequently a while back while I was fiddling with graph api so i used pagination to limit the size/quantity of items sent back by it. 当我摆弄图形api时,我经常有这个问题,所以我使用分页来限制它发回的项目的大小/数量。

I've just experienced this and the cause was a corporate firewall was blocking traffic to graph.microsoft.com:443我刚刚遇到过这种情况,原因是公司防火墙阻止了到 graph.microsoft.com:443 的流量

This can be seen in wireshark as [TCP Retransmission]s after the initial request.这在 wireshark 中可以看作是初始请求后的 [TCP 重传]。

Unblocking this host resolved this issue for me.取消阻止此主机为我解决了这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM