ServerXmlHttpRequest 有时在执行 POST 时挂起 [英] ServerXmlHttpRequest hanging sometimes when doing a POST

查看:45
本文介绍了ServerXmlHttpRequest 有时在执行 POST 时挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一份工作定期做一些涉及

所以我可以分析挂起的位置.在五次崩溃转储后(在过去 11 个月左右),我得到了一致的画面:

ntdll.dll!_NtWaitForMultipleObjects@20()KERNELBASE.dll!_WaitForMultipleObjectsEx@20()user32.dll!MsgWaitForMultipleObjectsEx()user32.dll!_MsgWaitForMultipleObjects@20()urlmon.dll!CTransaction::CompleteOperation(int fNested) 第 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 第 971 行Contoso.exe!FrobImporter.TFrobImporter.ImportCore 第 1583 行Contoso.exe!FrobImporter.TFrobImporter.RunImport 第 1070 行Contoso.exe!CommandLineProcessor.TCommandLineProcessor.HandleFrobImport 第 433 行Contoso.exe!CommandLineProcessor.TCommandLineProcessor.CoreExecute 第 71 行Contoso.exe!CommandLineProcessor.TCommandLineProcessor.Execute 第 84 行Contoso.exe!Contoso.Contoso 第 167 行kernel32.dll!@BaseThreadInitThunk@12()ntdll.dll!__RtlUserThreadStart()ntdll.dll!__RtlUserThreadStart@8()

所以我做了一个 ServerXmlHttpRequest.send,它永远不会返回.它会在那里停留数天(导致系统错过金融交易,直到周日晚上我接到电话说它坏了).

除非有人知道如何调试代码,否则没有帮助,但转储时停顿的线程中的寄存器是:

EAX 00000030EBX 00000000ECX 00000000EDX 00000000ESI 002CAC08EDI 00000001EIP 732A08A7ESP 0018F684EBP 0018F6C8EFL 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 将我的自我进程添加到作业,并使用 SetInformationJobObject 为我的进程设置时间限制:

将我的流程限制为三分钟的执行时间:

<块引用>

PerProcessUserTimeLimit
如果 LimitFlags 指定JOB_OBJECT_LIMIT_PROCESS_TIME,这个成员是每个进程的用户模式执行时间限制,以 100 纳秒为单位.除此以外,该成员被忽略.

系统会定期检查以确定与作业关联的每个进程是否积累了更多用户模式时间超过设置的限制.如果有,过程是终止.

如果作业是嵌套的,则有效限制最大作业链中的限制.

虽然由于 Task Scheduler 也使用 Job 对象来限制任务的时间,但我不希望 Job Object 也可以限制作业.

编辑:作业对象不能通过进程时间限制进程 - 仅限用户时间.并且当一个进程空闲等待一个对象时,它不会累积任何用户时间 - 当然不值得三分钟.

奖励阅读

解决方案

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

msxml3.dll 库不再受支持,仅出于兼容性原因保留.此外,msxml4.dll(以及更新的) 你错过了.

I have a job that periodically does some work involving ServerXmlHttpRquest to perform an HTTP POST. The job runs every 60 seconds.

And normally it runs without issue. But there's about a 1 in 50,000 chance (every two or three months) that it will hang:

IXMLHttpRequest http = new ServerXmlHttpRequest();

http.open("POST", deleteUrl, false, "", "");
http.send(stuffToDelete); <---hang

When it hangs, not even the Task Scheduler (with the option enabled to kill the job if it takes longer than 3 minutes to run) can end the task. I have to connect to the remote customer's network, get on the server, and use Task Manager to kill the process.

And then its good for another month or three.

Eventually i started using Task Manager to create a process dump,

so i could analyze where the hang is. After five crash dumps (over the last 11 months or so) i get a consistent picture:

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()

So i do a ServerXmlHttpRequest.send, and it never returns. It will sit there for days (causing the system to miss financial transactions, until come Sunday night i get a call that it's broken).

It is of no help unless someone knows how to debug code, but the registers in the stalled thread at the time of the dump are:

EAX 00000030
EBX 00000000
ECX 00000000
EDX 00000000
ESI 002CAC08
EDI 00000001
EIP 732A08A7
ESP 0018F684
EBP 0018F6C8
EFL 00000000 

  • Windows Server 2012 R2
  • Microsoft IIS/8.5

Default timeouts of ServerXmlHttpRequest

You can use serverXmlHttpRequest.setTimeouts(...) to configure the four classes of timeouts:

  • resolveTimeout: The value is applied to mapping host names (such as "www.microsoft.com") to IP addresses; the default value is infinite, meaning no timeout.
  • connectTimeout: A long integer. The value is applied to establishing a communication socket with the target server, with a default timeout value of 60 seconds.
  • sendTimeout: The value applies to sending an individual packet of request data (if any) on the communication socket to the target server. A large request sent to a server will normally be broken up into multiple packets; the send timeout applies to sending each packet individually. The default value is 30 seconds.
  • receiveTimeout: The value applies to receiving a packet of response data from the target server. Large responses will be broken up into multiple packets; the receive timeout applies to fetching each packet of data off the socket. The default value is 30 seconds.

The KB305053 (a server that decides to keep the connection open will cause serverXmlHttpRequest to wait for the connection to close) seems like it plausibly could be the issue. But the 30 second default timeout would have taken care of that.

Possible workaround - Add myself to a Job

The Windows Task Scheduler is unable to terminate the task; even though the option is enabled to do do.

I will look into using the Windows Job API to add my self process to a job, and use SetInformationJobObject to set a time limit on my process:

to limit my process to three minutes of execution time:

PerProcessUserTimeLimit
If LimitFlags specifies JOB_OBJECT_LIMIT_PROCESS_TIME, this member is the per-process user-mode execution time limit, in 100-nanosecond ticks. Otherwise, this member is ignored.

The system periodically checks to determine whether each process associated with the job has accumulated more user-mode time than the set limit. If it has, the process is terminated.

If the job is nested, the effective limit is the most restrictive limit in the job chain.

Although since Task Scheduler uses Job objects to also limit a task's time, i'm not hopeful that the Job Object can limit a job either.

Edit: Job objects cannot limit a process by process time - only user time. And with a process idle waiting for an object, it will not accumulate any user time - certainly not three minutes worth.

Bonus Reading

解决方案

Consider switching to a newer, supported API.

The msxml3.dll library is no longer supported and is only kept around for compatibility reasons. Plus, there were a number of security and stability improvements included with msxml4.dll (and newer) that you are missing out on.

这篇关于ServerXmlHttpRequest 有时在执行 POST 时挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆