【问题标题】:UploadValuesAsync response timeUploadValuesAsync 响应时间
【发布时间】:2011-11-03 18:32:41
【问题描述】:

我正在编写测试工具来测试 HTTP Post。测试用例将在 10 秒间隔内使用 Webclient 类中的 UploadValuesAsync 发送 8 个 http 请求。每 8 个请求后它会休眠 10 秒。我正在记录每个请求的开始时间和结束时间。当我计算平均响应时间时。我得到了大约 800 毫秒。但是当我在 Web 客户端中使用 UploadValues 方法同步运行这个测试用例时,我得到的平均响应时间为 250 毫秒。你能告诉我为什么这两种方法有区别吗?我期待 Aync 中的响应时间更短,但我没有得到。

这是异步发送 8 个请求的代码

                       var count = 0;
        foreach (var nameValueCollection in requestCollections)
        {
            count++;
            NameValueCollection collection = nameValueCollection;
            PostToURL(collection,uri);
            if (count % 8 == 0)
            {
                Thread.Sleep(TimeSpan.FromSeconds(10));
                count = 0;
            }
        }

更新 这是发送 8 个同步请求的代码

public void PostToURLSync(NameValueCollection collection,Uri uri)
    {
        var response = new ServiceResponse
        {
            Response = "Not Started",
            Request = string.Join(";", collection.Cast<string>()
                                        .Select(col => String.Concat(col, "=", collection[col])).ToArray()),
            ApplicationId = collection["ApplicationId"]

        };

        try
        {
            using (var transportType2 = new DerivedWebClient())
            {
                transportType2.Expect100Continue = false;
                transportType2.Timeout = TimeSpan.FromMilliseconds(2000);
                response.StartTime = DateTime.Now;
                var responeByte = transportType2.UploadValues(uri, "POST", collection);
                response.EndTime = DateTime.Now;
                response.Response = Encoding.Default.GetString(responeByte);
            }

        }
        catch (Exception exception)
        {
            Console.WriteLine(exception.ToString());
        }
        response.ResponseInMs = (int)response.EndTime.Subtract(response.StartTime).TotalMilliseconds;
        responses.Add(response);
        Console.WriteLine(response.ResponseInMs);
    }

这是发布到 HTTP URI 的代码

public void PostToURL(NameValueCollection collection,Uri uri)
    {
        var response = new ServiceResponse
                        {
                            Response = "Not Started",
                            Request = string.Join(";", collection.Cast<string>()
                                                        .Select(col => String.Concat(col, "=", collection[col])).ToArray()),
                            ApplicationId = collection["ApplicationId"]

                        };

        try
        {
            using (var transportType2 = new DerivedWebClient())
            {
                transportType2.Expect100Continue = false;
                transportType2.Timeout = TimeSpan.FromMilliseconds(2000);
                response.StartTime = DateTime.Now;
                transportType2.UploadValuesCompleted += new UploadValuesCompletedEventHandler(transportType2_UploadValuesCompleted);
                transportType2.UploadValuesAsync(uri, "POST", collection,response);
            }
        }
        catch (Exception exception)
        {
            Console.WriteLine(exception.ToString());
        }
    }

这里是上传完成事件

    private void transportType2_UploadValuesCompleted(object sender, UploadValuesCompletedEventArgs e)
    {
        var now = DateTime.Now;
        var response = (ServiceResponse)e.UserState;
        response.EndTime = now;
        response.ResponseInMs = (int) response.EndTime.Subtract(response.StartTime).TotalMilliseconds;
        Console.WriteLine(response.ResponseInMs);

        if (e.Error != null)
        {
            response.Response = e.Error.ToString();
        }
        else
        if (e.Result != null && e.Result.Length > 0)
        {
            string downloadedData = Encoding.Default.GetString(e.Result);
            response.Response = downloadedData;
        }
        //Recording response in Global variable
        responses.Add(response);
    }

【问题讨论】:

  • 您要发送的收藏有多大?是不是在使用异步时,您并行发送所有请求,但同步版本一个接一个地发送请求?您也可以发布您的同步代码吗?
  • 我正在测试的 @svick 集合包含 100 个对象。更新了同步代码。

标签: c# asynchronous webclient


【解决方案1】:

您可能遇到的一个问题是,默认情况下,.NET 会将传出的 HTTP 连接限制到相关 RFC 规定的限制(每个远程主机 2 个并发连接)。假设 2 个并发连接和每个请求 250 毫秒,这意味着您的前 2 个请求的响应时间将是 250 毫秒,第二个 2 将是 500 毫秒,第三个 750 毫秒,最后 1000 毫秒。这将产生 625 毫秒的平均响应时间,与您看到的 800 毫秒相差不远。

要消除限制,将ServicePointManager.DefaultConnectionLimit 增加到您希望支持的最大并发连接数,您应该会看到平均响应时间大大缩短。

第二个问题可能是服务器本身处理多个并发连接比一次处理一个请求要慢。即使您解除了上面的限制问题,我希望每个异步请求的平均执行速度都会比服务器一次只执行一个请求的速度慢一些。慢多少取决于服务器对并发请求的优化程度。

最后一个问题可能是由测试方法引起的。例如,如果您的测试客户端通过存储 cookie 并随每个请求重新发送 cookie 来模拟浏览器会话,则可能会在某些服务器上遇到问题,这些服务器将序列化来自单个用户的请求。这通常是对服务器应用程序的简化,因此它们不必像会话状态那样处理锁定交叉请求状态。如果您遇到此问题,请确保每个 WebClient 发送不同的 cookie 以模拟不同的用户。

我并不是说您遇到了所有这三个问题——您可能只会遇到 1 或 2 个问题——但这些是您所看到问题的最可能的罪魁祸首。

【讨论】:

    【解决方案2】:

    正如贾斯汀所说,我尝试了 ServicePointManager.DefaultConnectionLimit 但这并没有解决问题。我无法重现贾斯汀提出的其他问题。我不确定如何首先复制它们。

    我所做的是,我在对等机器上运行了相同的代码,它的响应时间完全符合我的预期。两台机器的区别在于操作系统。我的在 Windows Server 2003 上运行,其他机器在 Windows Server 2008 上运行。

    当它在其他机器上运行时,我怀疑它可能是 Justin 指定的问题之一,也可能是 2003 年的服务器设置或其他问题。之后我没有花太多时间来挖掘这个问题。因为这是一个测试工具,我们在这个问题上的优先级很低。我们没有更多时间就离开了。

    由于我没有确切地解决它的问题,因此我不接受除此之外的任何答案。因为至少我知道切换到 server 2008 解决了这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-07
      • 2020-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多