gpt4 book ai didi

c# - HttpWebResponse 不会针对并发出站请求进行扩展

转载 作者:可可西里 更新时间:2023-11-01 08:22:02 27 4
gpt4 key购买 nike

我有一个用 C# 编写的 ASP.NET 3.5 服务器应用程序。它使用 HttpWebRequest 和 HttpWebResponse 向 REST API 发出出站请求。

我已经设置了一个测试应用程序来在单独的线程上发送这些请求(以模糊地模拟针对服务器的并发)。

请注意,这更像是一个单声道/环境问题,而不是代码问题;所以请记住下面的代码不是逐字的;只是功能位的剪切/粘贴。

这是一些伪代码:

// threaded client piece
int numThreads = 1;
ManualResetEvent doneEvent;

using (doneEvent = new ManualResetEvent(false))
{

for (int i = 0; i < numThreads; i++)
{

ThreadPool.QueueUserWorkItem(new WaitCallback(Test), random_url_to_same_host);

}
doneEvent.WaitOne();
}

void Test(object some_url)
{
// setup service point here just to show what config settings Im using
ServicePoint lgsp = ServicePointManager.FindServicePoint(new Uri(some_url.ToString()));

// set these to optimal for MONO and .NET
lgsp.Expect100Continue = false;
lgsp.ConnectionLimit = 100;
lgsp.UseNagleAlgorithm = true;
lgsp.MaxIdleTime = 100000;

_request = (HttpWebRequest)WebRequest.Create(some_url);


using (HttpWebResponse _response = (HttpWebResponse)_request.GetResponse())
{
// do stuff
} // releases the response object

// close out threading stuff

if (Interlocked.Decrement(ref numThreads) == 0)
{
doneEvent.Set();
}
}

如果我在本地开发机器 (Windows 7) 的 Visual Studio Web 服务器上运行应用程序,我可以增加 numThreads 并接收相同的平均响应时间,无论是 1 个“用户”还是 100 个,变化都很小。

在 Mono 2.10.2 环境中将应用程序发布和部署到 Apache2,响应时间几乎呈线性增长。 (即,1 个线程 = 300 毫秒,5 个线程 = 1500 毫秒,10 个线程 = 3000 毫秒)。无论服务器端点如何(不同的主机名、不同的网络等),都会发生这种情况。

使用 IPTRAF(和其他网络工具),应用程序似乎只打开 1 或 2 个端口来路由所有连接,其余响应必须等待。

我们构建了一个类似的 PHP 应用程序,并在 Mono 中部署了相同的请求和相应的响应。

我已经遍历了我能想到的针对 Mono 和 Apache 的每一个配置设置,两种环境之间唯一不同的设置(至少在代码中)是有时 ServicePoint SupportsPipelining=false 在 Mono 中,而它是从我的机器上看是真的。

由于某种原因,似乎 ConnectionLimit(默认值为 2)没有在 Mono 中更改,但我在代码和指定主机的 web.config 中将其设置为更高的值。

要么我和我的团队忽略了一些重要的事情,要么这是 Mono 中的某种错误。

最佳答案

我相信您在 HttpWebRequest 中遇到了瓶颈。每个 Web 请求都使用 .NET 框架内的公共(public)服务点基础结构。这似乎是为了允许重复使用对同一主机的请求,但根据我的经验,这会导致两个瓶颈。

首先,为了符合 HTTP 规范,服务点默认只允许两个到给定主机的并发连接。这可以通过将静态属性 ServicePointManager.DefaultConnectionLimit 设置为更高的值来覆盖。看这个MSDN页面了解更多详情。看起来您已经在为单个服务点本身解决这个问题,但由于服务点级别的并发锁定方案,这样做可能会导致瓶颈。

其次,ServicePoint 类本身似乎存在锁定粒度问题。如果反编译并查看 lock 关键字的源代码,您会发现它使用实例本身进行同步,并且在很多地方都是这样做的。随着服务点实例在给定主机的 Web 请求之间共享,根据我的经验,随着打开更多 HttpWebRequests 并导致其扩展性很差,这往往会成为瓶颈。第二点主要是个人观察和源头探索,所以要持保留态度;我不认为它是权威来源。

不幸的是,我在使用它时没有找到合理的替代品。既然已经发布了 ASP.NET Web API,您不妨给 HttpClient看看。希望对您有所帮助。

关于c# - HttpWebResponse 不会针对并发出站请求进行扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9997143/

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