C# HttpWebResponse赢得';并发出站请求的t scale

C# HttpWebResponse赢得';并发出站请求的t scale,c#,apache,mono,httpwebresponse,servicepoint,C#,Apache,Mono,Httpwebresponse,Servicepoint,我有一个用C#编写的ASP.NET 3.5服务器应用程序。它使用HttpWebRequest和HttpWebResponse向RESTAPI发出出站请求 我已经设置了一个测试应用程序,在不同的线程上发送这些请求(模糊地模拟服务器的并发性) 请注意,这更多的是一个单声道/环境问题,而不是一个代码问题;所以请记住下面的代码不是一字不差的;只是功能位的剪切/粘贴 下面是一些伪代码: // threaded client piece int numThreads = 1; ManualResetEven

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

我已经设置了一个测试应用程序,在不同的线程上发送这些请求(模糊地模拟服务器的并发性)

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

下面是一些伪代码:

// 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();
    }
}
//线程化客户端
int numThreads=1;
手动重置事件不发生事件;
使用(doneEvent=new ManualResetEvent(假))
{
for(int i=0;i
如果我在Visual Studio web服务器的本地开发机器(Windows 7)上运行该应用程序,我可以启动numThreads并接收相同的平均响应时间,无论是1“user”还是100

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

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

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

我已经为Mono和Apache运行了我能想到的每一个配置设置,这两个环境之间唯一不同的设置(至少在代码中)是,有时候在Mono中ServicePoint SupportSpipeling=false,而在我的机器上则是true

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


要么我和我的团队忽略了一些重要的东西,要么这是Mono中的某种缺陷。

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

首先,默认情况下,服务点只允许到给定主机的两个并发连接,以符合HTTP规范。可以通过将静态属性
ServicePointManager.DefaultConnectionLimit
设置为更高的值来覆盖此设置。有关更多详细信息,请参阅本页。看起来您已经针对单个服务点本身解决了这个问题,但是由于服务点级别的并发锁定方案,这样做可能会造成瓶颈

其次,
ServicePoint
类本身似乎存在锁粒度问题。如果您反编译并查看
lock
关键字的源代码,您会发现它使用实例本身进行同步,并且在许多地方都这样做。在给定主机的web请求之间共享服务点实例的情况下,根据我的经验,随着更多的
HttpWebRequests
被打开,这往往会成为瓶颈,并导致其伸缩性差。第二点主要是个人观察和探源,所以对此持保留态度;我不认为它是权威的来源。< / P>
不幸的是,在我与它合作的时候,我没有找到一个合理的替代品。现在ASP.NET Web API已经发布,您可能希望看看。希望这会有所帮助。

我知道这已经很旧了,但我把它放在这里,以防它可能会帮助遇到这个问题的其他人。我们在并行出站HTTPS请求中遇到了同样的问题。有几个问题在起作用

第一个问题是,
ServicePointManager.DefaultConnectionLimit
据我所知没有更改连接限制。将其设置为50,创建一个新连接,然后检查服务点上新连接的连接限制,如2。一旦将该服务点上的值设置为50,对于最终将通过该服务点的所有连接,该值似乎都有效并保持不变

我们遇到的第二个问题是线程。单线程池的当前实现似乎每秒最多创建2个新线程。如果你在同一时间执行许多并行请求,这将是一个永恒的过程。为了解决这个问题,我们尝试将ThreadPool.SetMinThreads设置为更高的数字。无论当前线程数与所需线程数之间的增量如何,Mono在进行此调用时似乎最多只创建1个新线程。我们可以通过在循环中调用SetMinThreads来解决这个问题,直到线程池具有所需的num