【问题标题】:Performance testing API - WebClient.DownloadData async issue性能测试 API - WebClient.DownloadData 异步问题
【发布时间】:2013-10-01 01:28:53
【问题描述】:

我正忙于通过并行、同时调用加载公共 API 来对其进行性能测试。代码如下。

int batchSize = 10;

ParallelOptions parallelOptions = new ParallelOptions();
parallelOptions.MaxDegreeOfParallelism = batchSize;

Parallel.For(0, batchSize, parallelOptions, j =>
{
    Debug.WriteLine("Thread began at " + DateTime.Now.ToLongTimeString());

    using (WebClient client = new WebClient())
    {
        Stopwatch sw = Stopwatch.StartNew();
        byte[] arr = client.DownloadData("http://myapiurl/webservice.svc");
        sw.Stop();

        Console.WriteLine(sw.ElapsedMilliseconds.ToString());
    }
});

但我得到了奇怪的结果:

  • 从调试输出中,我可以看到所有线程都在完全相同的时间启动(如预期的那样)。

  • 我还记录了从 Web 服务中处理 API 调用所花费的时间(存储在日志表中)。每次通话的时间都差不多……大约 2.5 秒。

  • 但现在控制台输出不相关。我希望它只比网络服务记录的时间长一点。输出:

2883 
2914 
5653 
5822 
8000 
8250 
10215 
10539 
11622 
12494

我可以想出以下可能的原因:

  • 就好像WebClient.DownloadData 正在将我的请求在其自身的实例中排队。

  • IIS 正在排队我的 Web 请求。这是不可能的,因为 API 没有其他任何东西。

【问题讨论】:

    标签: c# .net performance task-parallel-library performance-testing


    【解决方案1】:

    所有 HTTP 请求都由 ServicePointManager 管理,它管理与各种主机的连接池。每个主机的并发连接(以及 HTTP 请求)存在限制。这可以通过调用来增加:

    ServicePointManager.FindServicePoint("http://myapiurl/webservice.svc")
        .ConnectionLimit = 100; //arbitrary value
    

    还值得记住的是,HttpWebRequest 的 .Net 实现(这是 WebClient 使用的)永远不可能真正异步,因为 DNS 查找在异步发出请求之前同步发生。我一直认为这是一个完全迟钝的设计决定,它会阻止高性能的 http 请求(尤其是在蜘蛛/爬行场景中)。

    【讨论】:

    • 请注意,ConnectionLimit 的默认值仅为 2,因为这是 HTTP RFC 推荐的值。您可以通过设置ServicePointManager.DefaultConnectionLimit 来更改默认值(但您必须在与该服务点建立任何连接之前执行此操作)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-06
    • 2016-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多