gpt4 book ai didi

c# - 对同一 http 主机的多个同时请求

转载 作者:可可西里 更新时间:2023-11-01 16:21:27 33 4
gpt4 key购买 nike

我有一个 C# 桌面应用程序,它需要同时向同一个 Web 服务器发出多个 http 请求。这是我为检查我的请求是否确实同时发生而执行的测试:

  1. 在网络服务器上,创建了一个休眠 3 秒的测试页面(模拟一些长时间运行的任务),然后返回当前日期/时间。这是代码 (VB.Net):

    <%system.threading.thread.sleep(3000)%><%=现在%>

  2. 在 C# 应用程序中,我有一个函数 MakeRequest(),它使用 System.Net.Http.HttpClient 发出 Web 请求,并以字符串形式返回响应。

  3. 然后在 C# 应用程序中有一个通过单击按钮调用的函数,它异步调用 MakeRequest() 多次:

    var responses = await Task.WhenAll(MakeRequest(), MakeRequest(), MakeRequest());

在上面的例子中,MakeRequest() 被调用了 3 次。当我监视 Requests/sec 性能计数器时,我在 Web 服务器上看到的是它收到 2 个请求,然后 3 秒后又收到 1 个请求。这是设计使然,因为 System.Net.ServicePointManager.DefaultConnectionLimit 的默认值为 2,所以我的 C# 应用一次只能发送 2 个请求,尽管我要求发送 3 个请求。C# 应用完成按钮点击的总时间是6 秒。

现在在 C# 应用程序中,我设置 ServicePointManager.DefaultConnectionLimit = 1000000。这次 Web 服务器上的 Requests/sec 显示 3,C# 应用程序中的按钮单击在 3 秒内完成。到目前为止一切都很好。

接下来,我更改 C# 应用程序以进行 60 个同时调用,而不是 3 个。这就是事情变得有趣的地方。当我单击按钮时,我希望看到 Web 服务器上的每秒请求数激增至 60,并且 C# 应用程序在 3 秒内完成按钮单击。相反,我得到的是 Web 服务器请求/秒显示类似 5,3 秒后 5 等,直到所有 60 个请求都已发出。当我再次单击该按钮时,相同的图片除了 Requests/sec 飙升至 10 或 15 之外,并且按钮单击显然完成得更快。再次单击 - 这次 Requests/sec 显示两个峰值到 30,按钮单击在 6 秒内完成。随后的按钮单击导致 Requests/sec 首先上升到 40,然后上升到 20(总共 60 个请求),然后是 50 和 10,然后可能是 55 和 5,最终我的 C# 应用程序开始一次性发送所有 60 个请求。按钮点击在 3 秒内完成,网络服务器上的请求/秒显示一个峰值到 60。如果我继续按下按钮,我始终会同时发出所有 60 个请求。

但这还不是全部。如果我停止按下按钮,我的 C# 应用程序似乎会“忘记”它之前的成就。我没有重新启动应用程序,只是停止按下按钮一分钟,在下一次按下时我又回到一次 5 个请求,如果我继续连续按下按钮,上述情况会重复。

我还从 MVC 执行了上述测试 - 只是将代码从 C# 应用程序复制并粘贴到 MVC 页面。得到完全相同的结果。

谁能解释一下这是怎么回事?谢谢


这是 C# 应用程序的代码。这是一个 WinForms 应用程序,代码位于 Form 类中:

<!-- language: lang-c# -->
private HttpClient _httpClient = new HttpClient();

private async void button1_Click(object sender, EventArgs e)
{
ServicePointManager.DefaultConnectionLimit = 1000000;

var sw = Stopwatch.StartNew();
var responses = await Task.WhenAll(MakeRequest(), MakeRequest(), MakeRequest());
sw.Stop();

var msg = String.Join("\r\n", responses) + "\r\n\r\nTime Elapsed: " + sw.ElapsedMilliseconds;
MessageBox.Show(msg);
}

private async Task<string> MakeRequest()
{
using (var message = await _httpClient.GetAsync("http://TestServer/TestPage.aspx"))
{
return await message.Content.ReadAsStringAsync();
}
}

最佳答案

两个原因:

  1. 客户端 Windows SKU 将并发 IIS 请求的数量限制为 10。
  2. 显然,您的客户端使用同步 IO 或以其他方式阻塞。线程池预热需要一段时间。线程仅随时间注入(inject)。要么使用异步 IO 并且是非阻塞的,要么确保你需要的线程确实存在。关于“遗忘”:空闲池线程会随着时间的推移而退役。因此,您的测试对时间敏感。非常不可靠,不要将其投入生产。

关于c# - 对同一 http 主机的多个同时请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32918973/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com