HttpWebRequest非常慢!


74

我正在使用开源库连接到我的Web服务器。我担心Web服务器的运行速度非常慢,然后我尝试在Ruby中进行简单测试,得到了这些结果

Ruby程序:10个HTTP GET的2.11秒

Ruby程序:100个HTTP GET的18.13秒

C#库:10个HTTP GET的20.81秒

C#库:用于100个HTTP GET的36847.46秒

我已经剖析并发现问题在于此功能:

private HttpWebResponse GetRawResponse(HttpWebRequest request) {
  HttpWebResponse raw = null;
  try {
    raw = (HttpWebResponse)request.GetResponse(); //This line!
  }
  catch (WebException ex) {
    if (ex.Response is HttpWebResponse) {
      raw = ex.Response as HttpWebResponse;
    }
  }
  return raw;
}

标记行本身需要1秒钟才能完成,而发出1个请求的红宝石程序则需要0.3秒。我也在127.0.0.1上进行了所有这些测试,因此网络带宽不是问题。

是什么原因导致这种巨大的放缓?

更新

检查更改后的基准结果。我实际上测试了10个GET,而不是100个,我更新了结果。


出于好奇,您是否对所有GET使用相同的HttpWebRequest对象?我认为减速只是最初的握手。尝试重用相同的HttpWebRequest对象。
BFree

进行个人资料配置时,您是否排除第一个电话?有时我注意到FireWall(或其他功能)可以将第一通电话的速度减慢几秒钟。(Alt:处理100多个请求,比率保持不变吗?)
Henk Holterman 2010年

我相信它会在每个调用上创建一个新的请求对象。尽管必须对HTTP执行哪种“握手”?它的协议相当简单
Earlz 2010年

1
@Henk,我刚刚尝试执行500个请求,并在5分钟后放弃了
Earlz 2010年

Answers:


175

我发现导致Web请求缓慢的主要原因是proxy属性。如果在调用GetResponse方法之前将此属性设置为null,则查询将跳过代理自动检测步骤:

request.Proxy = null;
using (var response = (HttpWebResponse)request.GetResponse())
{
}

在返回响应之前,代理自动检测最多需要7秒钟来查询。HttpWebRequest对象的默认设置为此属性有点令人讨厌。


2
詹姆斯,你摇滚。我最终会通过Wireshark找到了这一点,但是在阅读本文后几秒钟,我们的WebDAV性能提高了一百倍。我怀疑我们的Sharpoint服务器存在相同的问题
Paul Lockwood

1
我遇到了同样的问题(响应时间或多或少需要1秒钟),但设置WebRequest.DefaultWebProxy = null不能解决我的问题。还有其他想法吗?
Cristiano Ghersi

抱歉,增加线程数量,但是如果您尝试访问的地址仅通过默认代理可用,会发生什么情况?
Florian F.

3
我怀疑这里的关键是将GetResponse调用包装到using指令中,因为连接数量受到限制,如果未正确关闭它们,则必须等待它们超时。
Nicolas78

1
这对我有用,非常感谢。仅使用HTTPWebRequest的GetResponse方法需要5分钟以上的时间才能做出响应。默认情况下,它尝试获取系统代理并超时。手动调用GetSystemWebProxy在我的计算机上也有同样的问题。但是将proxy设置为null可以使其再次快速运行。
bobasaurus

21

您可能同时打开多个连接这一事实可能与之有关。默认情况下,“打开的HTTP连接的最大数量”设置为2。尝试将其添加到您的.config文件中,看看是否有帮助:

<system.net>
  .......
  <connectionManagement>
    <add address="*" maxconnection="20"/>
  </connectionManagement>
</system.net>

这是我的作品。我的情况是这样的:stackoverflow.com/questions/24154101/...
smwikipedia

10

我在VB.Net MVC项目中遇到了类似的问题。
在我的PC(Windows 7)上,本地请求不到1秒即可达到页面请求,但是在服务器(Windows Server 2008 R2)上,每个页面请求都需要20秒钟以上的时间。

我尝试了将代理设置为null的组合

  System.Net.WebRequest.DefaultWebProxy = Nothing
  request.Proxy = System.Net.WebRequest.DefaultWebProxy

并通过添加更改配置文件

 <system.net>
   .......
   <connectionManagement>
     <add address="*" maxconnection="20"/>
   </connectionManagement>
 </system.net>

这仍然没有减少服务器上的慢速页面请求时间。最后,解决方案是取消选中服务器本身IE选项中的“自动检测设置”选项。(在“工具”->“ Internet选项”下,选择“连接”选项卡。按“ LAN设置”按钮)

在我取消选中服务器上的此浏览器选项后,所有页面请求时间都立即从20多秒降至不到1秒。


8

我开始观察到与OP相似的减速,在增加MaxConnections时会有所改善。

ServicePointManager.DefaultConnectionLimit = 4;

但是在建立了如此数量的WebRequests之后,延迟又回来了。

就我而言,问题是我正在打电话给POST,而没有为响应打扰,因此没有接电话或对其进行任何处理。不幸的是,这使WebRequest浮动直到超时。

解决的办法是拿起响应并关闭它。

WebRequest webRequest = WebRequest.Create(sURL);
webRequest.Method = "POST";
webRequest.ContentLength = byteDataGZ.Length;
webRequest.Proxy = null;
using (var requestStream = webRequest.GetRequestStream())
{
    requestStream.WriteTimeout = 500;
    requestStream.Write(byteDataGZ, 0, byteDataGZ.Length);
    requestStream.Close();
}
// Get the response so that we don't leave this request hanging around
WebResponse response = webRequest.GetResponse();
response.Close();

有趣。我没有想到这一点,因为通常您也想从响应中收集一些信息。我很确定这不是我的实际问题,但是仍然

这并不能解决我的问题,但是导致我查看了对我的使用情况HttpWebResponse,发现其中一个我没有关闭。
Craig Silver

3

使用localhost以外的其他计算机,然后使用WireShark查看网络上的实际情况。

就像其他人所说的,可能有很多事情。在TCP级别上看情况应该可以清楚地看到。


3

我不知道该解决方案的精确程度,我还没有时间做一些研究,所以这取决于你们。有一个参数,我像这样使用它(在实例化HTTPWebRequest对象之前,在我的类的构造函数中):

System.Net.ServicePointManager.Expect100Continue = false;

我不知道为什么会这样,但是现在我的通话看起来更快。


如果您进行POST / PUT(请参阅文档),确实会有所帮助。
Styxxy

如果服务器有可能拒绝PUT / POST数据,它也会使速度变慢(即,如果禁用此功能,则在PUT / POST数据之后才知道呼叫被拒绝)。
BrainSlugs83 2014年

1

我知道这是一个旧的线程,但是我由于慢速的HttpWebRequest而失去了整整一天,尝试了所有提供的解决方案,但没有运气。每个地址的请求都超过一分钟。

最终,我的防病毒防火墙(Eset)出现了问题。我在交互模式下使用防火墙,但是Eset完全关闭了。这导致请求永远持续下去。后接通ESET,并执行请求,示出提示防火墙消息,并且确认之后,请求对于小于一秒执行


感谢您的提示。我完全忘记了Windows防火墙,事实证明,如果配置不正确,第一个请求就会生效。Esp。在Win对话框中将其“关闭”时,该服务仍在运行。
Xan-Kun Clark-Davis

0

我没有运气就尝试了这里描述的所有解决方案,通话大约花了5分钟。

问题是什么:我需要相同的会话和显然相同的cookie(在同一服务器上进行的请求),因此我将Request.Cookies中的cookie重新创建为WebRequest.CookieContainer。响应时间约为5分钟。

我的解决方案: 注释掉与cookie相关的代码和bam!通话时间不到一秒钟。


0

对我来说,问题是我安装了LogMeIn Hamachi,具有讽刺意味的是,它可以远程调试同一程序,然后开始表现出这种极慢的速度。

仅供参考,仅禁用Hamachi网络适配器是不够的,因为它的Windows服务似乎重新启用了适配器。

另外,重新连接到我的Hamachi网络也无法解决问题。仅禁用适配器(通过禁用LogMeIn Hamachi Windows服务),或者大概是卸载Hamachi,才为我解决了该问题。

是否可以要求HttpWebRequest通过特定的网络适配器出去?



0

对我来说,HttpWebRequest用于本地调用API的平均时间为40ms,而在服务器上调用API的平均时间为270ms。但是在两种环境下,通过Postman呼叫它们的平均时间为40ms。这个线程中的任何解决方案都对我没有任何影响。

然后我发现这篇文章提到了Nagle算法:

Nagle算法通过减少跨网络发送的数据包数量来提高网络效率。它通过在将少量数据写入网络时在客户端上设置最多200毫秒延迟来实现此目的。延迟是可能要写入其他数据的等待时间。新数据将添加到同一数据包。

设置ServicePoint.UseNagleAlgorithmfalse我所需的魔术,它产生了巨大的变化,并且服务器上的性能现在几乎与本地性能相同。

var webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Method = "POST";
webRequest.ServicePoint.Expect100Continue = false;
webRequest.ServicePoint.UseNagleAlgorithm = false; // <<<this is the important bit

请注意,这对我来说只处理少量数据,但是,如果您的请求涉及大数据,则可能有必要根据请求的大小/响应的预期大小将此条件设为条件标记。


0

就我而言,添加AspxAutoDetectCookieSupport=1到代码中,问题就解决了

Uri target = new Uri("http://payroll");

string responseContent;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(target);

request.CookieContainer = new CookieContainer();         
request.CookieContainer.Add(new Cookie("AspxAutoDetectCookieSupport", "1") { Domain = target.Host });

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
    using (Stream responseStream = response.GetResponseStream())
    {
        using (StreamReader sr = new StreamReader(responseStream))
            responseContent = sr.ReadToEnd();
    }
}

-1

我们在网络应用上遇到了同样的问题。我们等待响应5秒。当我们将IIS上的applicationPool上的用户更改为networkService时,响应开始不到1秒

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.