等待网络可能导致客户端超时
本文关键字:客户端 超时 网络 等待 | 更新日期: 2023-09-27 18:15:44
我有一个服务器正在做Azure队列指示的工作。它几乎总是在非常高的CPU上并行执行多个任务,并且一些任务使用Parallel.ForEach
。在任务运行期间,我通过使用await调用CloudQueue.AddMessageAsync
将分析事件写入另一个Azure队列。
我注意到成千上万的分析性文章都犯了以下错误:
WebException: The remote server returned an error: (500) Internal Server Error.
我检查了Azure的存储事件日志,我有一堆很好的PutMessage
命令,端到端需要80.000ms,但它们只需要1ms用于Azure本身。我得到的HTTP状态码是500,Azure将原因描述为客户端超时。
我认为正在发生的事情是我的代码调用AddMessageAsync
,从那一点我的线程被释放,网络驱动程序正在发送请求并等待响应。当获得响应时,网络驱动程序需要一个线程来获取响应,并安排一个任务来执行该任务并调用我的continuation。因为我的服务器一直处于高负载状态,任务需要很长时间才能获得一个线程,到那时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存储日志中的一行。您可以在这里找到每个属性的详细含义。
<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
谢谢。
错误500表示服务器收到了错误的请求或由于各种其他原因而崩溃。我不认为这与线程的高负载有关。请考虑采取以下措施:
- 检查正在使用的队列的名称。名称必须小写,以一个字符开头。这是一个常见的问题,导致错误500,没有提示错误消息从服务器。
- 设置Azure Storage SDK客户端的重试策略,最好使用指数重试策略。
- 请确保您正在使用最新的Azure存储SDK,因为底层协议最近更改为更高效的协议。
'Bad Request'是一个400错误,而不是500错误。500 Error表示任何类型的服务器错误,因此获得该响应是完全合理的,并且许多客户端库将使用500错误代码来处理类似类型的意外问题。
正常情况下,'client timeout'响应永远不会到达客户端(因为它超时了!)。我能想到的客户端超时响应可能发送到客户端的唯一情况是,如果请求不止一个网络数据包,并且客户端在第一个数据包之后发送数据包太慢。这很容易由客户机设备上的CPU争用引起。我建议使用更高优先级的线程来监听网络响应,然后立即将响应的处理传递给正常优先级的线程。CPU过载将导致各种超时问题,因为代码无法区分网络响应来得不够快和CPU没有及时调度侦听器来接收响应(甚至发送请求)之间的区别。在这些情况下,甚至本地磁盘I/O和锁定也会超时,这取决于底层实现。