无法实现ASP.NET

时间:2016-11-02 00:25:14

标签: asp.net concurrency

最初尝试创建一个长时间保持打开的HTTP端点(直到远程服务执行并完成,然后将结果返回给原始调用者),我遇到了一些并发问题:这个端点只会执行一个小的同时发生的次数(大约10次左右,而我预计会有数百次)。

然后我将我的代码缩小到一个测试端点,该端点仅在通过URL提供一定数量的MS之后返回。理论上,此方法应该提供最大的并发性,但在Windows 10桌面PC上的IIS下运行或在Windows 2012 Server 上运行时,它都不会发生

这是测试Web API端点:

[Route("throughput/raw")]
[HttpGet]
public async Task<IHttpActionResult> TestThroughput(int delay = 0)
{
    await Task.Delay(delay);
    return Ok();
}

这是一个简单的测试应用程序:

class Program
{
    static readonly HttpClient HttpClient = new HttpClient();
    static readonly ConcurrentBag<long> Stats = new ConcurrentBag<long>();
    private static Process _currentProcess;

    private static string url = "http://local.api/test/throughput/raw?delay=0";

    static void Main()
    {
        // Warm up
        var dummy = HttpClient.GetAsync(url).Result;
        Console.WriteLine("Warm up finished.");
        Thread.Sleep(500);

        // Get current process for later
        _currentProcess = Process.GetCurrentProcess();

        for (var i = 1; i <= 100; i++)
        {
            Thread t = new Thread(Proc);
            t.Start();
        }

        Console.ReadKey();
        Console.WriteLine($"Total requests: {Stats.Count}\r\nAverage time: {Stats.Average()}ms");
        Console.ReadKey();
    }

    static async void Proc()
    {
        Stopwatch sw = Stopwatch.StartNew();
        sw.Start();
        await HttpClient.GetAsync(url);
        sw.Stop();
        Stats.Add(sw.ElapsedMilliseconds);
        Console.WriteLine($"Thread finished at {sw.ElapsedMilliseconds}ms. Total threads running: {_currentProcess.Threads.Count}");
    }
}

我得到的结果是:

Warm up finished.
Thread finished at 118ms. Total threads running: 32
Thread finished at 114ms. Total threads running: 32
Thread finished at 130ms. Total threads running: 32
Thread finished at 110ms. Total threads running: 32
Thread finished at 115ms. Total threads running: 32
Thread finished at 117ms. Total threads running: 32
Thread finished at 119ms. Total threads running: 32
Thread finished at 112ms. Total threads running: 32
Thread finished at 163ms. Total threads running: 32
Thread finished at 134ms. Total threads running: 32
...
...
Some more
...
...
Thread finished at 4511ms. Total threads running: 32
Thread finished at 4504ms. Total threads running: 32
Thread finished at 4500ms. Total threads running: 32
Thread finished at 4507ms. Total threads running: 32
Thread finished at 4504ms. Total threads running: 32
Thread finished at 4515ms. Total threads running: 32
Thread finished at 4502ms. Total threads running: 32
Thread finished at 4528ms. Total threads running: 32
Thread finished at 4538ms. Total threads running: 32
Thread finished at 4535ms. Total threads running: 32

所以:

  1. 我不确定为什么只有32个线程在运行(我认为它与我机器上的内核数量有关,虽然有时这个数字是34,但无论如何它应该更多我想)。

  2. 我试图解决的主要问题:随着更多来电的创建,运行时间会增加,而我希望它保持相对稳定。< / p>

  3. 我在这里缺少什么?我希望在Windows服务器上运行一个ASP.NET站点(在这种情况下是API,但这并不重要)(所以没有应用人工并发限制)处理所有这些并发请求就好并且不会增加响应时间。我相信响应时间会增加,因为线程在服务器端上限,因此后续HTTP调用等待轮到他们。我还希望在客户端(测试)应用程序上运行超过32/34个线程。

    我也尝试调整machine.config但没有太大的成功,但我认为即使是默认值也应该提供更多的吞吐量。

1 个答案:

答案 0 :(得分:2)

HTTP客户端

同时HttpClient连接的数量受ServicePointManager的限制。如果您相信this article,则默认为2. TWO !!所以你的请求排队了。您可以通过设置DefaultConnectionLimit来增加号码。

线程

编辑OP:虽然事实上对于线程池是正确的,但我的问题不涉及线程池的使用。我将此留在这里,以备将来参考(使用与问题中所示的用法略有不同)以及给出此答案的人。

默认线程池中有最大线程数。默认值未预设;它取决于可用的内存量和其他因素,并且显然在您的计算机上为32。请参阅this article,其中说明:

  

从.NET Framework 4开始,进程的线程池的默认大小取决于多个因素,例如虚拟地址空间的大小。进程可以调用GetMaxThreads方法来确定线程数。

您当然可以change it