如何让 HttpWebRequest.GetResponse() 超时更慢?
How do I get HttpWebRequest.GetResponse() to time out more slowly?
我正在处理一个搅拌服务器,当我发出 POST 请求时,它需要很长时间才能发送响应。我不能使用 .NET 4.5,所以我一直在使用 HttpWebRequest
,最近还使用 WebClient
。服务器通过 POST 接受一些数据,需要很长时间(通常是 5-7 分钟)来处理它,然后生成一个响应来指示结果。
我所看到的表明 .NET 中的某些东西在 WebRequest.GetResponse()
上有大约 2 分钟的超时,而我所做的任何事情似乎都没有影响到这一点:
- 第一个版本的代码是完全同步的。我将
HttpWebRequest
的 Timeout
和 ReadWriteTimeout
设置为 10m,但 2 分钟后抛出了状态为 "ReceiveFailure" 的 WebException。
- 我测试了一个使用
BeginGetResponse()
的版本,但是 运行 出现了类似的失败。我还注意到我不应该在同一个请求上使用同步 GetRequestStream()
,所以它代表了一些相当大的变化,因为我最终希望这个 API 看起来是同步的。
- 我尝试使用
WebClient.UploadStringAsync()
,但它有类似的问题。就在 2 分钟时,它抛出一个 WebException(尽管这次是 ConnectionClosed)。
我试过 ServicePointManager.MaxServicePointIdleTime
之类的属性,但没有任何改变。我试过使用 HttpWebRequest.KeepAlive
。我已经阅读了几个关于 SO 的类似问题,但 none 似乎提出了适合我的情况的任何建议。感觉好像有一些我无法控制的超时,但也感觉应该有一种配置它的方法。我错过了什么?这是我的代码的同步版本的粗略示例,这里没有什么特别之处:
var request = (HttpWebRequest)WebRequest.Create(clientUrl);
request.ContentType = "application/json";
request.ReadWriteTimeout = DefaultTimeoutMilliseconds; // 600,000
request.Timeout = DefaultTimeoutMilliseconds;
request.Method = method; // "POST"
using (var writer = new StreamWriter(requestStream)) {
writer.Write(body);
}
var response = (HttpWebResponse)request.GetResponse();
// The exception happens on the line above, the code below does not execute.
string responseBody = null;
using (var responseStream = response.GetResponseStream())
using (var reader = new StreamReader(responseStream)) {
responseBody = reader.ReadToEnd();
}
response.Close();
return responseBody;
更新
一些谜团解开了,因为我没有意识到 Node 在 2 分钟时有一个套接字超时。现在,当我将其设置为 15m 时,指向我的节点服务器的 Windows 实例很乐意等待很长时间。但是生产环境是运行 on Linux via Mono。我正在重新测试一些我之前没有尝试过的东西,因为它们是针对错误节点超时的误报。
原来答案有点粗糙。
服务器正在发送 303 响应以表明它仍在处理中。位置 header 指示另一个 URL 将 return 另一个 303 或结果。选择此选项是因为大多数 HTTP 客户端会自动遵循重定向。
在 MS CLR 上,这工作正常。出于某种原因,在我使用的 Mono CLR 的特定版本中,HttpWebRequest
class 在获取重定向时重新发送 Content-Length header。这混淆了 Mono 内部的其他东西或服务器等待不会发送的数据,并且在 1m 后连接中断。
我通过将 HttpWebRequest 的 AllowAutoRedirect
属性 设置为 false 并手动处理 3xx 响应来解决它。看起来 Mono 的更高版本可能已经解决了这个问题,但我不想推动服务器管理员升级。
我正在处理一个搅拌服务器,当我发出 POST 请求时,它需要很长时间才能发送响应。我不能使用 .NET 4.5,所以我一直在使用 HttpWebRequest
,最近还使用 WebClient
。服务器通过 POST 接受一些数据,需要很长时间(通常是 5-7 分钟)来处理它,然后生成一个响应来指示结果。
我所看到的表明 .NET 中的某些东西在 WebRequest.GetResponse()
上有大约 2 分钟的超时,而我所做的任何事情似乎都没有影响到这一点:
- 第一个版本的代码是完全同步的。我将
HttpWebRequest
的Timeout
和ReadWriteTimeout
设置为 10m,但 2 分钟后抛出了状态为 "ReceiveFailure" 的 WebException。 - 我测试了一个使用
BeginGetResponse()
的版本,但是 运行 出现了类似的失败。我还注意到我不应该在同一个请求上使用同步GetRequestStream()
,所以它代表了一些相当大的变化,因为我最终希望这个 API 看起来是同步的。 - 我尝试使用
WebClient.UploadStringAsync()
,但它有类似的问题。就在 2 分钟时,它抛出一个 WebException(尽管这次是 ConnectionClosed)。
我试过 ServicePointManager.MaxServicePointIdleTime
之类的属性,但没有任何改变。我试过使用 HttpWebRequest.KeepAlive
。我已经阅读了几个关于 SO 的类似问题,但 none 似乎提出了适合我的情况的任何建议。感觉好像有一些我无法控制的超时,但也感觉应该有一种配置它的方法。我错过了什么?这是我的代码的同步版本的粗略示例,这里没有什么特别之处:
var request = (HttpWebRequest)WebRequest.Create(clientUrl);
request.ContentType = "application/json";
request.ReadWriteTimeout = DefaultTimeoutMilliseconds; // 600,000
request.Timeout = DefaultTimeoutMilliseconds;
request.Method = method; // "POST"
using (var writer = new StreamWriter(requestStream)) {
writer.Write(body);
}
var response = (HttpWebResponse)request.GetResponse();
// The exception happens on the line above, the code below does not execute.
string responseBody = null;
using (var responseStream = response.GetResponseStream())
using (var reader = new StreamReader(responseStream)) {
responseBody = reader.ReadToEnd();
}
response.Close();
return responseBody;
更新 一些谜团解开了,因为我没有意识到 Node 在 2 分钟时有一个套接字超时。现在,当我将其设置为 15m 时,指向我的节点服务器的 Windows 实例很乐意等待很长时间。但是生产环境是运行 on Linux via Mono。我正在重新测试一些我之前没有尝试过的东西,因为它们是针对错误节点超时的误报。
原来答案有点粗糙。
服务器正在发送 303 响应以表明它仍在处理中。位置 header 指示另一个 URL 将 return 另一个 303 或结果。选择此选项是因为大多数 HTTP 客户端会自动遵循重定向。
在 MS CLR 上,这工作正常。出于某种原因,在我使用的 Mono CLR 的特定版本中,HttpWebRequest
class 在获取重定向时重新发送 Content-Length header。这混淆了 Mono 内部的其他东西或服务器等待不会发送的数据,并且在 1m 后连接中断。
我通过将 HttpWebRequest 的 AllowAutoRedirect
属性 设置为 false 并手动处理 3xx 响应来解决它。看起来 Mono 的更高版本可能已经解决了这个问题,但我不想推动服务器管理员升级。