HttpWebResponse不会规模并发出站请求 [英] HttpWebResponse won't scale for concurrent outbound requests

查看:150
本文介绍了HttpWebResponse不会规模并发出站请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an ASP.NET 3.5 server application written in C#. It makes outbound requests to a REST API using HttpWebRequest and HttpWebResponse.

我已经建立了测试应用程序发送单独的线程上这些请求(隐约模拟并发针对服务器)。

I have setup a test application to send these requests on separate threads (to vaguely mimic concurrency against the server).

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

Please note this is more of a Mono/Environment question than a code question; so please keep in mind that the code below is not verbatim; just a cut/paste of the functional bits.

下面是一些伪code:

Here is some pseudo-code:

// 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();
    }
}

如果我在Visual Studio的Web服务器我的本地开发机器(Windows 7)中运行的应用程序,我可以起来numThreads和接收相同的平均响应时间的变化很小,无论是1用户或100。

If I run the application on my local development machine (Windows 7) in the Visual Studio web server, I can up the numThreads and receive the same avg response time with minimal variation whether it's 1 "user" or 100.

出版并在单2.10.2环境中部署应用程序的Apache2,响应时间规模几乎呈线性。 (即,1个线程= 300毫秒,5线程= 1500毫秒,10个线程= 3000ms)。这发生服务器端点(不同的主机名,不同的网络,等等)无关。

Publishing and deploying the application to Apache2 on a Mono 2.10.2 environment, the response times scale almost linearly. (i.e, 1 thread = 300ms, 5 thread = 1500ms, 10 threads = 3000ms). This happens regardless of server endpoint (different hostname, different network, etc).

使用IPTRAF(以及其他网络工具),它看起来好像应用程序只开1或2个端口借道所有连接,其余的答复要等待。

Using IPTRAF (and other network tools), it appears as though the application only opens 1 or 2 ports to route all connections through and the remaining responses have to wait.

我们已经建立了一个类似的PHP应用程序和相同的要求部署在单声道和响应规模适当。

We have built a similar PHP application and deployed in Mono with the same requests and the responses scale appropriately.

我走过的每一个配置设置,我可以为单声道和Apache和唯一的设置,在这两种环境之间的不同(至少在code)认为运行时,有时的ServicePoint SupportsPipelining =单声道假的,虽然这是事实,从我的机器。

I have run through every single configuration setting I can think of for Mono and Apache and the ONLY setting that is different between the two environments (at least in code) is that sometimes the ServicePoint SupportsPipelining=false in Mono, while it is true from my machine.

这好像在ConnectionLimit(2缺省值)未在单声道改变出于某种原因,但我将它设置为在code更高的价值,并都对指定的主机的web.config文件(S)

It seems as though the ConnectionLimit (default of 2) is not being changed in Mono for some reason but I am setting it to a higher value both in code and the web.config for the specified host(s).

无论是我和我的团队正在忽视的东西显著或者这是单声道某种错误的。

Either me and my team are overlooking something significant or this is some sort of bug in Mono.

推荐答案

我相信,你打在的HttpWebRequest 的瓶颈。该网站要求各使用.NET框架内共同服务点的基础设施。这似乎是旨在使请求到同一主机被重用,但在我的经验,结果两个瓶颈。

I believe that you're hitting a bottleneck in the HttpWebRequest. The web requests each use a common service point infrastructure within the .NET framework. This appears to be intended to allow requests to the same host to be reused, but in my experience results in two bottlenecks.

第一,服务点允许以默认给定主机只有两个并发连接都符合HTTP规范。这可以通过静态属性 ServicePointManager.DefaultConnectionLimit 设置为更高的值覆盖。看到这个<一个href=\"http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.defaultconnectionlimit.aspx\">MSDN更多详细信息页面。它看起来好像你已经解决这个为个人服务点本身,而是由于在服务点水平并发锁定方案,这样做可能是导致瓶颈。

First, the service points allow only two concurrent connections to a given host by default in order to be compliant to the HTTP specification. This can be overridden by setting the static property ServicePointManager.DefaultConnectionLimit to a higher value. See this MSDN page for more details. It looks as if you're already addressing this for the individual service point itself, but due to the concurrency locking scheme at the service point level, doing so may be contributing to the bottleneck.

第二,似乎与在的ServicePoint 类本身锁的粒度的问题。如果你反编译,并期待在源的锁定关键字,你会发现它使用实例自身同步,在许多地方这样做。随着服务点实例被给定主机的Web请求之间共享,在我的经验,这往往是瓶颈多个 HttpWebRequests 打开,导致其不良规模。这第二点主要是个人的观察和周围的源戳,所以把它当作一粒盐;我不认为这是一个权威的来源。

Second, there appears to be an issue with lock granularity in the ServicePoint class itself. If you decompile and look at the source for the lock keyword, you'll find that it uses the instance itself to synchronize and does so in many places. With the service point instance being shared among web requests for a given host, in my experience this tends to bottleneck as more HttpWebRequests are opened and causes it to scale poorly. This second point is mostly personal observation and poking around the source, so take it with a grain of salt; I wouldn't consider it an authoritative source.

不幸的是,我没有找到我与它的工作时间合理的替代品。现在,的ASP.NET Web API已经发布,你不妨给 HttpClient的一起来看看。希望有所帮助。

Unfortunately, I did not find a reasonable substitute at the time that I was working with it. Now that the ASP.NET Web API has been released, you may wish to give the HttpClient a look. Hope that helps.

这篇关于HttpWebResponse不会规模并发出站请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆