等待网络会导致客户端超时吗?

时间:2014-07-31 11:35:04

标签: c# parallel-processing async-await

我有一个服务器正在执行Azure队列指示的工作。它几乎总是在非常高的CPU上并行执行多个任务,而某些任务使用Parallel.ForEach。 在运行任务期间,我通过等待调用CloudQueue.AddMessageAsync将分析事件写入另一个Azure队列。

我注意到成千上万的这些分析文章因以下错误而失败:

WebException: The remote server returned an error: (500) Internal Server Error.

我检查了Azure的存储事件日志,我有一堆很好的PutMessage命令,端到端占用80.000ms,但Azure本身只需要1ms。我得到的HTTP状态代码是500,Azure描述了客户端超时的原因。

我认为发生的是我的代码调用AddMessageAsync,从那时起我的线程被释放,网络驱动程序正在发送请求并等待响应。获得响应时,网络驱动程序需要一个线程来获取响应,并且计划执行该任务并调用我的继续。由于我的服务器经常处于高负载状态,因此任务需要很长时间才能获得一个线程,然后Azure服务器会认为这是客户端超时。

调用azure的代码:

await cloudQueue.AddMessageAsync(new CloudQueueMessage(aMessageContent));

例外:

StorageException: The remote server returned an error: (500) Internal Server Error.
Microsoft.WindowsAzure.Storage.Core.Executor.Executor.EndExecuteAsync[T](IAsyncResult result):11
Microsoft.WindowsAzure.Storage.Core.Util.AsyncExtensions+<>c__DisplayClass4.<CreateCallbackVoid>b__3(IAsyncResult ar):45
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task):82
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task):41
AzureCommon.Data.AsyncQueueDataContext+<AddMessage>d__d.MoveNext() in c:\BuildAgent\work\14078ab89161833\Azure\AzureCommon\Data\Async\AsyncQueueDataContext.cs:60
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task):82
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task):41
AzureCommon.Storage.AzureEvent+<DispatchAsync>d__1.MoveNext() in c:\BuildAgent\work\14078ab89161833\Azure\AzureCommon\Events\AzureEvent.cs:354

WebException: The remote server returned an error: (500) Internal Server Error.
System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult):41
Microsoft.WindowsAzure.Storage.Core.Executor.Executor.EndGetResponse[T](IAsyncResult getResponseResult):44

我说的为什么会这样?如果是这样,那么使用单线程同步上下文对我来说会更好吗?

Azure存储日志中的一行。您可以找到有关每个属性的含义的详细信息here

<request-start-time>            <operation-type>     <request-status>     <http-status-code>    <end-to-end-latency-in-ms>      <server-latency-in-ms>
2014-07-29T14:55:20.0794198Z    PutMessage           ClientTimeoutError   500                   86929                           1

感谢。

2 个答案:

答案 0 :(得分:0)

错误500表示服务器收到错误请求或因各种其他原因而崩溃。我不相信它与你的线程的高负载有关。请考虑采取以下行动:

  • 检查您正在使用的队列的名称。名称必须小写,从字符开始。这是一个常见问题,导致错误500而服务器没有启动错误消息。
  • 设置Azure Storage SDK客户端的重试策略,最好使用指数重试策略。
  • 确保您使用的是最新的Azure Storage SDK,因为最近基础协议已更改为更高效的协议。

答案 1 :(得分:0)

'Bad Request' is a 400 error, not a 500 error。 500错误表示任何类型的服务器错误,因此获得该响应是完全合理的,并且许多客户端库将使用500错误代码来解决类似类型的意外问题。

通常,“客户端超时”响应永远不会进入客户端(因为它超时了!)。我可以想到的唯一情况是客户端超时响应可以进入客户端,如果请求不仅仅是一个网络数据包而且客户端在第一个数据包之后发送数据包太慢。这可能很容易由客户端设备上的CPU争用引起。我建议使用更高优先级的线程来监听网络响应,但然后立即将响应处理传递给普通优先级线程。 CPU过载会导致各种超时问题,因为代码无法区分网络响应不能很快进入,CPU无法及时调度监听器以接收响应(甚至发送请求)。在这些情况下,即使本地磁盘I / O和锁定也会超时,具体取决于底层实现。