【问题标题】:How to determine concurrent HTTP request bottleneck in .NET?如何确定 .NET 中的并发 HTTP 请求瓶颈?
【发布时间】:2015-12-28 07:06:39
【问题描述】:

我正在尝试make as many HTTP requests to a URL as possible, as quickly as possible

我正在使用此代码来限制最大并行度,因此我不会通过一次生成大量 Tasks 来溢出内存。

    public static Task ForEachAsync<T>(this IEnumerable<T> source, int dop, Func<T, Task> body)
    {
        return Task.WhenAll(
            from partition in Partitioner.Create(source).GetPartitions(dop)
            select Task.Run(async delegate {
                using (partition)
                    while (partition.MoveNext())
                        await body(partition.Current);
            }));
    }

这似乎工作正常。

body() 基本上归结为:

async Task Body()
{
    var r = WebRequest.Create("// the url");
    await r.GetResponseAsync();
}

但是,我似乎在某个地方遇到了瓶颈。如果我尝试使用 dop 的不同值进行 2500 迭代,我会得到以下结果:

DOP: 50
Total Time: 00:00:14.4801781
Average (ms): 246.6088
StDev: 84.1327983759009

DOP: 75
Total Time: 00:00:09.8089530
Average (ms): 265.758
StDev: 110.22912244956

DOP: 100
Total Time: 00:00:11.9899793
Average (ms): 344.9168
StDev: 173.281468939295

DOP: 200
Total Time: 00:00:09.1512825
Average (ms): 627.0492
StDev: 572.616238312676

DOP: 500
Total Time: 00:00:09.3556978
Average (ms): 1361.5328
StDev: 1798.70589239157

DOP: 750
Total Time: 00:00:12.6076035
Average (ms): 2009.058
Normal Total: 5022646
StDev: 2348.20874093199


DOP: 1000
Total Time: 00:00:11.4721195
Average (ms): 2453.782
StDev: 2481.56238190299

DOP: 2000
Total: 00:00:11.6039888
Average (ms): 4100.5536
StDev: 2459.36983911063

这似乎表明dop=50 小于瓶颈。但是,当您超过dop~=100 时,您会注意到每个请求所花费的Average 时间(这是Func&lt;T, Task&gt; body 运行2500 次所需的平均时间)与DOP 几乎呈线性增长(有点诚然,这些结果中的噪音,但它们是可重复的,误差很小)。

这表明body 正在做的工作中有一个“队列”,对吧?

我已经设置好了

ServicePointManager.DefaultConnectionLimit = int.MaxValue;

如果我这样做了

servicePoint = ServicePointManager.FindServicePoint("// the url", null);

和监控

servicePoint.CurrentConnections 

在每次执行body 时,它总是等于dop(除了初始加速和减速)。

我已经从各种网络尝试过这个,所以它不太可能是基于硬件的,它不应该是远程服务器,因为它是为大量入站负载而设计的(并不是说我所说的数字甚至很重)

如何更好地描述我正在做的事情?

【问题讨论】:

  • 这里有很多可能性,但我的第一个猜测是你达到了 Windows 并发连接限制。另一种可能性是服务器的硬件将您的连接视为潜在的 DOS 攻击并对其进行限制。
  • 平均是什么?每个请求还是总数?发布测量代码。
  • @usr 平均执行时间body 2500 次,我把问题说清楚了
  • @CollinDauphinee 您能否对 Windows 设置发表更多评论?不应该是服务器,它的设计是用来锤的
  • @AndrewBullock:Windows 对并发连接有限制,我相信它默认为 1000。它有一个注册表设置,但我无法立即找到它。

标签: c# .net httprequest


【解决方案1】:

完成所有工作级别的总时间在 9 到 11 秒之间。这是有道理的,因为当增加 DOP(以指数方式)时,您最终会使后端资源或网络或其他东西饱和。

我敢打赌,如果您发布的 DOP 基准数字较低,我们会看到更高的总时间。

当您此时将并发请求数加倍时,平均完成时间会加倍。

查看以每秒项目数或总时间衡量的吞吐量。这是一个有趣的指标。每项延迟不是。

【讨论】:

  • 是的,为了简洁起见,我做了很多测试并剪掉了结果。如您所料,
  • 你能发布所有用来衡量这个的代码吗?有点不清楚这些数字代表什么。另外,您能说一下您期望的结果吗?
  • 这是我的代码,它使用 AWS SES 服务(我可以向它发送 1000/s 请求 - 之后我应该看到节流)gist.github.com/trullock/a112885d374a081aee4d
  • 代码看起来不错。线程池配置不应该做任何事情,因为异步 IO 不使用线程,并且并行 foreach 也不使用任何线程。由于根据服务点有预期的连接数,它看起来就像 SES 节流(或网络饱和)。您可以通过对不受限制的 Web 请求和服务器执行相同的操作来测试这一点。例如,试试 google.com 或 example.org。
  • 一个调用2.2ms左右对吗?这似乎非常快......可疑。互联网往返时间应该更高。就像家庭连接需要 10-30 毫秒。尝试关闭 HTTP 管道并确保使用 netstat(或其他任何东西)同时打开 DOP TCP 连接。
猜你喜欢
  • 2015-06-12
  • 1970-01-01
  • 1970-01-01
  • 2010-11-04
  • 1970-01-01
  • 2021-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多