【发布时间】:2016-05-04 15:27:54
【问题描述】:
我的工作是定期做一些涉及ServerXmlHttpRquest 的工作以执行 HTTP POST。该作业每 60 秒运行一次。
通常它运行没有问题。但是大约有五万分之一的机会(每两三个月)会挂起:
IXMLHttpRequest http = new ServerXmlHttpRequest();
http.open("POST", deleteUrl, false, "", "");
http.send(stuffToDelete); <---hang
当它挂起时,即使是任务计划程序(如果运行时间超过 3 分钟,则启用了终止作业的选项)也无法结束任务。我必须连接到远程客户的网络,进入服务器,然后使用任务管理器来终止该进程。
然后再过一三个月就好了。
最后我开始使用任务管理器来创建进程转储,
所以我可以分析挂在哪里。在五次崩溃转储(过去 11 个月左右)之后,我得到了一致的图片:
ntdll.dll!_NtWaitForMultipleObjects@20()
KERNELBASE.dll!_WaitForMultipleObjectsEx@20()
user32.dll!MsgWaitForMultipleObjectsEx()
user32.dll!_MsgWaitForMultipleObjects@20()
urlmon.dll!CTransaction::CompleteOperation(int fNested) Line 2496
urlmon.dll!CTransaction::StartEx(IUri * pIUri, IInternetProtocolSink * pOInetProtSink, IInternetBindInfo * pOInetBindInfo, unsigned long grfOptions, unsigned long dwReserved) Line 4453 C++
urlmon.dll!CTransaction::Start(const wchar_t * pwzURL, IInternetProtocolSink * pOInetProtSink, IInternetBindInfo * pOInetBindInfo, unsigned long grfOptions, unsigned long dwReserved) Line 4515 C++
msxml3.dll!URLMONRequest::send()
msxml3.dll!XMLHttp::send()
Contoso.exe!FrobImporter.TFrobImporter.DeleteFrobs Line 971
Contoso.exe!FrobImporter.TFrobImporter.ImportCore Line 1583
Contoso.exe!FrobImporter.TFrobImporter.RunImport Line 1070
Contoso.exe!CommandLineProcessor.TCommandLineProcessor.HandleFrobImport Line 433
Contoso.exe!CommandLineProcessor.TCommandLineProcessor.CoreExecute Line 71
Contoso.exe!CommandLineProcessor.TCommandLineProcessor.Execute Line 84
Contoso.exe!Contoso.Contoso Line 167
kernel32.dll!@BaseThreadInitThunk@12()
ntdll.dll!__RtlUserThreadStart()
ntdll.dll!__RtlUserThreadStart@8()
所以我做了一个ServerXmlHttpRequest.send,它永远不会返回。它会在那里呆几天(导致系统错过金融交易,直到周日晚上我接到电话说它坏了)。
除非有人知道如何调试代码,否则无济于事,但转储时停滞线程中的寄存器是:
EAX 00000030
EBX 00000000
ECX 00000000
EDX 00000000
ESI 002CAC08
EDI 00000001
EIP 732A08A7
ESP 0018F684
EBP 0018F6C8
EFL 00000000
- Windows Server 2012 R2
- 微软 IIS/8.5
ServerXmlHttpRequest 的默认超时时间
您可以使用serverXmlHttpRequest.setTimeouts(...)来配置四类超时:
- resolveTimeout:该值用于将主机名(例如“www.microsoft.com”)映射到 IP 地址;默认值为infinite,表示没有超时。
- connectTimeout:长整数。该值用于与目标服务器建立通信套接字,默认超时值为 60 秒。
- sendTimeout:该值适用于将通信套接字上的单个请求数据包(如果有)发送到目标服务器。发送到服务器的大请求通常会被分解为多个数据包;发送超时适用于单独发送每个数据包。默认值为 30 秒。
- receiveTimeout:该值适用于从目标服务器接收响应数据包。大响应将被分解成多个数据包;接收超时适用于从套接字中获取每个数据包。默认值为 30 秒。
KB305053(决定保持连接打开的服务器将导致 serverXmlHttpRequest 等待连接关闭)似乎可能是问题所在。但是 30 秒的默认超时会解决这个问题。
可能的解决方法 - 将自己添加到工作中
Windows 任务计划程序无法终止任务;即使启用了该选项来做。
我将研究使用 Windows 作业 API 将我的 self 进程添加到作业中,并使用 SetInformationJobObject 为我的进程设置时间限制:
将我的进程限制为三分钟的执行时间:
PerProcessUserTimeLimit
如果 LimitFlags 指定 JOB_OBJECT_LIMIT_PROCESS_TIME,这个成员是per-process 用户模式执行时间限制,以 100 纳秒滴答为单位。除此以外, 该成员被忽略。系统会定期检查以确定 与作业相关的每个进程是否积累了更多 用户模式时间超过设置限制。如果有,流程是 终止。
如果作业是嵌套的,则有效限制是最大的 工作链中的限制性限制。
虽然由于任务调度器使用 Job 对象来限制任务的时间,但我不希望 Job 对象也可以限制作业。
编辑:作业对象不能通过进程时间来限制进程 - 只有用户时间。并且由于一个进程空闲等待一个对象,它不会累积任何用户时间——当然不值得三分钟。
阅读奖励
【问题讨论】:
标签: xmlhttprequest msxml serverxmlhttp