【问题标题】:ServerXmlHttpRequest hanging sometimes when doing a POSTServerXmlHttpRequest 在进行 POST 时有时会挂起
【发布时间】: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


    【解决方案1】:

    考虑切换到更新的、受支持的 API。

    msxml3.dll 库不再受支持,仅出于兼容性原因保留。此外,msxml4.dll(和更新版本)中包含许多 security and stability improvements,您错过了。

    【讨论】:

    • 我正在使用Msxml2.ServerXMLHTTP.6.0 ({88D96A0B-F192-11D4-A65F-0040963251E5})。
    • @IanBoyd 您列出的堆栈跟踪显示 msxml3.dll。它还向您展示了使用 MSXML2.XMLHTTP(使用 WinINet)而不是 MSXML2.ServerXMLHTTP(使用 WinHttp)。它通过显示 urlmon.dll 来证实这一点,它是 WinINet 的一个组件。生成堆栈跟踪后您是否更改了代码?
    • 客户端完全有可能运行的是旧版本的应用程序。随着我最近提供的更新(为 dns 解析指定非无限超时),如果它再也不会发生,我们将永远不知道是超时还是 msxml3 中的错误。
    • 我在五月份给了他们一个更新版本。它肯定使用了 msxml6,并且使用了 resolve 超时。已经两个月没有电话了。也许 msxml6 修复了它。也许解决超时修复了它。
    猜你喜欢
    • 2014-03-09
    • 2013-01-25
    • 1970-01-01
    • 1970-01-01
    • 2017-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多