【问题标题】:System.Net.WebClient unreasonably slowSystem.Net.WebClient 异常缓慢
【发布时间】:2011-05-23 20:39:27
【问题描述】:

使用System.Net.WebClient.DownloadData() 方法时,我的响应时间过慢。

在 .NET 中使用 WebClient 类获取 url 时,大约需要 10 秒才能得到响应,而我的浏览器在 1 秒内获取相同的页面。 这适用于大小为 0.5kB 或更小的数据。

请求涉及 POST/GET 参数和用户代理标头,如果这可能会导致问题。

如果在 .NET 中下载数据的其他方法是否会给我带来同样的问题,我还没有(还)尝试过,但我怀疑我可能会得到类似的结果。 (我一直觉得 .NET 中的 Web 请求异常缓慢……)

这可能是什么原因?

编辑:
我尝试使用System.Net.HttpWebRequest 代替,使用以下方法,所有请求都在 1 秒内完成。

public static string DownloadText(string url)
        var request = (HttpWebRequest)WebRequest.Create(url);
        var response = (HttpWebResponse)request.GetResponse();

        using (var reader = new StreamReader(response.GetResponseStream()))
        {
            return reader.ReadToEnd();
        }
}


虽然这种使用 System.Net.WebClient 的(旧)方法需要 15-30 秒才能完成每个请求:

public static string DownloadText(string url)
{
       var client = new WebClient();
       byte[] data = client.DownloadData(url);
       return client.Encoding.GetString(data);
}

【问题讨论】:

标签: c# .net performance http


【解决方案1】:

在此处下载 Wireshark http://www.wireshark.org/

捕获网络数据包并过滤“http”数据包。 它应该马上给你答案。

【讨论】:

  • wireshark 上没有出现任何奇怪的情况,但是通过跟踪打印,我可以看到 WebClient.DownloadData() 被调用,并且 GET 请求直到大约 10-30 秒后才出现在 wireshark 上(取决于“冻结“ 时间)。看起来拖慢它的不是请求本身,而是在实际 GET 请求之前完成的事情。
  • 您的客户似乎正在等待某事的超时。大多数时候,它正在等待 DNS 超时或 NetBIOS 超时。您可以尝试过滤掉 DNS 数据包和 NetBIOS 数据包。或者,您可以尝试按源 IP 地址进行过滤。这应该告诉您客户端在 GET 请求之前发送的最后一个数据包是什么。也许,@Broken Pipe 是对的。它可能正在等待代理。
【解决方案2】:

.NET Web 请求本身并不慢;该代码应该没问题。我经常使用WebClient,效果非常好。

每个方向的有效载荷有多大?可能是个愚蠢的问题,但这仅仅是带宽限制吗?

IMO 最有可能的情况是您的网站已停止运行,当您点击 URL 时,该网站的响应速度很慢。那么这不是客户的错。也有可能是由于某种原因 DNS 很慢(在这种情况下,您可以将 IP 硬编码到“主机”文件中),或者中间的某些代理服务器很慢。

如果该网站不是您的网站,他们也有可能检测到非典型使用情况并故意注入延迟来惹恼爬虫。

我会抓住 Fiddler(一个免费、简单的网络检查器)并查看时间。

【讨论】:

    【解决方案3】:

    Wireshark 的另一个替代品(也是免费的)是Microsoft Network Monitor

    【讨论】:

      【解决方案4】:

      您使用什么浏览器进行测试?

      尝试使用默认的 IE 安装。 System.Net.WebClient 使用本地 IE 设置、代理等。也许已经被破坏了?

      【讨论】:

        【解决方案5】:

        我在使用 WebRequest 时遇到了这个问题。尝试设置 Proxy = null;

            WebClient wc = new WebClient();
            wc.Proxy = null;
        

        默认情况下,WebClient,WebRequest 尝试从 IE 设置中确定要使用的代理,有时会导致在实际请求发送之前延迟 5 秒。

        这适用于所有使用 WebRequest 的类,包括带有 HTTP 绑定的 WCF 服务。 一般来说,您可以在应用程序启动时使用此静态代码:

        WebRequest.DefaultWebProxy = null;
        

        【讨论】:

        • 当我这样做时,我得到了一个巨大的速度提升。谢谢!
        • 第二个对我的情况产生了巨大的影响!这绝对是这些 WebProxies 的减慢“功能”。
        • 遇到了同样的问题,这确实提高了响应时间!
        • 也可以在配置文件中设置:msdn.microsoft.com/en-us/library/kd3cf2ex.aspx
        • 谢谢!对我来说速度翻倍。
        【解决方案6】:

        在 IE 设置(连接选项卡 - LAN 设置)中选中自动代理设置时,某些工作站上的 WebClient 可能会很慢。

        【讨论】:

          【解决方案7】:

          WebClient 下载速度极慢的另一个原因是您正在下载的目标媒体。如果它是像 USB 密钥这样的慢速设备,这会极大地影响下载速度。对于我的 HDD,我可以以 6MB/s 的速度下载到我的 USB 密钥,只有 700kb/s,即使我可以从另一个驱动器以 5MB/s 的速度将文件复制到这个 USB。 wget 显示相同的行为。这也在这里报告:

          https://superuser.com/questions/413750/why-is-downloading-over-usb-so-slow

          因此,如果这是您的情况,另一种解决方案是先下载到 HDD,然后在下载完成后将文件复制到慢速介质。

          【讨论】:

            【解决方案8】:

            设置 WebRequest.DefaultWebProxy = null;client.Proxy = null 对我没有任何作用,在 iOS 上使用 Xamarin

            我做了两件事来解决这个问题:

            我写了一个不使用 WebRequest 和 System.Net 的 downloadString 函数:

                    public static async Task<string> FnDownloadStringWithoutWebRequest(string url)
                    {
                        using (var client = new HttpClient())
                        {
                            //Define Headers
                            client.DefaultRequestHeaders.Accept.Clear();
                            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            
                            var response = await client.GetAsync(url);
            
                            if (response.IsSuccessStatusCode)
                            {
                                string responseContent = await response.Content.ReadAsStringAsync();
                                //dynamic json = Newtonsoft.Json.JsonConvert.DeserializeObject(responseContent);
                                return responseContent;
                            }
                            Logger.DefaultLogger.LogError(LogLevel.NORMAL, "GoogleLoginManager.FnDownloadString", "error fetching string, code: " + response.StatusCode);
                            return "";
                        }
                    }
            

            然而,托管 HttpClient 仍然很慢。

            其次,在 Visual Studio Community for Mac 中,右键单击解决方案中的项目 -> 选项 -> HttpClient implementation 设置为 NSUrlSession,而不是的托管

            Screenshot: Set HttpClient implementation to NSUrlSession instead of Managed

            Managed 未完全集成到 iOS 中,不支持 TLS 1.2,因此不支持在 iOS9+ 中设置为默认的 ATS 标准,请参见此处:

            https://docs.microsoft.com/en-us/xamarin/ios/app-fundamentals/ats

            通过这两项更改,字符串下载总是非常快(


            仅供参考,您还可以尝试一件事,尽管它应该不再需要

                        //var authgoogle = new OAuth2Authenticator(...);
                        //authgoogle.Completed...
            
                        if (authgoogle.IsUsingNativeUI)
                        {
                            // Step 2.1 Creating Login UI 
                            // In order to access SFSafariViewController API the cast is neccessary
                            SafariServices.SFSafariViewController c = null;
                            c = (SafariServices.SFSafariViewController)ui_object;
                            PresentViewController(c, true, null);
                        }
                        else
                        {
                            PresentViewController(ui_object, true, null);
                        }
            

            尽管根据我的经验,您可能不需要 SafariController。

            【讨论】:

            • 不幸的是在android上没有帮助
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-01-19
            • 2014-08-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多