[英]Adjusting HttpWebRequest Connection Timeout in C#
我相信经过漫长的研究和搜索,我发现我想做的事情可能更好,通过建立一个异步连接并在所需的超时后终止它...但是我会继续问无论如何!
快速代码片段:
HttpWebRequest webReq = (HttpWebRequest)HttpWebRequest.Create(url);
webReq.Timeout = 5000;
HttpWebResponse response = (HttpWebResponse)webReq.GetResponse();
// this takes ~20+ sec on servers that aren't on the proper port, etc.
我有一个HttpWebRequest
方法,它位于多线程应用程序中,我连接到大量的公司Web服务器。 如果服务器没有响应, HttpWebRequest.GetResponse()
大约需要20秒才能超时,即使我指定的超时时间仅为5秒。 为了定期通过服务器,我想跳过连接时间超过5秒的服务器。
所以问题是: “是否有一种简单的方法来指定/减少WebRequest或HttpWebRequest的连接超时?”
我认为问题在于WebRequest
仅在实际发出请求后才测量时间。 如果您向同一地址提交多个请求,那么ServicePointManager
将限制您的请求,并且实际上只提交与相应ServicePoint.ConnectionLimit
的值一样多的并发连接,默认情况下,它从ServicePointManager.DefaultConnectionLimit
获取值。 应用程序CLR主机将此设置为2,ASP主机设置为10.因此,如果您有一个多线程应用程序向同一主机提交多个请求,则实际上只有两个请求放在线路上,其余的排队等待。
我还没有研究过这个确凿的证据,证明这是真的发生了什么,但是在一个类似的项目中,我发现事情是可怕的,直到我删除了ServicePoint
限制。
另一个要考虑的因素是DNS查找时间。 同样,我相信没有确凿的证据支持,但我认为WebRequest
不计入请求超时的DNS查找时间。 DNS查找时间可能会在某些部署中显示为非常大的时间因素。
是的,您必须围绕WebRequest.BeginGetRequestStream
(对于带内容的POST
)和WebRequest.BeginGetResponse
(对于GET
和 POSTS
)编写应用程序。 同步调用不会扩展(我不会详细说明为什么,但我确实有确凿的证据)。 无论如何, ServicePoint
问题与此正交:排队行为也发生在异步调用上。
很抱歉找到一个旧线程,但我认为上面提到的内容可能不正确/误导。
从我所知道的.Timeout不是连接时间,它是HttpWebRequest和响应的整个生命周期所允许的总时间。 证明:
我设置:
.Timeout=5000
.ReadWriteTimeout=32000
HttpWebRequest的连接和发布时间为26ms
但随后的调用HttpWebRequest.GetResponse()在4974ms超时,从而证明5000ms是整个发送请求/获取响应调用集的时间限制。
我没有验证DNS名称解析是否作为时间的一部分被测量,因为这与我无关,因为这一切都不是我真正需要它工作的方式 - 我的意图是在连接到系统时更快地超时如果在请求的连接阶段失败,则不接受连接。
例如:我愿意在有可能返回结果的连接请求上等待30秒,但我只想等待10秒钟等待向一个行为不端的主机发送请求。
我后来发现有帮助的东西是.ReadWriteTimeout
属性。 除了.Timeout
属性之外,这似乎最终减少了线程花在尝试从有问题的服务器上下载的时间。 .ReadWriteTimeout
的默认时间是5分钟,对于我的应用程序来说太长了。
所以,在我看来:
.Timeout
=尝试建立连接所花费的时间(不包括查找时间) .ReadWriteTimeout
=建立连接后尝试读取或写入数据所花费的时间
更多信息: HttpWebRequest.ReadWriteTimeout属性
编辑:
根据Per @ KyleM的评论, Timeout
属性用于整个连接尝试,并在MSDN上阅读它显示:
Timeout是使用GetResponse方法进行的后续同步请求等待响应的毫秒数,GetRequestStream方法等待流。 Timeout适用于整个请求和响应,而不是单独应用于GetRequestStream和GetResponse方法调用。 如果在超时期限内未返回资源,则该请求将抛出WebException,并将Status属性设置为WebExceptionStatus.Timeout。
(强调我的。)
从HttpWebRequest.Timeout属性的文档:
域名系统(DNS)查询最多可能需要15秒才能返回或超时。 如果您的请求包含需要解析的主机名,并且您将Timeout设置为小于15秒的值,则可能需要15秒或更长时间才能引发WebException以指示请求超时。
您的DNS查询是否可能是超时的原因?
无论我们尝试什么,当我们检查的服务器关闭时,我们无法设置超过21秒的超时。
为了解决这个问题,我们结合了一个TcpClient检查来查看域是否还活着,然后单独检查以确定URL是否处于活动状态
public static bool IsUrlAlive(string aUrl, int aTimeoutSeconds)
{
try
{
//check the domain first
if (IsDomainAlive(new Uri(aUrl).Host, aTimeoutSeconds))
{
//only now check the url itself
var request = System.Net.WebRequest.Create(aUrl);
request.Method = "HEAD";
request.Timeout = aTimeoutSeconds * 1000;
var response = (HttpWebResponse)request.GetResponse();
return response.StatusCode == HttpStatusCode.OK;
}
}
catch
{
}
return false;
}
private static bool IsDomainAlive(string aDomain, int aTimeoutSeconds)
{
try
{
using (TcpClient client = new TcpClient())
{
var result = client.BeginConnect(aDomain, 80, null, null);
var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(aTimeoutSeconds));
if (!success)
{
return false;
}
// we have connected
client.EndConnect(result);
return true;
}
}
catch
{
}
return false;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.