ServerXmlHttpRequest 在执行 POST 时有时会挂起
ServerXmlHttpRequest hanging sometimes when doing a POST
我有一份工作,定期做一些涉及 ServerXmlHttpRquest
的工作来执行 HTTP POST
。作业 运行s 每 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
,但它从来没有 returns。它会在那里放置几天(导致系统错过金融交易,直到周日晚上我接到电话说它坏了)。
除非有人知道如何调试代码,否则它没有任何帮助,但转储时停滞线程中的寄存器是:
EAX 00000030
EBX 00000000
ECX 00000000
EDX 00000000
ESI 002CAC08
EDI 00000001
EIP 732A08A7
ESP 0018F684
EBP 0018F6C8
EFL 00000000
- Windows 服务器 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
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.
虽然因为 Task Scheduler 使用 Job 对象来限制任务的时间,我也不希望 Job 对象也能限制任务。
编辑:作业对象不能按进程时间限制进程 - 仅限 用户 时间。并且当一个进程空闲等待一个对象时,它不会累积任何用户时间——当然不值得三分钟。
红利阅读
- (
GET
, 不是 POST
)
- KB305053: ServerXMLHTTP Stops Responding When You Send a POST Request (表示超时应该到期;我的没有)
- MS Forums: oHttp.Send - Hangs (
HEAD
, 不是 POST
)
- MS Forums: ASP to test SOAP WebService using MSXML2.ServerXMLHTTP Send hangs
- CC to MS Support Forums
考虑切换到更新的、受支持的 API。
- msxml6.dll 使用
MSXML2.ServerXMLHTTP.6.0
- winhttpcom.dll 使用
WinHttp.WinHttpRequest.5.1
.
您错过的 msxml4.dll(和更新版本)中包含的 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。
我有一份工作,定期做一些涉及 ServerXmlHttpRquest
的工作来执行 HTTP POST
。作业 运行s 每 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
,但它从来没有 returns。它会在那里放置几天(导致系统错过金融交易,直到周日晚上我接到电话说它坏了)。
除非有人知道如何调试代码,否则它没有任何帮助,但转储时停滞线程中的寄存器是:
EAX 00000030
EBX 00000000
ECX 00000000
EDX 00000000
ESI 002CAC08
EDI 00000001
EIP 732A08A7
ESP 0018F684
EBP 0018F6C8
EFL 00000000
- Windows 服务器 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
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.
虽然因为 Task Scheduler 使用 Job 对象来限制任务的时间,我也不希望 Job 对象也能限制任务。
编辑:作业对象不能按进程时间限制进程 - 仅限 用户 时间。并且当一个进程空闲等待一个对象时,它不会累积任何用户时间——当然不值得三分钟。
红利阅读
- (
GET
, 不是POST
) - KB305053: ServerXMLHTTP Stops Responding When You Send a POST Request (表示超时应该到期;我的没有)
- MS Forums: oHttp.Send - Hangs (
HEAD
, 不是POST
) - MS Forums: ASP to test SOAP WebService using MSXML2.ServerXMLHTTP Send hangs
- CC to MS Support Forums
考虑切换到更新的、受支持的 API。
- msxml6.dll 使用
MSXML2.ServerXMLHTTP.6.0
- winhttpcom.dll 使用
WinHttp.WinHttpRequest.5.1
.
您错过的 msxml4.dll(和更新版本)中包含的 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。