在C#中调整HttpWebRequest连接超时
我相信经过长时间的研究和search,我发现我想要做的事情可能会更好地通过build立一个asynchronous连接,并在所需的超时后终止它。但是,我会继续问,无论如何!
快速代码片段:
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
方法是在一个multithreading应用程序,我连接到大量的公司Web服务器。 在服务器没有响应的情况下, HttpWebRequest.GetResponse()
大约需要20秒钟超时,即使我指定了仅5秒的超时时间。 为了定期通过服务器,我想跳过那些连接超过5秒的连接。
所以问题是: “是否有一个简单的方法来指定/减lessWebRequest或HttpWebRequest的连接超时?
我相信问题是WebRequest
只有在请求被实际执行之后才会测量时间。 如果你提交多个请求到同一个地址,那么ServicePointManager
将会限制你的请求,并且实际上只提交与默认值ServicePointManager.DefaultConnectionLimit
相对应的ServicePoint.ConnectionLimit
的值。 应用程序CLR主机将其设置为2,将ASP主机设置为10.因此,如果您有一个multithreading应用程序向同一主机提交多个请求,则只有两个实际上被放置在线路上,其余的则排队等候。
我没有把这个研究结果作为一个确凿的证据来certificate这是否真的发生了,但是在一个类似的项目中,直到我删除了ServicePoint
限制之前,事情是非常糟糕的。
另一个要考虑的因素是DNS查找时间。 再一次,我的信念没有得到有力证据的支持,但是我认为WebRequest
不会计算DNS请求超时的DNS查询时间。 DNS查找时间在某些部署中可能会显示为非常大的时间因素。
是的,你必须围绕WebRequest.BeginGetRequestStream
(对于具有内容的POST
)和WebRequest.BeginGetResponse
(对于GET
和 POSTS
)编码你的应用程序。 同步呼叫不会扩展(我不会详细说明为什么,但是我确实有很好的证据)。 无论如何, ServicePoint
问题与此是正交的:排队行为也发生在asynchronous调用中。
对不起,对一个古老的线程,但我认为上面说的东西可能是不正确的/误导。
从我可以告诉.Timeout不是连接时间,它是HttpWebRequest和响应的整个生命所允许的总时间。 certificate:
我设置:
.Timeout=5000 .ReadWriteTimeout=32000
HttpWebRequest的连接和发布时间花了26ms
但随后的调用HttpWebRequest.GetResponse()超时4974毫秒,从而certificate5000毫秒是整个发送请求/获取响应设置的调用的时间限制。
我没有validationDNS名称parsing是否作为时间的一部分来衡量,因为这与我无关,因为这些工作都不是我真正需要它工作的方式 – 我的意图是在连接到系统时超时没有接受连接,如在请求的连接阶段失败所示。
例如:我愿意等待30秒的连接请求,有机会返回一个结果,但我只想烧10秒,等待发送一个请求,一个不正常的主机。
我后来发现的帮助,是.ReadWriteTimeout
属性。 除了.Timeout
属性之外,这似乎最终会减less线程花费在从有问题的服务器上下载的时间。 .ReadWriteTimeout
的默认时间是5分钟,这对我的应用程序来说太长了。
所以,在我看来:
.Timeout
=尝试build立连接所用的时间(不包括查找时间) .ReadWriteTimeout
=连接build立后尝试读取或写入数据所花费的时间
更多信息: HttpWebRequest.ReadWriteTimeout属性
编辑:
Per @ KyleM的评论是, Timeout
属性用于整个连接尝试,并且在MSDN上读取它显示:
Timeout是用GetResponse方法进行的后续同步请求等待响应的毫秒数,GetRequestStream方法等待stream。 超时适用于整个请求和响应,而不是单独的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; }