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

Posted

技术标签:

【中文标题】等待网络会导致客户端超时吗?【英文标题】:Could awaiting network cause client timeouts? 【发布时间】:2014-09-23 08:07:17 【问题描述】:

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

我注意到数以千计的这些分析著作都因以下错误而失败:

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

我检查了 Azure 的存储事件日志,我有很多 PutMessage 命令,端到端需要 80.000 毫秒,但 Azure 本身只需要 1 毫秒。我得到的 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

谢谢。

【问题讨论】:

好吧,也许......你为什么不去试试呢? @CarstenKönig 我可能会,但我对这些网络驱动程序-线程关系如何工作缺乏很多了解。所以我想知道我认为问题可能是一种可能的情况,或者它可能不是那样工作的。 您关于网络驱动程序的理论很可能不正确。将代码发布到您收到此错误的位置。发布完整的例外。 “500 server error”表示服务器崩溃而不是客户端。 @usr 我添加了代码和异常。我知道 500 表示服务器崩溃,但 Azure 存储日志说返回的代码是 500,原因是客户端超时。因此,我假设如果我的客户端没有足够快地拦截响应,Azure 会返回此错误(尽管此代码似乎不太合适)。 Azure 无法确定您的客户端是否快速接受了响应。它无法分辨,因此无法生成该错误。 Azure 日志到底在说什么?发布您可以掌握的所有详细信息。此外,发布存储在该 StorageException 中的 RequestResult。调试的第一步是查看all错误信息。 【参考方案1】:

错误 500 表示服务器收到了错误的请求或由于各种其他原因而崩溃。我不认为这与线程的高负载有关。请考虑采取以下措施:

检查您正在使用的队列的名称。名称必须小写,以字符开头。这是一个常见的问题,会导致错误 500,而服务器没有任何启发性的错误消息。 设置 Azure 存储 SDK 客户端的重试策略,最好使用指数重试策略。 确保您使用的是最新的 Azure 存储 SDK,因为底层协议最近已更改为更高效的协议。

【讨论】:

【参考方案2】:

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

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

【讨论】:

以上是关于等待网络会导致客户端超时吗?的主要内容,如果未能解决你的问题,请参考以下文章

发送消息超时,咋办

OPC-UA 服务器可以覆盖连接客户端的超时和其他参数吗?

接口调用过于频繁会引发超时错误吗

tcp连接状态有大量的timewait 状态,导致连接等待至超时,怎么解决

Nginx并发请求过高导致请求超时的问题

使用 IErrorHandler 和 TCP Message Security 会导致超时